Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Safar <marek.safar@gmail.com>2009-07-02 15:50:24 +0400
committerMarek Safar <marek.safar@gmail.com>2009-07-02 15:50:24 +0400
commit340222ffe8b958cd22d9eb0388488f326845b363 (patch)
tree0f8d3a5279e30e88514d0c5ba05fb295c7bbc282 /mcs/class/dlr
parent683302613627b3c9c3bd0dc3139a3c489bfce477 (diff)
2009-07-02 Marek Safar <marek.safar@gmail.com>
* Initial import, revision 25679. svn path=/trunk/mcs/; revision=137277
Diffstat (limited to 'mcs/class/dlr')
-rw-r--r--mcs/class/dlr/License.html36
-rw-r--r--mcs/class/dlr/License.rtf177
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ArgBuilder.cs61
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Assert.cs82
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/BoolArgBuilder.cs72
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/BoundDispEvent.cs138
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/CollectionExtensions.cs55
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinder.cs441
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinderHelpers.cs138
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComDispIds.cs32
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventDesc.cs31
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSink.cs349
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinkProxy.cs148
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinksContainer.cs98
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComFallbackMetaObject.cs92
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComHresults.cs58
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInterop.cs98
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeAction.cs107
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeBinder.cs538
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMetaObject.cs87
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMethodDesc.cs120
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComObject.cs145
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComRuntimeHelpers.cs814
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeClassDesc.cs79
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeDesc.cs227
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeEnumDesc.cs50
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeLibDesc.cs109
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ContractUtils.cs57
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ConversionArgBuilder.cs63
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertArgBuilder.cs50
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertibleArgBuilder.cs50
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/CurrencyArgBuilder.cs71
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/DateTimeArgBuilder.cs71
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallable.cs85
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallableMetaObject.cs148
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/DispatchArgBuilder.cs101
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ErrorArgBuilder.cs66
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Errors.cs348
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/ExcepInfo.cs119
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Helpers.cs41
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchComObject.cs643
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchMetaObject.cs273
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Microsoft.Dynamic.csproj134
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/NullArgBuilder.cs45
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/AssemblyInfo.cs79
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/GlobalSuppressions.cs17
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/SimpleArgBuilder.cs61
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/SplatCallSite.cs67
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/StringArgBuilder.cs100
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.csproj124
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.txt72
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/TypeUtils.cs260
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/UnknownArgBuilder.cs100
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/VarEnumSelector.cs475
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Variant.cs985
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArgBuilder.cs94
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArray.cs114
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantBuilder.cs177
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BinaryOperationBinder.cs154
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BindingRestrictions.cs377
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallInfo.cs115
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSite.cs709
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteBinder.cs239
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteHelpers.cs62
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteOps.cs173
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ConvertBinder.cs111
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CreateInstanceBinder.cs97
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteIndexBinder.cs97
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteMemberBinder.cs112
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObject.cs335
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObjectBinder.cs305
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs634
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoClass.cs197
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoObject.cs1108
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetIndexBinder.cs98
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetMemberBinder.cs110
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/IDynamicMetaObjectProvider.cs44
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeBinder.cs98
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeMemberBinder.cs139
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/RuleCache.cs126
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetIndexBinder.cs107
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetMemberBinder.cs116
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UnaryOperationBinder.cs135
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UpdateDelegates.Generated.cs2665
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs2624
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BlockExpression.cs801
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/CatchBlock.cs163
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConditionalExpression.cs214
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConstantExpression.cs136
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugInfoExpression.cs247
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugViewWriter.cs1196
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DefaultExpression.cs87
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs841
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ElementInit.cs129
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.DebuggerProxy.cs462
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.cs403
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionStringBuilder.cs755
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionType.cs379
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionVisitor.cs791
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/GotoExpression.cs362
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IArgumentProvider.cs80
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IndexExpression.cs446
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/InvocationExpression.cs189
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelExpression.cs100
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelTarget.cs107
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs635
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListArgumentProvider.cs153
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListInitExpression.cs224
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LoopExpression.cs123
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberAssignment.cs98
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberBinding.cs83
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberExpression.cs352
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberInitExpression.cs171
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberListBinding.cs128
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberMemberBinding.cs142
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MethodCallExpression.cs1022
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewArrayExpression.cs227
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs321
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ParameterExpression.cs226
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/RuntimeVariablesExpression.cs111
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchCase.cs97
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchExpression.cs286
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SymbolDocumentInfo.cs158
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TryExpression.cs215
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeBinaryExpression.cs198
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeUtils.cs585
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/UnaryExpression.cs989
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AnalyzedTree.cs47
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AssemblyGen.cs184
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/BoundConstants.cs193
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Closure.cs57
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.Storage.cs191
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.cs468
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ConstantCheck.cs133
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs72
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.Generated.cs299
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs47
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ExpressionQuoter.cs253
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/HoistedLocals.cs111
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ILGen.cs1061
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/KeyedQueue.cs95
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LabelInfo.cs365
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Address.cs339
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs706
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.ControlFlow.cs263
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Expressions.cs1094
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Generated.cs288
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Lambda.cs202
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Logical.cs651
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Statements.cs824
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Unary.cs354
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.cs323
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/OffsetTrackingILGenerator.cs363
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/RuntimeVariableList.cs128
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Set.cs97
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Bindings.cs238
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Generated.cs278
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Temps.cs313
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.cs991
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/SymbolDocumentGenerator.cs76
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/VariableBinder.cs246
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/GlobalSuppressions.cs28
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.Core.csproj248
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.ExtensionAttribute.csproj104
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/AssemblyInfo.cs73
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/ExtensionAssemblyInfo.cs69
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Stubs.cs213
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/System.Core.csproj253
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Action.cs654
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CacheDict.cs121
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CollectionExtensions.cs193
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ContractUtils.cs107
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ExceptionFactory.Generated.cs2524
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Extension.cs14
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Function.cs711
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Helpers.cs57
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/IRuntimeVariables.cs39
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyCollectionBuilder.cs525
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyDictionary.cs205
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReferenceEqualityComparer.cs43
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/StrongBox.cs69
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TrueReadOnlyCollection.cs40
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs128
183 files changed, 52759 insertions, 0 deletions
diff --git a/mcs/class/dlr/License.html b/mcs/class/dlr/License.html
new file mode 100644
index 00000000000..42a1b7aed46
--- /dev/null
+++ b/mcs/class/dlr/License.html
@@ -0,0 +1,36 @@
+<html>
+
+<head>
+<title>Microsoft Public License (Ms-PL)</title>
+</head>
+
+<body>
+
+<p><b>This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.</b></p>
+
+<h2>1. Definitions</h2>
+<p>The terms &#8220;reproduce,&#8221; &#8220;reproduction,&#8221; &#8220;derivative works,&#8221; and &#8220;distribution&#8221; have the same meaning here as under U.S. copyright law.</p>
+<p>A &#8220;contribution&#8221; is the original software, or any additions or changes to the software.</p>
+<p>A &#8220;contributor&#8221; is any person that distributes its contribution under this license.</p>
+<p> &#8220;Licensed patents&#8221; are a contributor&#8217;s patent claims that read directly on its contribution.</p>
+<h2>2. Grant of Rights</h2>
+<p>(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright
+license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.</p>
+
+<p>(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide,
+royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative
+works of the contribution in the software.</p>
+
+<h2>3. Conditions and Limitations</h2><p>(A) No Trademark License- This license does not grant you rights to use any contributors&#8217; name, logo, or trademarks.</p>
+<p>(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.</p>
+<p>(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.</p>
+<p>(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution.
+If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.</p>
+
+<p>(E) The software is licensed &#8220;as-is.&#8221; You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional
+consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability,
+fitness for a particular purpose and non-infringement.</p>
+
+</body>
+
+</html>
diff --git a/mcs/class/dlr/License.rtf b/mcs/class/dlr/License.rtf
new file mode 100644
index 00000000000..b623377bd0e
--- /dev/null
+++ b/mcs/class/dlr/License.rtf
@@ -0,0 +1,177 @@
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}
+{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}
+{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}
+{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
+{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}
+{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;
+\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025
+\ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033
+\snext11 \ssemihidden \sunhideused \sqformat Normal Table;}}{\*\rsidtbl \rsid11612883}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author dinov}{\operator dinov}
+{\creatim\yr2007\mo10\dy30\hr14\min43}{\revtim\yr2007\mo10\dy30\hr14\min43}{\version2}{\edmins1}{\nofpages2}{\nofwords404}{\nofchars2212}{\*\company Microsoft}{\nofcharsws2611}{\vern32893}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/200
+3/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
+\widowctrl\ftnbj\aenddoc\trackmoves1\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701
+\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot11612883 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
+\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
+\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sb100\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af0\afs28 \ltrch\fcs0 \b\f0\fs28\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 Microsoft }{\rtlch\fcs1 \ab\af0\afs28 \ltrch\fcs0
+\b\f0\fs28\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 Public }{\rtlch\fcs1 \ab\af0\afs28 \ltrch\fcs0 \b\f0\fs28\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 License (Ms-PL)
+\par }{\rtlch\fcs1 \ab\af0\afs24 \ltrch\fcs0 \b\f0\fs24\insrsid11612883 \hich\af0\dbch\af31505\loch\f0
+This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid11612883
+\par }{\rtlch\fcs1 \ab\af0\afs36 \ltrch\fcs0 \b\f0\fs36\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 1. Definitions
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 \hich\f0 The terms \'93\loch\f0 \hich\f0 reproduce,\'94\loch\f0 \hich\f0 \'93\loch\f0 \hich\f0 reproduction,\'94\loch\f0 \hich\f0 \'93
+\hich\af0\dbch\af31505\loch\f0 \hich\f0 derivative works,\'94\loch\f0 \hich\f0 and \'93\loch\f0 \hich\f0 distribution\'94\loch\f0 have the same meaning here as under U.S. copyright law.
+\par \hich\af0\dbch\af31505\loch\f0 \hich\f0 A \'93\loch\f0 \hich\f0 contribution\'94\loch\f0 is the original software, or any additions or changes to the software.
+\par \hich\af0\dbch\af31505\loch\f0 \hich\f0 A \'93\loch\f0 \hich\f0 contributor\'94\loch\f0 is any person that distributes its contribution under this\hich\af0\dbch\af31505\loch\f0 license.
+\par \loch\af0\dbch\af31505\hich\f0 \'93\loch\f0 \hich\f0 Licensed patents\'94\loch\f0 are a contributor\hich\f0 \rquote \loch\f0 s patent claims that read directly on its contribution.
+\par }{\rtlch\fcs1 \ab\af0\afs36 \ltrch\fcs0 \b\f0\fs36\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 2. Grant of Rights
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contrib
+\hich\af0\dbch\af31505\loch\f0 utor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
+
+\par \hich\af0\dbch\af31505\loch\f0 (B) Patent Grant- Subject to th\hich\af0\dbch\af31505\loch\f0
+e terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or o
+\hich\af0\dbch\af31505\loch\f0 t\hich\af0\dbch\af31505\loch\f0 herwise dispose of its contribution in the software or derivative works of the contribution in the software.
+\par }{\rtlch\fcs1 \ab\af0\afs36 \ltrch\fcs0 \b\f0\fs36\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 3. Conditions and Limitations
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid11612883 \hich\af0\dbch\af31505\loch\f0 (A) No Trademark License- This license does not grant you rights to use any contributors\hich\f0 \rquote \loch\f0 name, logo, or trademarks.
+\par \hich\af0\dbch\af31505\loch\f0 (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
+\par \hich\af0\dbch\af31505\loch\f0 (C) If you distribute any portion of the software, you must ret\hich\af0\dbch\af31505\loch\f0 ain all copyright, patent, trademark, and attribution notices that are present in the software.
+\par \hich\af0\dbch\af31505\loch\f0 (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with y\hich\af0\dbch\af31505\loch\f0
+our distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
+\par \hich\af0\dbch\af31505\loch\f0 \hich\f0 (E) The software is licensed \'93\loch\f0 \hich\f0 as-is.\'94\loch\f0 You bear the risk of using it. The contributors give \hich\af0\dbch\af31505\loch\f0
+no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantabil
+\hich\af0\dbch\af31505\loch\f0 i\hich\af0\dbch\af31505\loch\f0 ty, fitness for a particular purpose and non-infringement.
+\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid11612883
+\par }{\*\themedata 504b030414000600080000002100828abc13fa0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb6ac3301045f785fe83d0b6d8
+72ba28a5d8cea249777d2cd20f18e4b12d6a8f843409c9df77ecb850ba082d74231062ce997b55ae8fe3a00e1893f354e9555e6885647de3a8abf4fbee29bbd7
+2a3150038327acf409935ed7d757e5ee14302999a654e99e393c18936c8f23a4dc072479697d1c81e51a3b13c07e4087e6b628ee8cf5c4489cf1c4d075f92a0b
+44d7a07a83c82f308ac7b0a0f0fbf90c2480980b58abc733615aa2d210c2e02cb04430076a7ee833dfb6ce62e3ed7e14693e8317d8cd0433bf5c60f53fea2fe7
+065bd80facb647e9e25c7fc421fd2ddb526b2e9373fed4bb902e182e97b7b461e6bfad3f010000ffff0300504b030414000600080000002100a5d6a7e7c00000
+00360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4fc7060abb08
+84a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b63095120f88d94fbc
+52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462a1a82fe353
+bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f7468656d652f7468
+656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b4b0d592c9c
+070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b4757e8d3f7
+29e245eb2b260a0238fd010000ffff0300504b03041400060008000000210096b5ade296060000501b0000160000007468656d652f7468656d652f7468656d65
+312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87615b8116d8
+a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad79482a9c04
+98f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b5d8a314d3c
+94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab999fb7b471
+7509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9699640f671
+9e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd5868b37a088d1
+e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d60cf03ac1a5
+193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f9e7ef3f2d1
+17d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be15c308d3f2
+8acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a99793849c26ae6
+6252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d32a423279a
+668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2af074481847
+bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86e877f0034e
+16bafb0e258ebb4faf06b769e888340b103d3311da9750aa9d0a1cd3e4efca31a3508f6d0c5c5c398602f8e2ebc71591f5b616e24dd893aa3261fb44f95d843b
+5974bb5c04f4edafb95b7892ec1108f3f98de75dc97d5772bdff7cc95d94cf672db4b3da0a6557f70db629362d72bcb0431e53c6066acac80d699a6409fb44d0
+8741bdce9c0e4971624a2378cceaba830b05366b90e0ea23aaa241845368b0eb9e2612ca8c742851ca251ceccc70256d8d87265dd96361531f186c3d9058edf2
+c00eafe8e1fc5c509031bb4d680e9f39a3154de0accc56ae644441edd76156d7429d995bdd88664a9dc3ad50197c38af1a0c16d684060441db02565e85f3b966
+0d0713cc48a0ed6ef7dedc2dc60b17e92219e180643ed27acffba86e9c94c78ab90980d8a9f0913ee49d62b512b79626fb06dccee2a432bbc60276b9f7dec44b
+7904cfbca4f3f6443ab2a49c9c2c41476dafd55c6e7ac8c769db1bc399161ee314bc2e75cf8759081743be1236ec4f4d6693e5336fb672c5dc24a8c33585b5fb
+9cc24e1d4885545b58463634cc5416022cd19cacfccb4d30eb45296023fd35a458598360f8d7a4003bbaae25e331f155d9d9a5116d3bfb9a95523e51440ca2e0
+088dd844ec6370bf0e55d027a012ae264c45d02f708fa6ad6da6dce29c255df9f6cae0ec38666984b372ab5334cf640b37795cc860de4ae2816e95b21be5ceaf
+8a49f90b52a51cc6ff3355f47e0237052b81f6800fd7b802239daf6d8f0b1571a8426944fdbe80c6c1d40e8816b88b8569082ab84c36ff0539d4ff6dce591a26
+ade1c0a7f669880485fd484582903d284b26fa4e2156cff62e4b9265844c4495c495a9157b440e091bea1ab8aaf7760f4510eaa69a6465c0e04ec69ffb9e65d0
+28d44d4e39df9c1a52ecbd3607fee9cec7263328e5d661d3d0e4f62f44acd855ed7ab33cdf7bcb8ae889599bd5c8b3029895b6825696f6af29c239b75a5bb1e6
+345e6ee6c28117e73586c1a2214ae1be07e93fb0ff51e133fb65426fa843be0fb515c187064d0cc206a2fa926d3c902e907670048d931db4c1a44959d366ad93
+b65abe595f70a75bf03d616c2dd959fc7d4e6317cd99cbcec9c58b34766661c7d6766ca1a9c1b327531486c6f941c638c67cd22a7f75e2a37be0e82db8df9f30
+254d30c1372581a1f51c983c80e4b71ccdd28dbf000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74
+68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24
+51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198
+720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528
+a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100828abc13fa0000001c0200001300000000000000000000000000
+000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000
+002b0100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000140200007468
+656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d001400060008000000210096b5ade296060000501b000016000000000000000000
+00000000d10200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000
+00000000000000009b0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000960a00000000}
+{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
+617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
+6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
+656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
+{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
+\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;
+\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7;
+\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000
+4d73786d6c322e534158584d4c5265616465722e352e3000000000000000000000060000
+d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffffec69d9888b8b3d4c859eaf6cd158be0f0000000000000000000000009055
+58f93d1bc801feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ArgBuilder.cs
new file mode 100644
index 00000000000..813e49f09a1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ArgBuilder.cs
@@ -0,0 +1,61 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// ArgBuilder provides an argument value used by the MethodBinder. One ArgBuilder exists for each
+ /// physical parameter defined on a method.
+ ///
+ /// Contrast this with ParameterWrapper which represents the logical argument passed to the method.
+ /// </summary>
+ internal abstract class ArgBuilder {
+ /// <summary>
+ /// Provides the Expression which provides the value to be passed to the argument.
+ /// </summary>
+ internal abstract Expression Marshal(Expression parameter);
+
+ /// <summary>
+ /// Provides the Expression which provides the value to be passed to the argument.
+ /// This method is called when result is intended to be used ByRef.
+ /// </summary>
+ internal virtual Expression MarshalToRef(Expression parameter) {
+ return Marshal(parameter);
+ }
+
+ /// <summary>
+ /// Provides an Expression which will update the provided value after a call to the method.
+ /// May return null if no update is required.
+ /// </summary>
+ internal virtual Expression UnmarshalFromRef(Expression newValue) {
+ return newValue;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Assert.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Assert.cs
new file mode 100644
index 00000000000..e3cf30e50f6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Assert.cs
@@ -0,0 +1,82 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#define DEBUG
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal static class Assert {
+
+ internal static Exception Unreachable {
+ get {
+ Debug.Assert(false, "Unreachable");
+ return new InvalidOperationException("Code supposed to be unreachable");
+ }
+ }
+
+ [Conditional("DEBUG")]
+ internal static void NotNull(object var) {
+ Debug.Assert(var != null);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void NotNull(object var1, object var2) {
+ Debug.Assert(var1 != null && var2 != null);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void NotNull(object var1, object var2, object var3) {
+ Debug.Assert(var1 != null && var2 != null && var3 != null);
+ }
+
+ [Conditional("DEBUG")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
+ internal static void NotNull(object var1, object var2, object var3, object var4) {
+ Debug.Assert(var1 != null && var2 != null && var3 != null && var4 != null);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void NotEmpty(string str) {
+ Debug.Assert(!String.IsNullOrEmpty(str));
+ }
+
+ [Conditional("DEBUG")]
+ internal static void NotEmpty<T>(ICollection<T> array) {
+ Debug.Assert(array != null && array.Count > 0);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void NotNullItems<T>(IEnumerable<T> items) where T : class {
+ Debug.Assert(items != null);
+ foreach (object item in items) {
+ Debug.Assert(item != null);
+ }
+ }
+
+ [Conditional("DEBUG")]
+ internal static void IsTrue(Func<bool> predicate) {
+ ContractUtils.RequiresNotNull(predicate, "predicate");
+ Debug.Assert(predicate());
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/BoolArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/BoolArgBuilder.cs
new file mode 100644
index 00000000000..c31df708d2c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/BoolArgBuilder.cs
@@ -0,0 +1,72 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Runtime.InteropServices;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal sealed class BoolArgBuilder : SimpleArgBuilder {
+ internal BoolArgBuilder(Type parameterType)
+ : base(parameterType) {
+ Debug.Assert(parameterType == typeof(bool));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ // parameter ? -1 : 0
+ return Expression.Condition(
+ Marshal(parameter),
+ Expression.Constant((Int16)(-1)),
+ Expression.Constant((Int16)0)
+ );
+ }
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ //parameter = temp != 0
+ return base.UnmarshalFromRef(
+ Expression.NotEqual(
+ value,
+ Expression.Constant((Int16)0)
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/BoundDispEvent.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/BoundDispEvent.cs
new file mode 100644
index 00000000000..7569a74d1d6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/BoundDispEvent.cs
@@ -0,0 +1,138 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Security;
+using System.Security.Permissions;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal sealed class BoundDispEvent : DynamicObject {
+ private object _rcw;
+ private Guid _sourceIid;
+ private int _dispid;
+
+ internal BoundDispEvent(object rcw, Guid sourceIid, int dispid) {
+ _rcw = rcw;
+ _sourceIid = sourceIid;
+ _dispid = dispid;
+ }
+
+ /// <summary>
+ /// Provides the implementation of performing AddAssign and SubtractAssign binary operations.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="handler">The handler for the operation.</param>
+ /// <param name="result">The result of the operation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ public override bool TryBinaryOperation(BinaryOperationBinder binder, object handler, out object result) {
+ if (binder.Operation == ExpressionType.AddAssign) {
+ result = InPlaceAdd(handler);
+ return true;
+ }
+
+ if (binder.Operation == ExpressionType.SubtractAssign) {
+ result = InPlaceSubtract(handler);
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
+
+ private static void VerifyHandler(object handler) {
+ if (handler is Delegate && handler.GetType() != typeof(Delegate)) {
+ return; // delegate
+ }
+
+ if (handler is IDynamicMetaObjectProvider) {
+ return; // IDMOP
+ }
+
+ throw Error.UnsupportedHandlerType();
+ }
+
+ /// <summary>
+ /// Adds a handler to an event.
+ /// </summary>
+ /// <param name="handler">The handler to be added.</param>
+ /// <returns>The original event with handler added.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ private object InPlaceAdd(object handler) {
+ ContractUtils.RequiresNotNull(handler, "handler");
+ VerifyHandler(handler);
+
+ //
+ // Demand Full Trust to proceed with the operation.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, true);
+ comEventSink.AddHandler(_dispid, handler);
+ return this;
+ }
+
+ /// <summary>
+ /// Removes handler from the event.
+ /// </summary>
+ /// <param name="handler">The handler to be removed.</param>
+ /// <returns>The original event with handler removed.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ private object InPlaceSubtract(object handler) {
+ ContractUtils.RequiresNotNull(handler, "handler");
+ VerifyHandler(handler);
+
+ //
+ // Demand Full Trust to proceed with the operation.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ ComEventSink comEventSink = ComEventSink.FromRuntimeCallableWrapper(_rcw, _sourceIid, false);
+ if (comEventSink != null) {
+ comEventSink.RemoveHandler(_dispid, handler);
+ }
+
+ return this;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/CollectionExtensions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/CollectionExtensions.cs
new file mode 100644
index 00000000000..12ccd7f8b2d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/CollectionExtensions.cs
@@ -0,0 +1,55 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal static class CollectionExtensions {
+
+ internal static T[] RemoveFirst<T>(this T[] array) {
+ T[] result = new T[array.Length - 1];
+ Array.Copy(array, 1, result, 0, result.Length);
+ return result;
+ }
+
+ internal static T[] AddFirst<T>(this IList<T> list, T item) {
+ T[] res = new T[list.Count + 1];
+ res[0] = item;
+ list.CopyTo(res, 1);
+ return res;
+ }
+
+ internal static T[] ToArray<T>(this IList<T> list) {
+ T[] res = new T[list.Count];
+ list.CopyTo(res, 0);
+ return res;
+ }
+
+ internal static T[] AddLast<T>(this IList<T> list, T item) {
+ T[] res = new T[list.Count + 1];
+ list.CopyTo(res, 0);
+ res[list.Count] = item;
+ return res;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinder.cs
new file mode 100644
index 00000000000..3a7d606d2b8
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinder.cs
@@ -0,0 +1,441 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Security;
+using System.Security.Permissions;
+
+#if CODEPLEX_40
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Dynamic")]
+#else
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Microsoft.Scripting")]
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Provides helper methods to bind COM objects dynamically.
+ /// </summary>
+ public static class ComBinder {
+
+ /// <summary>
+ /// Determines if an object is a COM object.
+ /// </summary>
+ /// <param name="value">The object to test.</param>
+ /// <returns>true if the object is a COM object, false otherwise.</returns>
+ public static bool IsComObject(object value) {
+ return ComObject.IsComObject(value);
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic get member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="GetMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation. </param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <param name="delayInvocation">true if member evaluation may be delayed.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result, bool delayInvocation) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+
+ if (TryGetMetaObject(ref instance)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ var comGetMember = new ComGetMemberBinder(binder, delayInvocation);
+ result = instance.BindGetMember(comGetMember);
+ if (result.Expression.Type.IsValueType) {
+ result = new DynamicMetaObject(
+ Expression.Convert(result.Expression, typeof(object)),
+ result.Restrictions
+ );
+ }
+ return true;
+ } else {
+ result = null;
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic get member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="GetMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation. </param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+ public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result) {
+ return TryBindGetMember(binder, instance, out result, false);
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic set member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="SetMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation.</param>
+ /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set member operation.</param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryBindSetMember(SetMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject value, out DynamicMetaObject result) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+ ContractUtils.RequiresNotNull(value, "value");
+
+ if (TryGetMetaObject(ref instance)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ result = instance.BindSetMember(binder, value);
+ return true;
+ } else {
+ result = null;
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic invoke operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="InvokeBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation. </param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryBindInvoke(InvokeBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+ ContractUtils.RequiresNotNull(args, "args");
+
+ if (TryGetMetaObject(ref instance)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ result = instance.BindInvoke(binder, args);
+ return true;
+ } else {
+ result = null;
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic invoke member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="InvokeMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation. </param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryBindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+ ContractUtils.RequiresNotNull(args, "args");
+
+ if (TryGetMetaObject(ref instance)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ result = instance.BindInvokeMember(binder, args);
+ return true;
+ } else {
+ result = null;
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic get index operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="GetIndexBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation. </param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryBindGetIndex(GetIndexBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+ ContractUtils.RequiresNotNull(args, "args");
+
+ if (TryGetMetaObject(ref instance)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ result = instance.BindGetIndex(binder, args);
+ return true;
+ } else {
+ result = null;
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic set index operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation. </param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
+ /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryBindSetIndex(SetIndexBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, DynamicMetaObject value, out DynamicMetaObject result) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+ ContractUtils.RequiresNotNull(args, "args");
+ ContractUtils.RequiresNotNull(value, "value");
+
+ if (TryGetMetaObject(ref instance)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ result = instance.BindSetIndex(binder, args, value);
+ return true;
+ } else {
+ result = null;
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Tries to perform binding of the dynamic Convert operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="ConvertBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="instance">The target of the dynamic operation.</param>
+ /// <param name="result">The new <see cref="DynamicMetaObject"/> representing the result of the binding.</param>
+ /// <returns>true if operation was bound successfully; otherwise, false.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static bool TryConvert(ConvertBinder binder, DynamicMetaObject instance, out DynamicMetaObject result) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(instance, "instance");
+
+ if (IsComObject(instance.Value)) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ // Converting a COM object to any interface is always considered possible - it will result in
+ // a QueryInterface at runtime
+ if (binder.Type.IsInterface) {
+ result = new DynamicMetaObject(
+ Expression.Convert(
+ instance.Expression,
+ binder.Type
+ ),
+ BindingRestrictions.GetExpressionRestriction(
+ Expression.Call(
+ typeof(ComObject).GetMethod("IsComObject", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic),
+ Helpers.Convert(instance.Expression, typeof(object))
+ )
+ )
+ );
+ return true;
+ }
+ }
+
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Gets the member names associated with the object.
+ /// This function can operate only with objects for which <see cref="IsComObject"/> returns true.
+ /// </summary>
+ /// <param name="value">The object for which member names are requested.</param>
+ /// <returns>The collection of member names.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public static IEnumerable<string> GetDynamicMemberNames(object value) {
+ ContractUtils.RequiresNotNull(value, "value");
+ ContractUtils.Requires(IsComObject(value), "value", Strings.ComObjectExpected);
+
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ return ComObject.ObjectToComObject(value).GetMemberNames(false);
+ }
+
+ /// <summary>
+ /// Gets the member names of the data-like members associated with the object.
+ /// This function can operate only with objects for which <see cref="IsComObject"/> returns true.
+ /// </summary>
+ /// <param name="value">The object for which member names are requested.</param>
+ /// <returns>The collection of member names.</returns>
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal static IList<string> GetDynamicDataMemberNames(object value) {
+ ContractUtils.RequiresNotNull(value, "value");
+ ContractUtils.Requires(IsComObject(value), "value", Strings.ComObjectExpected);
+
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ return ComObject.ObjectToComObject(value).GetMemberNames(true);
+ }
+
+ /// <summary>
+ /// Gets the data-like members and associated data for an object.
+ /// This function can operate only with objects for which <see cref="IsComObject"/> returns true.
+ /// </summary>
+ /// <param name="value">The object for which data members are requested.</param>
+ /// <param name="names">The enumeration of names of data members for which to retrieve values.</param>
+ /// <returns>The collection of pairs that represent data member's names and their data.</returns>
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ internal static IList<KeyValuePair<string, object>> GetDynamicDataMembers(object value, IEnumerable<string> names) {
+ ContractUtils.RequiresNotNull(value, "value");
+ ContractUtils.Requires(IsComObject(value), "value", Strings.ComObjectExpected);
+
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ return ComObject.ObjectToComObject(value).GetMembers(names);
+ }
+
+ private static bool TryGetMetaObject(ref DynamicMetaObject instance) {
+ // If we're already a COM MO don't make a new one
+ // (we do this to prevent recursion if we call Fallback from COM)
+ if (instance is ComUnwrappedMetaObject) {
+ return false;
+ }
+
+ if (IsComObject(instance.Value)) {
+ instance = new ComMetaObject(instance.Expression, instance.Restrictions, instance.Value);
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Special binder that indicates special semantics for COM GetMember operation.
+ /// </summary>
+ internal class ComGetMemberBinder : GetMemberBinder {
+ private readonly GetMemberBinder _originalBinder;
+ internal bool _CanReturnCallables;
+
+ internal ComGetMemberBinder(GetMemberBinder originalBinder, bool CanReturnCallables) :
+ base(originalBinder.Name, originalBinder.IgnoreCase) {
+ _originalBinder = originalBinder;
+ _CanReturnCallables = CanReturnCallables;
+ }
+
+ public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) {
+ return _originalBinder.FallbackGetMember(target, errorSuggestion);
+ }
+
+ public override int GetHashCode() {
+ return _originalBinder.GetHashCode() ^ (_CanReturnCallables ? 1 : 0);
+ }
+
+ public override bool Equals(object obj) {
+ ComGetMemberBinder other = obj as ComGetMemberBinder;
+ return other != null &&
+ _CanReturnCallables == other._CanReturnCallables &&
+ _originalBinder.Equals(other._originalBinder);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinderHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinderHelpers.cs
new file mode 100644
index 00000000000..01c4f5e489b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComBinderHelpers.cs
@@ -0,0 +1,138 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal static class ComBinderHelpers {
+
+ internal static bool PreferPut(Type type, bool holdsNull) {
+ Debug.Assert(type != null);
+
+ if (type.IsValueType || type.IsArray) return true;
+
+ if (type == typeof(String) ||
+ type == typeof(DBNull) ||
+ holdsNull ||
+ type == typeof(System.Reflection.Missing) ||
+ type == typeof(CurrencyWrapper)) {
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ internal static bool IsByRef(DynamicMetaObject mo) {
+ ParameterExpression pe = mo.Expression as ParameterExpression;
+ return pe != null && pe.IsByRef;
+ }
+
+ internal static bool IsStrongBoxArg(DynamicMetaObject o) {
+ Type t = o.LimitType;
+ return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(StrongBox<>);
+ }
+
+ // this helper prepares arguments for COM binding by transforming ByVal StongBox arguments
+ // into ByRef expressions that represent the argument's Value fields.
+ internal static bool[] ProcessArgumentsForCom(ref DynamicMetaObject[] args) {
+ Debug.Assert(args != null);
+
+ DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length];
+ bool[] isByRefArg = new bool[args.Length];
+
+ for (int i = 0; i < args.Length; i++) {
+ DynamicMetaObject curArgument = args[i];
+
+ // set new arg infos to their original values or set default ones
+ // we will do this fixup early so that we can assume we always have
+ // arginfos in COM binder.
+
+ if (IsByRef(curArgument)) {
+ newArgs[i] = curArgument;
+ isByRefArg[i] = true;
+ } else {
+ if (IsStrongBoxArg(curArgument)) {
+ var restrictions = curArgument.Restrictions.Merge(
+ GetTypeRestrictionForDynamicMetaObject(curArgument)
+ );
+
+ // we have restricted this argument to LimitType so we can convert and conversion will be trivial cast.
+ Expression boxedValueAccessor = Expression.Field(
+ Helpers.Convert(
+ curArgument.Expression,
+ curArgument.LimitType
+ ),
+ curArgument.LimitType.GetField("Value")
+ );
+
+ IStrongBox value = curArgument.Value as IStrongBox;
+ object boxedValue = value != null ? value.Value : null;
+
+ newArgs[i] = new DynamicMetaObject(
+ boxedValueAccessor,
+ restrictions,
+ boxedValue
+ );
+
+ isByRefArg[i] = true;
+ } else {
+ newArgs[i] = curArgument;
+ isByRefArg[i] = false;
+ }
+ }
+ }
+
+ args = newArgs;
+ return isByRefArg;
+ }
+
+ internal static BindingRestrictions GetTypeRestrictionForDynamicMetaObject(DynamicMetaObject obj) {
+ if (obj.Value == null && obj.HasValue) {
+ //If the meta object holds a null value, create an instance restriction for checking null
+ return BindingRestrictions.GetInstanceRestriction(obj.Expression, null);
+ }
+ return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComDispIds.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComDispIds.cs
new file mode 100644
index 00000000000..7745d256e98
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComDispIds.cs
@@ -0,0 +1,32 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal static class ComDispIds {
+ internal const int DISPID_VALUE = 0;
+ internal const int DISPID_PROPERTYPUT = -3;
+ internal const int DISPID_NEWENUM = -4;
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventDesc.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventDesc.cs
new file mode 100644
index 00000000000..d652537165d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventDesc.cs
@@ -0,0 +1,31 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal class ComEventDesc {
+ internal Guid sourceIID;
+ internal int dispid;
+ };
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSink.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSink.cs
new file mode 100644
index 00000000000..8acec9bec9e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSink.cs
@@ -0,0 +1,349 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// This class implements an event sink for a particular RCW.
+ /// Unlike the implementation of events in TlbImp'd assemblies,
+ /// we will create only one event sink per RCW (theoretically RCW might have
+ /// several ComEventSink evenk sinks - but all these implement different source intefaces).
+ /// Each ComEventSink contains a list of ComEventSinkMethod objects - which represent
+ /// a single method on the source interface an a multicast delegate to redirect
+ /// the calls. Notice that we are chaining multicast delegates so that same
+ /// ComEventSinkMedhod can invoke multiple event handlers).
+ ///
+ /// ComEventSink implements an IDisposable pattern to Unadvise from the connection point.
+ /// Typically, when RCW is finalized the corresponding Dispose will be triggered by
+ /// ComEventSinksContainer finalizer. Notice that lifetime of ComEventSinksContainer
+ /// is bound to the lifetime of the RCW.
+ /// </summary>
+ internal sealed class ComEventSink : MarshalByRefObject, IReflect, IDisposable {
+
+ #region private fields
+
+ private Guid _sourceIid;
+ private ComTypes.IConnectionPoint _connectionPoint;
+ private int _adviseCookie;
+ private List<ComEventSinkMethod> _comEventSinkMethods;
+ private object _lockObject = new object(); // We cannot lock on ComEventSink since it causes a DoNotLockOnObjectsWithWeakIdentity warning
+
+ #endregion
+
+ #region private classes
+
+ /// <summary>
+ /// Contains a methods DISPID (in a string formatted of "[DISPID=N]"
+ /// and a chained list of delegates to invoke
+ /// </summary>
+ private class ComEventSinkMethod {
+ public string _name;
+ public Func<object[], object> _handlers;
+ }
+ #endregion
+
+ #region ctor
+
+ [SecurityCritical]
+ private ComEventSink(object rcw, Guid sourceIid) {
+ Initialize(rcw, sourceIid);
+ }
+
+ #endregion
+
+ [SecurityCritical]
+ private void Initialize(object rcw, Guid sourceIid) {
+ _sourceIid = sourceIid;
+ _adviseCookie = -1;
+
+ Debug.Assert(_connectionPoint == null, "re-initializing event sink w/o unadvising from connection point");
+
+ ComTypes.IConnectionPointContainer cpc = rcw as ComTypes.IConnectionPointContainer;
+ if (cpc == null)
+ throw Error.COMObjectDoesNotSupportEvents();
+
+ cpc.FindConnectionPoint(ref _sourceIid, out _connectionPoint);
+ if (_connectionPoint == null)
+ throw Error.COMObjectDoesNotSupportSourceInterface();
+
+ // Read the comments for ComEventSinkProxy about why we need it
+ ComEventSinkProxy proxy = new ComEventSinkProxy(this, _sourceIid);
+ _connectionPoint.Advise(proxy.GetTransparentProxy(), out _adviseCookie);
+ }
+
+ #region static methods
+
+ [SecurityCritical]
+ public static ComEventSink FromRuntimeCallableWrapper(object rcw, Guid sourceIid, bool createIfNotFound) {
+ List<ComEventSink> comEventSinks = ComEventSinksContainer.FromRuntimeCallableWrapper(rcw, createIfNotFound);
+
+ if (comEventSinks == null) {
+ return null;
+ }
+
+ ComEventSink comEventSink = null;
+ lock (comEventSinks) {
+
+ foreach (ComEventSink sink in comEventSinks) {
+ if (sink._sourceIid == sourceIid) {
+ comEventSink = sink;
+ break;
+ } else if (sink._sourceIid == Guid.Empty) {
+ // we found a ComEventSink object that
+ // was previously disposed. Now we will reuse it.
+ sink.Initialize(rcw, sourceIid);
+ comEventSink = sink;
+ }
+ }
+
+ if (comEventSink == null && createIfNotFound == true) {
+ comEventSink = new ComEventSink(rcw, sourceIid);
+ comEventSinks.Add(comEventSink);
+ }
+ }
+
+ return comEventSink;
+ }
+
+ #endregion
+
+ public void AddHandler(int dispid, object func) {
+ string name = String.Format(CultureInfo.InvariantCulture, "[DISPID={0}]", dispid);
+
+ lock (_lockObject) {
+ ComEventSinkMethod sinkMethod;
+ sinkMethod = FindSinkMethod(name);
+
+ if (sinkMethod == null) {
+ if (_comEventSinkMethods == null) {
+ _comEventSinkMethods = new List<ComEventSinkMethod>();
+ }
+
+ sinkMethod = new ComEventSinkMethod();
+ sinkMethod._name = name;
+ _comEventSinkMethods.Add(sinkMethod);
+ }
+
+ sinkMethod._handlers += new SplatCallSite(func).Invoke;
+ }
+ }
+
+ [SecurityCritical]
+ public void RemoveHandler(int dispid, object func) {
+
+ string name = String.Format(CultureInfo.InvariantCulture, "[DISPID={0}]", dispid);
+
+ lock (_lockObject) {
+
+ ComEventSinkMethod sinkEntry = FindSinkMethod(name);
+ if (sinkEntry == null){
+ return;
+ }
+
+ // Remove the delegate from multicast delegate chain.
+ // We will need to find the delegate that corresponds
+ // to the func handler we want to remove. This will be
+ // easy since we Target property of the delegate object
+ // is a ComEventCallContext object.
+ Delegate[] delegates = sinkEntry._handlers.GetInvocationList();
+ foreach (Delegate d in delegates) {
+ SplatCallSite callContext = d.Target as SplatCallSite;
+ if (callContext != null && callContext._callable.Equals(func)) {
+ sinkEntry._handlers -= d as Func<object[], object>;
+ break;
+ }
+ }
+
+ // If the delegates chain is empty - we can remove
+ // corresponding ComEvenSinkEntry
+ if (sinkEntry._handlers == null)
+ _comEventSinkMethods.Remove(sinkEntry);
+
+ // We can Unadvise from the ConnectionPoint if no more sink entries
+ // are registered for this interface
+ //(calling Dispose will call IConnectionPoint.Unadvise).
+ if (_comEventSinkMethods.Count == 0) {
+ // notice that we do not remove
+ // ComEventSinkEntry from the list, we will re-use this data structure
+ // if a new handler needs to be attached.
+ Dispose();
+ }
+ }
+ }
+
+ public object ExecuteHandler(string name, object[] args) {
+ ComEventSinkMethod site;
+ site = FindSinkMethod(name);
+
+ if (site != null && site._handlers != null) {
+ return site._handlers(args);
+ }
+
+ return null;
+ }
+
+ #region IReflect
+
+ #region Unimplemented members
+
+ public FieldInfo GetField(string name, BindingFlags bindingAttr) {
+ return null;
+ }
+
+ public FieldInfo[] GetFields(BindingFlags bindingAttr) {
+ return new FieldInfo[0];
+ }
+
+ public MemberInfo[] GetMember(string name, BindingFlags bindingAttr) {
+ return new MemberInfo[0];
+ }
+
+ public MemberInfo[] GetMembers(BindingFlags bindingAttr) {
+ return new MemberInfo[0];
+ }
+
+ public MethodInfo GetMethod(string name, BindingFlags bindingAttr) {
+ return null;
+ }
+
+ public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) {
+ return null;
+ }
+
+ public MethodInfo[] GetMethods(BindingFlags bindingAttr) {
+ return new MethodInfo[0];
+ }
+
+ public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
+ return null;
+ }
+
+ public PropertyInfo GetProperty(string name, BindingFlags bindingAttr) {
+ return null;
+ }
+
+ public PropertyInfo[] GetProperties(BindingFlags bindingAttr) {
+ return new PropertyInfo[0];
+ }
+
+ #endregion
+
+ public Type UnderlyingSystemType {
+ get {
+ return typeof(object);
+ }
+ }
+
+ public object InvokeMember(
+ string name,
+ BindingFlags invokeAttr,
+ Binder binder,
+ object target,
+ object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture,
+ string[] namedParameters) {
+
+ return ExecuteHandler(name, args);
+ }
+
+ #endregion
+
+ #region IDisposable
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public void Dispose() {
+ DisposeAll();
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ ~ComEventSink() {
+ DisposeAll();
+ }
+
+ [SecurityCritical]
+ private void DisposeAll() {
+ if (_connectionPoint == null) {
+ return;
+ }
+
+ if (_adviseCookie == -1) {
+ return;
+ }
+
+ try {
+ _connectionPoint.Unadvise(_adviseCookie);
+
+ // _connectionPoint has entered the CLR in the constructor
+ // for this object and hence its ref counter has been increased
+ // by us. We have not exposed it to other components and
+ // hence it is safe to call RCO on it w/o worrying about
+ // killing the RCW for other objects that link to it.
+ Marshal.ReleaseComObject(_connectionPoint);
+ } catch (Exception ex) {
+ // if something has gone wrong, and the object is no longer attached to the CLR,
+ // the Unadvise is going to throw. In this case, since we're going away anyway,
+ // we'll ignore the failure and quietly go on our merry way.
+ COMException exCOM = ex as COMException;
+ if (exCOM != null && exCOM.ErrorCode == ComHresults.CONNECT_E_NOCONNECTION) {
+ Debug.Assert(false, "IConnectionPoint::Unadvise returned CONNECT_E_NOCONNECTION.");
+ throw;
+ }
+ } finally {
+ _connectionPoint = null;
+ _adviseCookie = -1;
+ _sourceIid = Guid.Empty;
+ }
+ }
+
+ private ComEventSinkMethod FindSinkMethod(string name) {
+ if (_comEventSinkMethods == null)
+ return null;
+
+ ComEventSinkMethod site;
+ site = _comEventSinkMethods.Find(element => element._name == name);
+
+ return site;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinkProxy.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinkProxy.cs
new file mode 100644
index 00000000000..032bc1efa39
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinkProxy.cs
@@ -0,0 +1,148 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Proxies;
+using System.Security;
+using System.Security.Permissions;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// ComEventSinkProxy class is responsible for handling QIs for sourceIid
+ /// on instances of ComEventSink.
+ ///
+ /// Background: When a COM even sink advises to a connection point it is
+ /// supposed to hand over the dispinterface. Now, some hosts will trust
+ /// the COM client to pass the correct pointer, but some will not.
+ /// E.g. Excel's implementation of Connection Points will not cause a
+ /// QI on the pointer that has been passed, however Word will QI the
+ /// pointer to return the required interface.
+ ///
+ /// ComEventSink does not, strongly speaking, implements the interface
+ /// that it claims to implement - it is just "faking" it by using IReflect.
+ /// Thus, Word's QIs on the pointer passed to ICP::Advise would fail. To
+ /// prevent this we take advangate of RealProxy's ability of
+ /// "dressing up" like other classes and hence successfully respond to QIs
+ /// for interfaces that it does not really support( it is OK to say
+ /// "I implement this interface" for event sinks only since the common
+ /// practice is to use IDistpach.Invoke when calling into event sinks).
+ /// </summary>
+ [SecurityCritical]
+ internal sealed class ComEventSinkProxy : RealProxy {
+
+ private Guid _sinkIid;
+ private ComEventSink _sink;
+ private static readonly MethodInfo _methodInfoInvokeMember = typeof(ComEventSink).GetMethod("InvokeMember", BindingFlags.Instance | BindingFlags.Public);
+
+ #region ctors
+
+ [SecurityCritical]
+ private ComEventSinkProxy() {
+ }
+
+ [SecurityCritical]
+ public ComEventSinkProxy(ComEventSink sink, Guid sinkIid)
+ : base(typeof(ComEventSink)) {
+ _sink = sink;
+ _sinkIid = sinkIid;
+ }
+
+ #endregion
+
+ #region Base Class Overrides
+
+#if MICROSOFT_DYNAMIC
+ // to match the base method
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
+#else
+ [SecurityCritical]
+#endif
+ public override IntPtr SupportsInterface(ref Guid iid) {
+ // if the iid is the sink iid, we ask the base class for an rcw to IDispatch
+ if (iid == _sinkIid) {
+ IntPtr retVal = IntPtr.Zero;
+ retVal = Marshal.GetIDispatchForObject(_sink);
+ return retVal;
+ }
+
+ return base.SupportsInterface(ref iid);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+#if MICROSOFT_DYNAMIC
+ // to match the base method
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
+#else
+ [SecurityCritical]
+#endif
+ public override IMessage Invoke(IMessage msg) {
+ ContractUtils.RequiresNotNull(msg, "msg");
+
+ //Only know how to handle method calls (property and fields accessors count as methods)
+ IMethodCallMessage methodCallMessage = msg as IMethodCallMessage;
+ if (methodCallMessage == null)
+ throw new NotSupportedException();
+
+ // ComEventSink.InvokeMember is handled specially.
+ // The reason we need to do that is due to how namedParameters arg (7th element in the IMethodCallMessage.Args array)
+ // is marshalled when called through RealProxy.Invoke.
+ // In RealProxy.Invoke namedParameters is typed as object[], while InvokeMember expects it to be string[].
+ // If we simply let this call go through (with RemotingServices.ExecuteMessage)
+ // we get an InvalidCastException when Remoting tries to pass namedParameters (of type object[])
+ // to InvokeMember (which expects namedParameters to be string[]).
+ // Since we don't use namedParameters in ComEventSink.InvokeMember - we simply ignore it here
+ // and pass-in null.
+ MethodInfo methodInfo = (MethodInfo)methodCallMessage.MethodBase;
+ if (methodInfo == _methodInfoInvokeMember) {
+ object retVal = null;
+
+ try {
+ // InvokeMember(string name, BindingFlags bindingFlags, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
+ retVal = ((IReflect)_sink).InvokeMember(
+ /*name*/ methodCallMessage.Args[0] as string,
+ /*bindingFlags*/ (BindingFlags)methodCallMessage.Args[1],
+ /*binder*/ methodCallMessage.Args[2] as Binder,
+ /*target*/ null,
+ /*args*/ methodCallMessage.Args[4] as object[],
+ /*modifiers*/ methodCallMessage.Args[5] as ParameterModifier[],
+ /*culture*/ methodCallMessage.Args[6] as CultureInfo,
+ /*namedParameters*/ null);
+ } catch (Exception ex) {
+ return new ReturnMessage(ex.InnerException, methodCallMessage);
+ }
+
+ return new ReturnMessage(retVal, methodCallMessage.Args, methodCallMessage.ArgCount, null, methodCallMessage);
+ }
+
+ return RemotingServices.ExecuteMessage(_sink, methodCallMessage);
+ }
+
+ #endregion
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinksContainer.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinksContainer.cs
new file mode 100644
index 00000000000..1f3fbe54378
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComEventSinksContainer.cs
@@ -0,0 +1,98 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Security;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// ComEventSinksContainer is just a regular list with a finalizer.
+ /// This list is usually attached as a custom data for RCW object and
+ /// is finalized whenever RCW is finalized.
+ /// </summary>
+ internal class ComEventSinksContainer : List<ComEventSink>, IDisposable {
+ private ComEventSinksContainer() {
+ }
+
+ private static readonly object _ComObjectEventSinksKey = new object();
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
+ [SecurityCritical]
+ public static ComEventSinksContainer FromRuntimeCallableWrapper(object rcw, bool createIfNotFound) {
+ // !!! Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into
+ // a full demand. We need to avoid this by making this method SecurityCritical
+ object data = Marshal.GetComObjectData(rcw, _ComObjectEventSinksKey);
+ if (data != null || createIfNotFound == false) {
+ return (ComEventSinksContainer)data;
+ }
+
+ lock (_ComObjectEventSinksKey) {
+ data = Marshal.GetComObjectData(rcw, _ComObjectEventSinksKey);
+ if (data != null) {
+ return (ComEventSinksContainer)data;
+ }
+
+ ComEventSinksContainer comEventSinks = new ComEventSinksContainer();
+ if (!Marshal.SetComObjectData(rcw, _ComObjectEventSinksKey, comEventSinks)) {
+ throw Error.SetComObjectDataFailed();
+ }
+
+ return comEventSinks;
+ }
+ }
+
+ #region IDisposable Members
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public void Dispose() {
+ DisposeAll();
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ [SecurityCritical]
+ private void DisposeAll() {
+ foreach (ComEventSink sink in this) {
+ sink.Dispose();
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ ~ComEventSinksContainer() {
+ DisposeAll();
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComFallbackMetaObject.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComFallbackMetaObject.cs
new file mode 100644
index 00000000000..10f1fabcc67
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComFallbackMetaObject.cs
@@ -0,0 +1,92 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ //
+ // ComFallbackMetaObject just delegates everything to the binder.
+ //
+ // Note that before performing FallBack on a ComObject we need to unwrap it so that
+ // binder would act upon the actual object (typically Rcw)
+ //
+ // Also: we don't need to implement these for any operations other than those
+ // supported by ComBinder
+ internal class ComFallbackMetaObject : DynamicMetaObject {
+ internal ComFallbackMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
+ : base(expression, restrictions, arg) {
+ }
+
+ public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackGetIndex(UnwrapSelf(), indexes);
+ }
+
+ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackSetIndex(UnwrapSelf(), indexes, value);
+ }
+
+ public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackGetMember(UnwrapSelf());
+ }
+
+ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackInvokeMember(UnwrapSelf(), args);
+ }
+
+ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackSetMember(UnwrapSelf(), value);
+ }
+
+ protected virtual ComUnwrappedMetaObject UnwrapSelf() {
+ return new ComUnwrappedMetaObject(
+ ComObject.RcwFromComObject(Expression),
+ Restrictions.Merge(ComBinderHelpers.GetTypeRestrictionForDynamicMetaObject(this)),
+ ((ComObject)Value).RuntimeCallableWrapper
+ );
+ }
+ }
+
+ // This type exists as a signal type, so ComBinder knows not to try to bind
+ // again when we're trying to fall back
+ internal sealed class ComUnwrappedMetaObject : DynamicMetaObject {
+ internal ComUnwrappedMetaObject(Expression expression, BindingRestrictions restrictions, object value)
+ : base(expression, restrictions, value) {
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComHresults.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComHresults.cs
new file mode 100644
index 00000000000..dfc00fca5e3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComHresults.cs
@@ -0,0 +1,58 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal static class ComHresults {
+
+ internal const int S_OK = 0;
+
+ internal const int CONNECT_E_NOCONNECTION = unchecked((int)0x80040200);
+
+ internal const int DISP_E_UNKNOWNINTERFACE = unchecked((int)0x80020001);
+ internal const int DISP_E_MEMBERNOTFOUND = unchecked((int)0x80020003);
+ internal const int DISP_E_PARAMNOTFOUND = unchecked((int)0x80020004);
+ internal const int DISP_E_TYPEMISMATCH = unchecked((int)0x80020005);
+ internal const int DISP_E_UNKNOWNNAME = unchecked((int)0x80020006); // GetIDsOfName
+ internal const int DISP_E_NONAMEDARGS = unchecked((int)0x80020007);
+ internal const int DISP_E_BADVARTYPE = unchecked((int)0x80020008);
+ internal const int DISP_E_EXCEPTION = unchecked((int)0x80020009);
+ internal const int DISP_E_OVERFLOW = unchecked((int)0x8002000A);
+ internal const int DISP_E_BADINDEX = unchecked((int)0x8002000B); // GetTypeInfo
+ internal const int DISP_E_UNKNOWNLCID = unchecked((int)0x8002000C);
+ internal const int DISP_E_ARRAYISLOCKED = unchecked((int)0x8002000D); // VariantClear
+ internal const int DISP_E_BADPARAMCOUNT = unchecked((int)0x8002000E);
+ internal const int DISP_E_PARAMNOTOPTIONAL = unchecked((int)0x8002000F);
+
+ internal const int E_NOINTERFACE = unchecked((int)0x80004002);
+ internal const int E_FAIL = unchecked((int)0x80004005);
+
+ internal const int TYPE_E_LIBNOTREGISTERED = unchecked((int)0x8002801D);
+
+ internal static bool IsSuccess(int hresult) {
+ return hresult >= 0;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInterop.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInterop.cs
new file mode 100644
index 00000000000..2d289c7c596
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInterop.cs
@@ -0,0 +1,98 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Runtime.InteropServices;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ [
+ ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
+ Guid("00020400-0000-0000-C000-000000000046")
+ ]
+ internal interface IDispatchForReflection {
+ }
+
+ [
+ ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("00020400-0000-0000-C000-000000000046"),
+ ]
+ internal interface IDispatch {
+
+ [PreserveSig]
+ int TryGetTypeInfoCount(out uint pctinfo);
+
+ [PreserveSig]
+ int TryGetTypeInfo(uint iTInfo, int lcid, out IntPtr info);
+
+ [PreserveSig]
+ int TryGetIDsOfNames(
+ ref Guid iid,
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)]
+ string[] names,
+ uint cNames,
+ int lcid,
+ [Out]
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)]
+ int[] rgDispId);
+
+ [PreserveSig]
+ int TryInvoke(
+ int dispIdMember,
+ ref Guid riid,
+ int lcid,
+ ComTypes.INVOKEKIND wFlags,
+ ref ComTypes.DISPPARAMS pDispParams,
+ out object VarResult,
+ out ComTypes.EXCEPINFO pExcepInfo,
+ out uint puArgErr);
+ }
+
+ /// <summary>
+ /// Layout of the IDispatch vtable
+ /// </summary>
+ internal enum IDispatchMethodIndices {
+ IUnknown_QueryInterface,
+ IUnknown_AddRef,
+ IUnknown_Release,
+
+ IDispatch_GetTypeInfoCount ,
+ IDispatch_GetTypeInfo,
+ IDispatch_GetIDsOfNames,
+ IDispatch_Invoke
+ }
+
+ [
+ ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("B196B283-BAB4-101A-B69C-00AA00341D07")
+ ]
+ internal interface IProvideClassInfo {
+ void GetClassInfo(out IntPtr info);
+ }
+
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeAction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeAction.cs
new file mode 100644
index 00000000000..47ac1dd3f35
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeAction.cs
@@ -0,0 +1,107 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Invokes the object. If it falls back, just produce an error.
+ /// </summary>
+ internal sealed class ComInvokeAction : InvokeBinder {
+ internal ComInvokeAction(CallInfo callInfo)
+ : base(callInfo) {
+ }
+
+ public override int GetHashCode() {
+ return base.GetHashCode();
+ }
+
+ public override bool Equals(object obj) {
+ return base.Equals(obj as ComInvokeAction);
+ }
+
+ public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) {
+ return errorSuggestion ?? new DynamicMetaObject(
+ Expression.Throw(
+ Expression.New(
+ typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }),
+ Expression.Constant(Strings.CannotCall)
+ )
+ ),
+ target.Restrictions.Merge(BindingRestrictions.Combine(args))
+ );
+ }
+ }
+
+ /// <summary>
+ /// Splats the arguments to another nested dynamic site, which does the
+ /// real invocation of the IDynamicMetaObjectProvider.
+ /// </summary>
+ internal sealed class SplatInvokeBinder : CallSiteBinder {
+ internal readonly static SplatInvokeBinder Instance = new SplatInvokeBinder();
+
+ // Just splat the args and dispatch through a nested site
+ public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
+ Debug.Assert(args.Length == 2);
+
+ int count = ((object[])args[1]).Length;
+ ParameterExpression array = parameters[1];
+
+ var nestedArgs = new ReadOnlyCollectionBuilder<Expression>(count + 1);
+ var delegateArgs = new Type[count + 3]; // args + target + returnType + CallSite
+ nestedArgs.Add(parameters[0]);
+ delegateArgs[0] = typeof(CallSite);
+ delegateArgs[1] = typeof(object);
+ for (int i = 0; i < count; i++) {
+ nestedArgs.Add(Expression.ArrayAccess(array, Expression.Constant(i)));
+ delegateArgs[i + 2] = typeof(object).MakeByRefType();
+ }
+ delegateArgs[delegateArgs.Length - 1] = typeof(object);
+
+ return Expression.IfThen(
+ Expression.Equal(Expression.ArrayLength(array), Expression.Constant(count)),
+ Expression.Return(
+ returnLabel,
+ Expression.MakeDynamic(
+ Expression.GetDelegateType(delegateArgs),
+ new ComInvokeAction(new CallInfo(count)),
+ nestedArgs
+ )
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeBinder.cs
new file mode 100644
index 00000000000..98afb92dfd3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComInvokeBinder.cs
@@ -0,0 +1,538 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal sealed class ComInvokeBinder {
+ private readonly ComMethodDesc _methodDesc;
+ private readonly Expression _method; // ComMethodDesc to be called
+ private readonly Expression _dispatch; // IDispatch
+
+ private readonly CallInfo _callInfo;
+ private readonly DynamicMetaObject[] _args;
+ private readonly bool[] _isByRef;
+ private readonly Expression _instance;
+
+ private BindingRestrictions _restrictions;
+
+ private VarEnumSelector _varEnumSelector;
+ private string[] _keywordArgNames;
+ private int _totalExplicitArgs; // Includes the individial elements of ArgumentKind.Dictionary (if any)
+
+ private ParameterExpression _dispatchObject;
+ private ParameterExpression _dispatchPointer;
+ private ParameterExpression _dispId;
+ private ParameterExpression _dispParams;
+ private ParameterExpression _paramVariants;
+ private ParameterExpression _invokeResult;
+ private ParameterExpression _returnValue;
+ private ParameterExpression _dispIdsOfKeywordArgsPinned;
+ private ParameterExpression _propertyPutDispId;
+
+ internal ComInvokeBinder(
+ CallInfo callInfo,
+ DynamicMetaObject[] args,
+ bool[] isByRef,
+ BindingRestrictions restrictions,
+ Expression method,
+ Expression dispatch,
+ ComMethodDesc methodDesc
+ ) {
+
+ Debug.Assert(callInfo != null, "arguments");
+ Debug.Assert(args != null, "args");
+ Debug.Assert(isByRef != null, "isByRef");
+ Debug.Assert(method != null, "method");
+ Debug.Assert(dispatch != null, "dispatch");
+
+ Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method");
+ Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch");
+
+ _method = method;
+ _dispatch = dispatch;
+ _methodDesc = methodDesc;
+
+ _callInfo = callInfo;
+ _args = args;
+ _isByRef = isByRef;
+ _restrictions = restrictions;
+
+ // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with
+ _instance = dispatch;
+ }
+
+ private ParameterExpression DispatchObjectVariable {
+ get { return EnsureVariable(ref _dispatchObject, typeof(IDispatch), "dispatchObject"); }
+ }
+
+ private ParameterExpression DispatchPointerVariable {
+ get { return EnsureVariable(ref _dispatchPointer, typeof(IntPtr), "dispatchPointer"); }
+ }
+
+ private ParameterExpression DispIdVariable {
+ get { return EnsureVariable(ref _dispId, typeof(int), "dispId"); }
+ }
+
+ private ParameterExpression DispParamsVariable {
+ get { return EnsureVariable(ref _dispParams, typeof(ComTypes.DISPPARAMS), "dispParams"); }
+ }
+
+ private ParameterExpression InvokeResultVariable {
+ get { return EnsureVariable(ref _invokeResult, typeof(Variant), "invokeResult"); }
+ }
+
+ private ParameterExpression ReturnValueVariable {
+ get { return EnsureVariable(ref _returnValue, typeof(object), "returnValue"); }
+ }
+
+ private ParameterExpression DispIdsOfKeywordArgsPinnedVariable {
+ get { return EnsureVariable(ref _dispIdsOfKeywordArgsPinned, typeof(GCHandle), "dispIdsOfKeywordArgsPinned"); }
+ }
+
+ private ParameterExpression PropertyPutDispIdVariable {
+ get { return EnsureVariable(ref _propertyPutDispId, typeof(int), "propertyPutDispId"); }
+ }
+
+ private ParameterExpression ParamVariantsVariable {
+ get {
+ if (_paramVariants == null) {
+ _paramVariants = Expression.Variable(VariantArray.GetStructType(_args.Length), "paramVariants");
+ }
+ return _paramVariants;
+ }
+ }
+
+ private static ParameterExpression EnsureVariable(ref ParameterExpression var, Type type, string name) {
+ if (var != null) {
+ return var;
+ }
+ return var = Expression.Variable(type, name);
+ }
+
+ private static Type MarshalType(DynamicMetaObject mo, bool isByRef) {
+ Type marshalType = (mo.Value == null && mo.HasValue && !mo.LimitType.IsValueType) ? null : mo.LimitType;
+
+ // we are not checking that mo.Expression is writeable or whether evaluating it has no sideeffects
+ // the assumption is that whoever matched it with ByRef arginfo took care of this.
+ if (isByRef) {
+ // Null just means that null was supplied.
+ if (marshalType == null) {
+ marshalType = mo.Expression.Type;
+ }
+ marshalType = marshalType.MakeByRefType();
+ }
+ return marshalType;
+ }
+
+ internal DynamicMetaObject Invoke() {
+ _keywordArgNames = _callInfo.ArgumentNames.ToArray();
+ _totalExplicitArgs = _args.Length;
+
+ Type[] marshalArgTypes = new Type[_args.Length];
+
+ // We already tested the instance, so no need to test it again
+ for (int i = 0; i < _args.Length; i++) {
+ DynamicMetaObject curMo = _args[i];
+ _restrictions = _restrictions.Merge(ComBinderHelpers.GetTypeRestrictionForDynamicMetaObject(curMo));
+ marshalArgTypes[i] = MarshalType(curMo, _isByRef[i]);
+ }
+
+ _varEnumSelector = new VarEnumSelector(marshalArgTypes);
+
+ return new DynamicMetaObject(
+ CreateScope(MakeIDispatchInvokeTarget()),
+ BindingRestrictions.Combine(_args).Merge(_restrictions)
+ );
+ }
+
+ private static void AddNotNull(List<ParameterExpression> list, ParameterExpression var) {
+ if (var != null) list.Add(var);
+ }
+
+ private Expression CreateScope(Expression expression) {
+ List<ParameterExpression> vars = new List<ParameterExpression>();
+ AddNotNull(vars, _dispatchObject);
+ AddNotNull(vars, _dispatchPointer);
+ AddNotNull(vars, _dispId);
+ AddNotNull(vars, _dispParams);
+ AddNotNull(vars, _paramVariants);
+ AddNotNull(vars, _invokeResult);
+ AddNotNull(vars, _returnValue);
+ AddNotNull(vars, _dispIdsOfKeywordArgsPinned);
+ AddNotNull(vars, _propertyPutDispId);
+ return vars.Count > 0 ? Expression.Block(vars, expression) : expression;
+ }
+
+ private Expression GenerateTryBlock() {
+ //
+ // Declare variables
+ //
+ ParameterExpression excepInfo = Expression.Variable(typeof(ExcepInfo), "excepInfo");
+ ParameterExpression argErr = Expression.Variable(typeof(uint), "argErr");
+ ParameterExpression hresult = Expression.Variable(typeof(int), "hresult");
+
+ List<Expression> tryStatements = new List<Expression>();
+ Expression expr;
+
+ if (_keywordArgNames.Length > 0) {
+ string[] names = _keywordArgNames.AddFirst(_methodDesc.Name);
+
+ tryStatements.Add(
+ Expression.Assign(
+ Expression.Field(
+ DispParamsVariable,
+ typeof(ComTypes.DISPPARAMS).GetField("rgdispidNamedArgs")
+ ),
+ Expression.Call(typeof(UnsafeMethods).GetMethod("GetIdsOfNamedParameters"),
+ DispatchObjectVariable,
+ Expression.Constant(names),
+ DispIdVariable,
+ DispIdsOfKeywordArgsPinnedVariable
+ )
+ )
+ );
+ }
+
+ //
+ // Marshal the arguments to Variants
+ //
+ // For a call like this:
+ // comObj.Foo(100, 101, 102, x=123, z=125)
+ // DISPPARAMS needs to be setup like this:
+ // cArgs: 5
+ // cNamedArgs: 2
+ // rgArgs: 123, 125, 102, 101, 100
+ // rgdispidNamedArgs: dispid x, dispid z (the dispids of x and z respectively)
+
+ Expression[] parameters = MakeArgumentExpressions();
+
+ int reverseIndex = _varEnumSelector.VariantBuilders.Length - 1;
+ int positionalArgs = _varEnumSelector.VariantBuilders.Length - _keywordArgNames.Length; // args passed by position order and not by name
+ for (int i = 0; i < _varEnumSelector.VariantBuilders.Length; i++, reverseIndex--) {
+ int variantIndex;
+ if (i >= positionalArgs) {
+ // Named arguments are in order at the start of rgArgs
+ variantIndex = i - positionalArgs;
+ } else {
+ // Positial arguments are in reverse order at the tail of rgArgs
+ variantIndex = reverseIndex;
+ }
+ VariantBuilder variantBuilder = _varEnumSelector.VariantBuilders[i];
+
+ Expression marshal = variantBuilder.InitializeArgumentVariant(
+ VariantArray.GetStructField(ParamVariantsVariable, variantIndex),
+ parameters[i + 1]
+ );
+
+ if (marshal != null) {
+ tryStatements.Add(marshal);
+ }
+ }
+
+
+ //
+ // Call Invoke
+ //
+
+ ComTypes.INVOKEKIND invokeKind;
+ if (_methodDesc.IsPropertyPut) {
+ if (_methodDesc.IsPropertyPutRef) {
+ invokeKind = ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF;
+ } else {
+ invokeKind = ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT;
+ }
+ } else {
+ // INVOKE_PROPERTYGET should only be needed for COM objects without typeinfo, where we might have to treat properties as methods
+ invokeKind = ComTypes.INVOKEKIND.INVOKE_FUNC | ComTypes.INVOKEKIND.INVOKE_PROPERTYGET;
+ }
+
+ MethodCallExpression invoke = Expression.Call(
+ typeof(UnsafeMethods).GetMethod("IDispatchInvoke"),
+ DispatchPointerVariable,
+ DispIdVariable,
+ Expression.Constant(invokeKind),
+ DispParamsVariable,
+ InvokeResultVariable,
+ excepInfo,
+ argErr
+ );
+
+ expr = Expression.Assign(hresult, invoke);
+ tryStatements.Add(expr);
+
+ //
+ // ComRuntimeHelpers.CheckThrowException(hresult, excepInfo, argErr, ThisParameter);
+ //
+ expr = Expression.Call(
+ typeof(ComRuntimeHelpers).GetMethod("CheckThrowException"),
+ hresult,
+ excepInfo,
+ argErr,
+ Expression.Constant(_methodDesc.Name, typeof(string))
+ );
+ tryStatements.Add(expr);
+
+ //
+ // _returnValue = (ReturnType)_invokeResult.ToObject();
+ //
+ Expression invokeResultObject =
+ Expression.Call(
+ InvokeResultVariable,
+ typeof(Variant).GetMethod("ToObject"));
+
+ VariantBuilder[] variants = _varEnumSelector.VariantBuilders;
+
+ Expression[] parametersForUpdates = MakeArgumentExpressions();
+ tryStatements.Add(Expression.Assign(ReturnValueVariable, invokeResultObject));
+
+ for (int i = 0, n = variants.Length; i < n; i++) {
+ Expression updateFromReturn = variants[i].UpdateFromReturn(parametersForUpdates[i + 1]);
+ if (updateFromReturn != null) {
+ tryStatements.Add(updateFromReturn);
+ }
+ }
+
+ tryStatements.Add(Expression.Empty());
+
+ return Expression.Block(new[] { excepInfo, argErr, hresult }, tryStatements);
+ }
+
+ private Expression GenerateFinallyBlock() {
+ List<Expression> finallyStatements = new List<Expression>();
+
+ //
+ // UnsafeMethods.IUnknownRelease(dispatchPointer);
+ //
+ finallyStatements.Add(
+ Expression.Call(
+ typeof(UnsafeMethods).GetMethod("IUnknownRelease"),
+ DispatchPointerVariable
+ )
+ );
+
+ //
+ // Clear memory allocated for marshalling
+ //
+ for (int i = 0, n = _varEnumSelector.VariantBuilders.Length; i < n; i++) {
+ Expression clear = _varEnumSelector.VariantBuilders[i].Clear();
+ if (clear != null) {
+ finallyStatements.Add(clear);
+ }
+ }
+
+ //
+ // _invokeResult.Clear()
+ //
+
+ finallyStatements.Add(
+ Expression.Call(
+ InvokeResultVariable,
+ typeof(Variant).GetMethod("Clear")
+ )
+ );
+
+ //
+ // _dispIdsOfKeywordArgsPinned.Free()
+ //
+ if (_dispIdsOfKeywordArgsPinned != null) {
+ finallyStatements.Add(
+ Expression.Call(
+ DispIdsOfKeywordArgsPinnedVariable,
+ typeof(GCHandle).GetMethod("Free")
+ )
+ );
+ }
+
+ finallyStatements.Add(Expression.Empty());
+ return Expression.Block(finallyStatements);
+ }
+
+ /// <summary>
+ /// Create a stub for the target of the optimized lopop.
+ /// </summary>
+ /// <returns></returns>
+ private Expression MakeIDispatchInvokeTarget() {
+ Debug.Assert(_varEnumSelector.VariantBuilders.Length == _totalExplicitArgs);
+
+ List<Expression> exprs = new List<Expression>();
+
+ //
+ // _dispId = ((DispCallable)this).ComMethodDesc.DispId;
+ //
+ exprs.Add(
+ Expression.Assign(
+ DispIdVariable,
+ Expression.Property(_method, typeof(ComMethodDesc).GetProperty("DispId"))
+ )
+ );
+
+ //
+ // _dispParams.rgvararg = RuntimeHelpers.UnsafeMethods.ConvertVariantByrefToPtr(ref _paramVariants._element0)
+ //
+ if (_totalExplicitArgs != 0) {
+ exprs.Add(
+ Expression.Assign(
+ Expression.Field(
+ DispParamsVariable,
+ typeof(ComTypes.DISPPARAMS).GetField("rgvarg")
+ ),
+ Expression.Call(
+ typeof(UnsafeMethods).GetMethod("ConvertVariantByrefToPtr"),
+ VariantArray.GetStructField(ParamVariantsVariable, 0)
+ )
+ )
+ );
+ }
+
+ //
+ // _dispParams.cArgs = <number_of_params>;
+ //
+ exprs.Add(
+ Expression.Assign(
+ Expression.Field(
+ DispParamsVariable,
+ typeof(ComTypes.DISPPARAMS).GetField("cArgs")
+ ),
+ Expression.Constant(_totalExplicitArgs)
+ )
+ );
+
+ if (_methodDesc.IsPropertyPut) {
+ //
+ // dispParams.cNamedArgs = 1;
+ // dispParams.rgdispidNamedArgs = RuntimeHelpers.UnsafeMethods.GetNamedArgsForPropertyPut()
+ //
+ exprs.Add(
+ Expression.Assign(
+ Expression.Field(
+ DispParamsVariable,
+ typeof(ComTypes.DISPPARAMS).GetField("cNamedArgs")
+ ),
+ Expression.Constant(1)
+ )
+ );
+
+ exprs.Add(
+ Expression.Assign(
+ PropertyPutDispIdVariable,
+ Expression.Constant(ComDispIds.DISPID_PROPERTYPUT)
+ )
+ );
+
+ exprs.Add(
+ Expression.Assign(
+ Expression.Field(
+ DispParamsVariable,
+ typeof(ComTypes.DISPPARAMS).GetField("rgdispidNamedArgs")
+ ),
+ Expression.Call(
+ typeof(UnsafeMethods).GetMethod("ConvertInt32ByrefToPtr"),
+ PropertyPutDispIdVariable
+ )
+ )
+ );
+ } else {
+ //
+ // _dispParams.cNamedArgs = N;
+ //
+ exprs.Add(
+ Expression.Assign(
+ Expression.Field(
+ DispParamsVariable,
+ typeof(ComTypes.DISPPARAMS).GetField("cNamedArgs")
+ ),
+ Expression.Constant(_keywordArgNames.Length)
+ )
+ );
+ }
+
+ //
+ // _dispatchObject = _dispatch
+ // _dispatchPointer = Marshal.GetIDispatchForObject(_dispatchObject);
+ //
+
+ exprs.Add(Expression.Assign(DispatchObjectVariable, _dispatch));
+
+ exprs.Add(
+ Expression.Assign(
+ DispatchPointerVariable,
+ Expression.Call(
+ typeof(Marshal).GetMethod("GetIDispatchForObject"),
+ DispatchObjectVariable
+ )
+ )
+ );
+
+ Expression tryStatements = GenerateTryBlock();
+ Expression finallyStatements = GenerateFinallyBlock();
+
+ exprs.Add(Expression.TryFinally(tryStatements, finallyStatements));
+
+ exprs.Add(ReturnValueVariable);
+ var vars = new List<ParameterExpression>();
+ foreach (var variant in _varEnumSelector.VariantBuilders) {
+ if (variant.TempVariable != null) {
+ vars.Add(variant.TempVariable);
+ }
+ }
+ return Expression.Block(vars, exprs);
+ }
+
+ /// <summary>
+ /// Gets expressions to access all the arguments. This includes the instance argument.
+ /// </summary>
+ private Expression[] MakeArgumentExpressions() {
+ Expression[] res;
+ int copy = 0;
+ if (_instance != null) {
+ res = new Expression[_args.Length + 1];
+ res[copy++] = _instance;
+ } else {
+ res = new Expression[_args.Length];
+ }
+
+ for (int i = 0; i < _args.Length; i++) {
+ res[copy++] = _args[i].Expression;
+ }
+ return res;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMetaObject.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMetaObject.cs
new file mode 100644
index 00000000000..4beb7c54929
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMetaObject.cs
@@ -0,0 +1,87 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+using System.Collections.Generic;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ // Note: we only need to support the operations used by ComBinder
+ internal class ComMetaObject : DynamicMetaObject {
+ internal ComMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
+ : base(expression, restrictions, arg) {
+ }
+
+ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.Defer(args.AddFirst(WrapSelf()));
+ }
+
+ public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.Defer(args.AddFirst(WrapSelf()));
+ }
+
+ public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.Defer(WrapSelf());
+ }
+
+ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.Defer(WrapSelf(), value);
+ }
+
+ public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.Defer(WrapSelf(), indexes);
+ }
+
+ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.Defer(WrapSelf(), indexes.AddLast(value));
+ }
+
+ private DynamicMetaObject WrapSelf() {
+ return new DynamicMetaObject(
+ ComObject.RcwToComObject(Expression),
+ BindingRestrictions.GetExpressionRestriction(
+ Expression.Call(
+ typeof(ComObject).GetMethod("IsComObject", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic),
+ Helpers.Convert(Expression, typeof(object))
+ )
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMethodDesc.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMethodDesc.cs
new file mode 100644
index 00000000000..e221bb92574
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComMethodDesc.cs
@@ -0,0 +1,120 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using System.Globalization;
+using Marshal = System.Runtime.InteropServices.Marshal;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal sealed class ComMethodDesc {
+ private readonly int _memid; // this is the member id extracted from FUNCDESC.memid
+ private readonly string _name;
+ internal readonly INVOKEKIND InvokeKind;
+ private readonly int _paramCnt;
+
+ private ComMethodDesc(int dispId) {
+ _memid = dispId;
+ }
+
+ internal ComMethodDesc(string name, int dispId)
+ : this(dispId) {
+ // no ITypeInfo constructor
+ _name = name;
+ }
+
+ internal ComMethodDesc(string name, int dispId, INVOKEKIND invkind)
+ : this(name, dispId) {
+ InvokeKind = invkind;
+ }
+
+ internal ComMethodDesc(ITypeInfo typeInfo, FUNCDESC funcDesc)
+ : this(funcDesc.memid) {
+
+ InvokeKind = funcDesc.invkind;
+
+ int cNames;
+ string[] rgNames = new string[1 + funcDesc.cParams];
+ typeInfo.GetNames(_memid, rgNames, rgNames.Length, out cNames);
+ if (IsPropertyPut && rgNames[rgNames.Length - 1] == null) {
+ rgNames[rgNames.Length - 1] = "value";
+ cNames++;
+ }
+ Debug.Assert(cNames == rgNames.Length);
+ _name = rgNames[0];
+
+ _paramCnt = funcDesc.cParams;
+ }
+
+ public string Name {
+ get {
+ Debug.Assert(_name != null);
+ return _name;
+ }
+ }
+
+ public int DispId {
+ get { return _memid; }
+ }
+
+ public bool IsPropertyGet {
+ get {
+ return (InvokeKind & INVOKEKIND.INVOKE_PROPERTYGET) != 0;
+ }
+ }
+
+ public bool IsDataMember {
+ get {
+ //must be regular get
+ if (!IsPropertyGet || DispId == ComDispIds.DISPID_NEWENUM) {
+ return false;
+ }
+
+ //must have no parameters
+ return _paramCnt == 0;
+ }
+ }
+
+ public bool IsPropertyPut {
+ get {
+ return (InvokeKind & (INVOKEKIND.INVOKE_PROPERTYPUT | INVOKEKIND.INVOKE_PROPERTYPUTREF)) != 0;
+ }
+ }
+
+ public bool IsPropertyPutRef {
+ get {
+ return (InvokeKind & INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0;
+ }
+ }
+
+ internal int ParamCount {
+ get {
+ return _paramCnt;
+ }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComObject.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComObject.cs
new file mode 100644
index 00000000000..0860ae04bb5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComObject.cs
@@ -0,0 +1,145 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// This is a helper class for runtime-callable-wrappers of COM instances. We create one instance of this type
+ /// for every generic RCW instance.
+ /// </summary>
+ internal class ComObject : IDynamicMetaObjectProvider {
+ /// <summary>
+ /// The runtime-callable wrapper
+ /// </summary>
+ private readonly object _rcw;
+
+ internal ComObject(object rcw) {
+ Debug.Assert(ComObject.IsComObject(rcw));
+ _rcw = rcw;
+ }
+
+ internal object RuntimeCallableWrapper {
+ get {
+ return _rcw;
+ }
+ }
+
+ private readonly static object _ComObjectInfoKey = new object();
+
+ /// <summary>
+ /// This is the factory method to get the ComObject corresponding to an RCW
+ /// </summary>
+ /// <returns></returns>
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ public static ComObject ObjectToComObject(object rcw) {
+ Debug.Assert(ComObject.IsComObject(rcw));
+
+ // Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into
+ // a full demand. We could avoid this by making this method SecurityCritical
+ object data = Marshal.GetComObjectData(rcw, _ComObjectInfoKey);
+ if (data != null) {
+ return (ComObject)data;
+ }
+
+ lock (_ComObjectInfoKey) {
+ data = Marshal.GetComObjectData(rcw, _ComObjectInfoKey);
+ if (data != null) {
+ return (ComObject)data;
+ }
+
+ ComObject comObjectInfo = CreateComObject(rcw);
+ if (!Marshal.SetComObjectData(rcw, _ComObjectInfoKey, comObjectInfo)) {
+ throw Error.SetComObjectDataFailed();
+ }
+
+ return comObjectInfo;
+ }
+ }
+
+ // Expression that unwraps ComObject
+ internal static MemberExpression RcwFromComObject(Expression comObject) {
+ Debug.Assert(comObject != null && typeof(ComObject).IsAssignableFrom(comObject.Type), "must be ComObject");
+
+ return Expression.Property(
+ Helpers.Convert(comObject, typeof(ComObject)),
+ typeof(ComObject).GetProperty("RuntimeCallableWrapper", BindingFlags.NonPublic | BindingFlags.Instance)
+ );
+ }
+
+ // Expression that finds or creates a ComObject that corresponds to given Rcw
+ internal static MethodCallExpression RcwToComObject(Expression rcw) {
+ return Expression.Call(
+ typeof(ComObject).GetMethod("ObjectToComObject"),
+ Helpers.Convert(rcw, typeof(object))
+ );
+ }
+
+ private static ComObject CreateComObject(object rcw) {
+ IDispatch dispatchObject = rcw as IDispatch;
+ if (dispatchObject != null) {
+ // We can do method invocations on IDispatch objects
+ return new IDispatchComObject(dispatchObject);
+ }
+
+ // There is not much we can do in this case
+ return new ComObject(rcw);
+ }
+
+ internal virtual IList<string> GetMemberNames(bool dataOnly) {
+ return new string[0];
+ }
+
+ internal virtual IList<KeyValuePair<string, object>> GetMembers(IEnumerable<string> names) {
+ return new KeyValuePair<string, object>[0];
+ }
+
+ DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
+ return new ComFallbackMetaObject(parameter, BindingRestrictions.Empty, this);
+ }
+
+ private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
+
+ internal static bool IsComObject(object obj) {
+ // we can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust
+ return obj != null && ComObjectType.IsAssignableFrom(obj.GetType());
+ }
+
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComRuntimeHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComRuntimeHelpers.cs
new file mode 100644
index 00000000000..be0f036363b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComRuntimeHelpers.cs
@@ -0,0 +1,814 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal static class ComRuntimeHelpers {
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")]
+ public static void CheckThrowException(int hresult, ref ExcepInfo excepInfo, uint argErr, string message) {
+ if (ComHresults.IsSuccess(hresult)) {
+ return;
+ }
+
+ switch (hresult) {
+ case ComHresults.DISP_E_BADPARAMCOUNT:
+ // The number of elements provided to DISPPARAMS is different from the number of arguments
+ // accepted by the method or property.
+ throw Error.DispBadParamCount(message);
+
+ case ComHresults.DISP_E_BADVARTYPE:
+ //One of the arguments in rgvarg is not a valid variant type.
+ break;
+
+ case ComHresults.DISP_E_EXCEPTION:
+ // The application needs to raise an exception. In this case, the structure passed in pExcepInfo
+ // should be filled in.
+ throw excepInfo.GetException();
+
+ case ComHresults.DISP_E_MEMBERNOTFOUND:
+ // The requested member does not exist, or the call to Invoke tried to set the value of a
+ // read-only property.
+ throw Error.DispMemberNotFound(message);
+
+ case ComHresults.DISP_E_NONAMEDARGS:
+ // This implementation of IDispatch does not support named arguments.
+ throw Error.DispNoNamedArgs(message);
+
+ case ComHresults.DISP_E_OVERFLOW:
+ // One of the arguments in rgvarg could not be coerced to the specified type.
+ throw Error.DispOverflow(message);
+
+ case ComHresults.DISP_E_PARAMNOTFOUND:
+ // One of the parameter DISPIDs does not correspond to a parameter on the method. In this case,
+ // puArgErr should be set to the first argument that contains the error.
+ break;
+
+ case ComHresults.DISP_E_TYPEMISMATCH:
+ // One or more of the arguments could not be coerced. The index within rgvarg of the first
+ // parameter with the incorrect type is returned in the puArgErr parameter.
+ throw Error.DispTypeMismatch(argErr, message);
+
+ case ComHresults.DISP_E_UNKNOWNINTERFACE:
+ // The interface identifier passed in riid is not IID_NULL.
+ break;
+
+ case ComHresults.DISP_E_UNKNOWNLCID:
+ // The member being invoked interprets string arguments according to the LCID, and the
+ // LCID is not recognized.
+ break;
+
+ case ComHresults.DISP_E_PARAMNOTOPTIONAL:
+ // A required parameter was omitted.
+ throw Error.DispParamNotOptional(message);
+ }
+
+ Marshal.ThrowExceptionForHR(hresult);
+ }
+
+ internal static void GetInfoFromType(ComTypes.ITypeInfo typeInfo, out string name, out string documentation) {
+ int dwHelpContext;
+ string strHelpFile;
+
+ typeInfo.GetDocumentation(-1, out name, out documentation, out dwHelpContext, out strHelpFile);
+ }
+
+ internal static string GetNameOfMethod(ComTypes.ITypeInfo typeInfo, int memid) {
+ int cNames;
+ string[] rgNames = new string[1];
+ typeInfo.GetNames(memid, rgNames, 1, out cNames);
+ return rgNames[0];
+ }
+
+ internal static string GetNameOfLib(ComTypes.ITypeLib typeLib) {
+ string name;
+ string strDocString;
+ int dwHelpContext;
+ string strHelpFile;
+
+ typeLib.GetDocumentation(-1, out name, out strDocString, out dwHelpContext, out strHelpFile);
+ return name;
+ }
+
+ internal static string GetNameOfType(ComTypes.ITypeInfo typeInfo) {
+ string name;
+ string documentation;
+ GetInfoFromType(typeInfo, out name, out documentation);
+
+ return name;
+ }
+
+ /// <summary>
+ /// Look for typeinfo using IDispatch.GetTypeInfo
+ /// </summary>
+ /// <param name="dispatch"></param>
+ /// <param name="throwIfMissingExpectedTypeInfo">
+ /// Some COM objects just dont expose typeinfo. In these cases, this method will return null.
+ /// Some COM objects do intend to expose typeinfo, but may not be able to do so if the type-library is not properly
+ /// registered. This will be considered as acceptable or as an error condition depending on throwIfMissingExpectedTypeInfo</param>
+ /// <returns></returns>
+ [SecurityCritical]
+ internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch, bool throwIfMissingExpectedTypeInfo) {
+ uint typeCount;
+ int hresult = dispatch.TryGetTypeInfoCount(out typeCount);
+ Marshal.ThrowExceptionForHR(hresult);
+ Debug.Assert(typeCount <= 1);
+ if (typeCount == 0) {
+ return null;
+ }
+
+ IntPtr typeInfoPtr = IntPtr.Zero;
+
+ hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
+ if (!ComHresults.IsSuccess(hresult)) {
+ CheckIfMissingTypeInfoIsExpected(hresult, throwIfMissingExpectedTypeInfo);
+ return null;
+ }
+ if (typeInfoPtr == IntPtr.Zero) { // be defensive against components that return IntPtr.Zero
+ if (throwIfMissingExpectedTypeInfo) {
+ Marshal.ThrowExceptionForHR(ComHresults.E_FAIL);
+ }
+ return null;
+ }
+
+ ComTypes.ITypeInfo typeInfo = null;
+ try {
+ typeInfo = Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
+ } finally {
+ Marshal.Release(typeInfoPtr);
+ }
+
+ return typeInfo;
+ }
+
+ /// <summary>
+ /// This method should be called when typeinfo is not available for an object. The function
+ /// will check if the typeinfo is expected to be missing. This can include error cases where
+ /// the same error is guaranteed to happen all the time, on all machines, under all circumstances.
+ /// In such cases, we just have to operate without the typeinfo.
+ ///
+ /// However, if accessing the typeinfo is failing in a transient way, we might want to throw
+ /// an exception so that we will eagerly predictably indicate the problem.
+ /// </summary>
+ [SecurityCritical]
+ private static void CheckIfMissingTypeInfoIsExpected(int hresult, bool throwIfMissingExpectedTypeInfo) {
+ Debug.Assert(!ComHresults.IsSuccess(hresult));
+
+ // Word.Basic always returns this because of an incorrect implementation of IDispatch.GetTypeInfo
+ // Any implementation that returns E_NOINTERFACE is likely to do so in all environments
+ if (hresult == ComHresults.E_NOINTERFACE) {
+ return;
+ }
+
+ // This assert is potentially over-restrictive since COM components can behave in quite unexpected ways.
+ // However, asserting the common expected cases ensures that we find out about the unexpected scenarios, and
+ // can investigate the scenarios to ensure that there is no bug in our own code.
+ Debug.Assert(hresult == ComHresults.TYPE_E_LIBNOTREGISTERED);
+
+ if (throwIfMissingExpectedTypeInfo) {
+ Marshal.ThrowExceptionForHR(hresult);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [SecurityCritical]
+ internal static ComTypes.TYPEATTR GetTypeAttrForTypeInfo(ComTypes.ITypeInfo typeInfo) {
+ IntPtr pAttrs = IntPtr.Zero;
+ typeInfo.GetTypeAttr(out pAttrs);
+
+ // GetTypeAttr should never return null, this is just to be safe
+ if (pAttrs == IntPtr.Zero) {
+ throw Error.CannotRetrieveTypeInformation();
+ }
+
+ try {
+ return (ComTypes.TYPEATTR)Marshal.PtrToStructure(pAttrs, typeof(ComTypes.TYPEATTR));
+ } finally {
+ typeInfo.ReleaseTypeAttr(pAttrs);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [SecurityCritical]
+ internal static ComTypes.TYPELIBATTR GetTypeAttrForTypeLib(ComTypes.ITypeLib typeLib) {
+ IntPtr pAttrs = IntPtr.Zero;
+ typeLib.GetLibAttr(out pAttrs);
+
+ // GetTypeAttr should never return null, this is just to be safe
+ if (pAttrs == IntPtr.Zero) {
+ throw Error.CannotRetrieveTypeInformation();
+ }
+
+ try {
+ return (ComTypes.TYPELIBATTR)Marshal.PtrToStructure(pAttrs, typeof(ComTypes.TYPELIBATTR));
+ } finally {
+ typeLib.ReleaseTLibAttr(pAttrs);
+ }
+ }
+
+ public static BoundDispEvent CreateComEvent(object rcw, Guid sourceIid, int dispid) {
+ return new BoundDispEvent(rcw, sourceIid, dispid);
+ }
+
+ public static DispCallable CreateDispCallable(IDispatchComObject dispatch, ComMethodDesc method) {
+ return new DispCallable(dispatch, method.Name, method.DispId);
+ }
+ }
+
+ /// <summary>
+ /// This class contains methods that either cannot be expressed in C#, or which require writing unsafe code.
+ /// Callers of these methods need to use them extremely carefully as incorrect use could cause GC-holes
+ /// and other problems.
+ /// </summary>
+ ///
+ internal static class UnsafeMethods {
+ #region public members
+
+ #region Generated ConvertByrefToPtr
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_ConvertByrefToPtr from: generate_comdispatch.py
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertSByteByrefToPtr(ref SByte value) {
+ fixed (SByte *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertInt16ByrefToPtr(ref Int16 value) {
+ fixed (Int16 *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ public static unsafe IntPtr ConvertInt32ByrefToPtr(ref Int32 value) {
+ fixed (Int32 *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertInt64ByrefToPtr(ref Int64 value) {
+ fixed (Int64 *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertByteByrefToPtr(ref Byte value) {
+ fixed (Byte *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertUInt16ByrefToPtr(ref UInt16 value) {
+ fixed (UInt16 *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertUInt32ByrefToPtr(ref UInt32 value) {
+ fixed (UInt32 *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertUInt64ByrefToPtr(ref UInt64 value) {
+ fixed (UInt64 *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertIntPtrByrefToPtr(ref IntPtr value) {
+ fixed (IntPtr *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertUIntPtrByrefToPtr(ref UIntPtr value) {
+ fixed (UIntPtr *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertSingleByrefToPtr(ref Single value) {
+ fixed (Single *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertDoubleByrefToPtr(ref Double value) {
+ fixed (Double *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ internal static unsafe IntPtr ConvertDecimalByrefToPtr(ref Decimal value) {
+ fixed (Decimal *x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ public static unsafe IntPtr ConvertVariantByrefToPtr(ref Variant value) {
+ fixed (Variant* x = &value) {
+ AssertByrefPointsToStack(new IntPtr(x));
+ return new IntPtr(x);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ internal static Variant GetVariantForObject(object obj) {
+ Variant variant = default(Variant);
+ if (obj == null) {
+ return variant;
+ }
+ InitVariantForObject(obj, ref variant);
+ return variant;
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ internal static void InitVariantForObject(object obj, ref Variant variant) {
+ Debug.Assert(obj != null);
+
+ // GetNativeVariantForObject is very expensive for values that marshal as VT_DISPATCH
+ // also is is extremely common scenario when object at hand is an RCW.
+ // Therefore we are going to test for IDispatch before defaulting to GetNativeVariantForObject.
+ IDispatch disp = obj as IDispatch;
+ if (disp != null) {
+ variant.AsDispatch = obj;
+ return;
+ }
+
+ System.Runtime.InteropServices.Marshal.GetNativeVariantForObject(obj, UnsafeMethods.ConvertVariantByrefToPtr(ref variant));
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [Obsolete("do not use this method", true)]
+ public static object GetObjectForVariant(Variant variant) {
+ IntPtr ptr = UnsafeMethods.ConvertVariantByrefToPtr(ref variant);
+ return System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(ptr);
+ }
+
+ [Obsolete("do not use this method", true)]
+ public static int IUnknownRelease(IntPtr interfacePointer) {
+ return _IUnknownRelease(interfacePointer);
+ }
+
+ [Obsolete("do not use this method", true)]
+ public static void IUnknownReleaseNotZero(IntPtr interfacePointer) {
+ if (interfacePointer != IntPtr.Zero) {
+ IUnknownRelease(interfacePointer);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ [Obsolete("do not use this method", true)]
+ public static int IDispatchInvoke(
+ IntPtr dispatchPointer,
+ int memberDispId,
+ ComTypes.INVOKEKIND flags,
+ ref ComTypes.DISPPARAMS dispParams,
+ out Variant result,
+ out ExcepInfo excepInfo,
+ out uint argErr
+ ) {
+
+ int hresult = _IDispatchInvoke(
+ dispatchPointer,
+ memberDispId,
+ flags,
+ ref dispParams,
+ out result,
+ out excepInfo,
+ out argErr
+ );
+
+ if (hresult == ComHresults.DISP_E_MEMBERNOTFOUND
+ && (flags & ComTypes.INVOKEKIND.INVOKE_FUNC) != 0
+ && (flags & (ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT | ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF)) == 0) {
+
+ // Re-invoke with no result argument to accomodate Word
+ hresult = _IDispatchInvokeNoResult(
+ dispatchPointer,
+ memberDispId,
+ ComTypes.INVOKEKIND.INVOKE_FUNC,
+ ref dispParams,
+ out result,
+ out excepInfo,
+ out argErr);
+ }
+ return hresult;
+ }
+
+ [Obsolete("do not use this method", true)]
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public static IntPtr GetIdsOfNamedParameters(IDispatch dispatch, string[] names, int methodDispId, out GCHandle pinningHandle) {
+ pinningHandle = GCHandle.Alloc(null, GCHandleType.Pinned);
+ int[] dispIds = new int[names.Length];
+ Guid empty = Guid.Empty;
+ int hresult = dispatch.TryGetIDsOfNames(ref empty, names, (uint)names.Length, 0, dispIds);
+ if (hresult < 0) {
+ Marshal.ThrowExceptionForHR(hresult);
+ }
+
+ if (methodDispId != dispIds[0]) {
+ throw Error.GetIDsOfNamesInvalid(names[0]);
+ }
+
+ int[] keywordArgDispIds = dispIds.RemoveFirst(); // Remove the dispId of the method name
+
+ pinningHandle.Target = keywordArgDispIds;
+ return Marshal.UnsafeAddrOfPinnedArrayElement(keywordArgDispIds, 0);
+ }
+
+ #endregion
+
+ #region non-public members
+
+ [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
+ [SecurityCritical]
+ static UnsafeMethods() {
+ }
+
+ private static void EmitLoadArg(ILGenerator il, int index) {
+ ContractUtils.Requires(index >= 0, "index");
+
+ switch (index) {
+ case 0:
+ il.Emit(OpCodes.Ldarg_0);
+ break;
+ case 1:
+ il.Emit(OpCodes.Ldarg_1);
+ break;
+ case 2:
+ il.Emit(OpCodes.Ldarg_2);
+ break;
+ case 3:
+ il.Emit(OpCodes.Ldarg_3);
+ break;
+ default:
+ if (index <= Byte.MaxValue) {
+ il.Emit(OpCodes.Ldarg_S, (byte)index);
+ } else {
+ il.Emit(OpCodes.Ldarg, index);
+ }
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Ensure that "value" is a local variable in some caller's frame. So converting
+ /// the byref to an IntPtr is a safe operation. Alternatively, we could also allow
+ /// allowed "value" to be a pinned object.
+ /// </summary>
+ [Conditional("DEBUG")]
+ [SecurityCritical]
+ private static void AssertByrefPointsToStack(IntPtr ptr) {
+ if (Marshal.ReadInt32(ptr) == _dummyMarker) {
+ // Prevent recursion
+ return;
+ }
+ int dummy = _dummyMarker;
+ IntPtr ptrToLocal = ConvertInt32ByrefToPtr(ref dummy);
+ Debug.Assert(ptrToLocal.ToInt64() < ptr.ToInt64());
+ Debug.Assert((ptr.ToInt64() - ptrToLocal.ToInt64()) < (16 * 1024));
+ }
+
+ private static readonly object _lock = new object();
+ private static ModuleBuilder _dynamicModule;
+
+ internal static ModuleBuilder DynamicModule {
+ get {
+ if (_dynamicModule != null) {
+ return _dynamicModule;
+ }
+ lock (_lock) {
+ if (_dynamicModule == null) {
+ var attributes = new[] {
+ new CustomAttributeBuilder(typeof(UnverifiableCodeAttribute).GetConstructor(Type.EmptyTypes), new object[0]),
+ //PermissionSet(SecurityAction.Demand, Unrestricted = true)
+ new CustomAttributeBuilder(typeof(PermissionSetAttribute).GetConstructor(new Type[]{typeof(SecurityAction)}),
+ new object[]{SecurityAction.Demand},
+ new PropertyInfo[]{typeof(PermissionSetAttribute).GetProperty("Unrestricted")},
+ new object[] {true})
+ };
+
+ string name = typeof(VariantArray).Namespace + ".DynamicAssembly";
+ var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.Run, attributes);
+ assembly.DefineVersionInfoResource();
+ _dynamicModule = assembly.DefineDynamicModule(name);
+ }
+ return _dynamicModule;
+ }
+ }
+ }
+
+ private const int _dummyMarker = 0x10101010;
+
+ /// <summary>
+ /// We will emit an indirect call to an unmanaged function pointer from the vtable of the given interface pointer.
+ /// This approach can take only ~300 instructions on x86 compared with ~900 for Marshal.Release. We are relying on
+ /// the JIT-compiler to do pinvoke-stub-inlining and calling the pinvoke target directly.
+ /// </summary>
+ private delegate int IUnknownReleaseDelegate(IntPtr interfacePointer);
+ private static readonly IUnknownReleaseDelegate _IUnknownRelease = Create_IUnknownRelease();
+
+ private static IUnknownReleaseDelegate Create_IUnknownRelease() {
+ DynamicMethod dm = new DynamicMethod("IUnknownRelease", typeof(int), new Type[] { typeof(IntPtr) }, DynamicModule);
+
+ ILGenerator method = dm.GetILGenerator();
+
+ // return functionPtr(...)
+
+ method.Emit(OpCodes.Ldarg_0);
+
+ // functionPtr = *(IntPtr*)(*(interfacePointer) + VTABLE_OFFSET)
+ int iunknownReleaseOffset = ((int)IDispatchMethodIndices.IUnknown_Release) * Marshal.SizeOf(typeof(IntPtr));
+ method.Emit(OpCodes.Ldarg_0);
+ method.Emit(OpCodes.Ldind_I);
+ method.Emit(OpCodes.Ldc_I4, iunknownReleaseOffset);
+ method.Emit(OpCodes.Add);
+ method.Emit(OpCodes.Ldind_I);
+
+ SignatureHelper signature = SignatureHelper.GetMethodSigHelper(CallingConvention.Winapi, typeof(int));
+ signature.AddArgument(typeof(IntPtr));
+ method.Emit(OpCodes.Calli, signature);
+
+ method.Emit(OpCodes.Ret);
+
+ return (IUnknownReleaseDelegate)dm.CreateDelegate(typeof(IUnknownReleaseDelegate));
+ }
+
+ internal static readonly IntPtr NullInterfaceId = GetNullInterfaceId();
+
+ [SecurityCritical]
+ private static IntPtr GetNullInterfaceId() {
+ int size = Marshal.SizeOf(Guid.Empty);
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ for (int i = 0; i < size; i++) {
+ Marshal.WriteByte(ptr, i, 0);
+ }
+ return ptr;
+ }
+
+ /// <summary>
+ /// We will emit an indirect call to an unmanaged function pointer from the vtable of the given IDispatch interface pointer.
+ /// It is not possible to express this in C#. Using an indirect pinvoke call allows us to do our own marshalling.
+ /// We can allocate the Variant arguments cheaply on the stack. We are relying on the JIT-compiler to do
+ /// pinvoke-stub-inlining and calling the pinvoke target directly.
+ /// The alternative of calling via a managed interface declaration of IDispatch would have a performance
+ /// penalty of going through a CLR stub that would have to re-push the arguments on the stack, etc.
+ /// Marshal.GetDelegateForFunctionPointer could be used here, but its too expensive (~2000 instructions on x86).
+ /// </summary>
+ private delegate int IDispatchInvokeDelegate(
+ IntPtr dispatchPointer,
+ int memberDispId,
+ ComTypes.INVOKEKIND flags,
+ ref ComTypes.DISPPARAMS dispParams,
+ out Variant result,
+ out ExcepInfo excepInfo,
+ out uint argErr
+ );
+
+ private static readonly IDispatchInvokeDelegate _IDispatchInvoke = Create_IDispatchInvoke(true);
+ private static IDispatchInvokeDelegate _IDispatchInvokeNoResultImpl;
+
+ private static IDispatchInvokeDelegate _IDispatchInvokeNoResult {
+ get {
+ if (_IDispatchInvokeNoResultImpl == null) {
+ lock (_IDispatchInvoke) {
+ if (_IDispatchInvokeNoResultImpl == null) {
+ _IDispatchInvokeNoResultImpl = Create_IDispatchInvoke(false);
+ }
+ }
+ }
+ return _IDispatchInvokeNoResultImpl;
+ }
+ }
+
+ private static IDispatchInvokeDelegate Create_IDispatchInvoke(bool returnResult) {
+ const int dispatchPointerIndex = 0;
+ const int memberDispIdIndex = 1;
+ const int flagsIndex = 2;
+ const int dispParamsIndex = 3;
+ const int resultIndex = 4;
+ const int exceptInfoIndex = 5;
+ const int argErrIndex = 6;
+ Debug.Assert(argErrIndex + 1 == typeof(IDispatchInvokeDelegate).GetMethod("Invoke").GetParameters().Length);
+
+ Type[] paramTypes = new Type[argErrIndex + 1];
+ paramTypes[dispatchPointerIndex] = typeof(IntPtr);
+ paramTypes[memberDispIdIndex] = typeof(int);
+ paramTypes[flagsIndex] = typeof(ComTypes.INVOKEKIND);
+ paramTypes[dispParamsIndex] = typeof(ComTypes.DISPPARAMS).MakeByRefType();
+ paramTypes[resultIndex] = typeof(Variant).MakeByRefType();
+ paramTypes[exceptInfoIndex] = typeof(ExcepInfo).MakeByRefType();
+ paramTypes[argErrIndex] = typeof(uint).MakeByRefType();
+
+ // Define the dynamic method in our assembly so we skip verification
+ DynamicMethod dm = new DynamicMethod("IDispatchInvoke", typeof(int), paramTypes, DynamicModule);
+ ILGenerator method = dm.GetILGenerator();
+
+ // return functionPtr(...)
+
+ EmitLoadArg(method, dispatchPointerIndex);
+ EmitLoadArg(method, memberDispIdIndex);
+
+ // burn the address of our empty IID in directly. This is never freed, relocated, etc...
+ // Note passing this as a Guid directly results in a ~30% perf hit for IDispatch invokes so
+ // we also pass it directly as an IntPtr instead.
+ if (IntPtr.Size == 4) {
+ method.Emit(OpCodes.Ldc_I4, UnsafeMethods.NullInterfaceId.ToInt32()); // riid
+ } else {
+ method.Emit(OpCodes.Ldc_I8, UnsafeMethods.NullInterfaceId.ToInt64()); // riid
+ }
+ method.Emit(OpCodes.Conv_I);
+
+ method.Emit(OpCodes.Ldc_I4_0); // lcid
+ EmitLoadArg(method, flagsIndex);
+
+ EmitLoadArg(method, dispParamsIndex);
+
+ if (returnResult) {
+ EmitLoadArg(method, resultIndex);
+ } else {
+ method.Emit(OpCodes.Ldsfld, typeof(IntPtr).GetField("Zero"));
+ }
+ EmitLoadArg(method, exceptInfoIndex);
+ EmitLoadArg(method, argErrIndex);
+
+ // functionPtr = *(IntPtr*)(*(dispatchPointer) + VTABLE_OFFSET)
+ int idispatchInvokeOffset = ((int)IDispatchMethodIndices.IDispatch_Invoke) * Marshal.SizeOf(typeof(IntPtr));
+ EmitLoadArg(method, dispatchPointerIndex);
+ method.Emit(OpCodes.Ldind_I);
+ method.Emit(OpCodes.Ldc_I4, idispatchInvokeOffset);
+ method.Emit(OpCodes.Add);
+ method.Emit(OpCodes.Ldind_I);
+
+ SignatureHelper signature = SignatureHelper.GetMethodSigHelper(CallingConvention.Winapi, typeof(int));
+ Type[] invokeParamTypes = new Type[] {
+ typeof(IntPtr), // dispatchPointer
+ typeof(int), // memberDispId
+ typeof(IntPtr), // riid
+ typeof(int), // lcid
+ typeof(ushort), // flags
+ typeof(IntPtr), // dispParams
+ typeof(IntPtr), // result
+ typeof(IntPtr), // excepInfo
+ typeof(IntPtr), // argErr
+ };
+ signature.AddArguments(invokeParamTypes, null, null);
+ method.Emit(OpCodes.Calli, signature);
+
+ method.Emit(OpCodes.Ret);
+ return (IDispatchInvokeDelegate)dm.CreateDelegate(typeof(IDispatchInvokeDelegate));
+ }
+
+ #endregion
+ }
+
+ internal static class NativeMethods {
+ [System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.None)]
+ [System.Runtime.Versioning.ResourceConsumption(System.Runtime.Versioning.ResourceScope.Process, System.Runtime.Versioning.ResourceScope.Process)]
+ [DllImport("oleaut32.dll", PreserveSig = false)]
+ internal static extern void VariantClear(IntPtr variant);
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeClassDesc.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeClassDesc.cs
new file mode 100644
index 00000000000..f6d45165e12
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeClassDesc.cs
@@ -0,0 +1,79 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Security;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal sealed class ComTypeClassDesc : ComTypeDesc {
+ private LinkedList<string> _itfs; // implemented interfaces
+ private LinkedList<string> _sourceItfs; // source interfaces supported by this coclass
+
+ [SecurityCritical]
+ internal ComTypeClassDesc(ComTypes.ITypeInfo typeInfo) :
+ base(typeInfo) {
+ ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);
+ Guid = typeAttr.guid;
+
+ for (int i = 0; i < typeAttr.cImplTypes; i++) {
+ int hRefType;
+ typeInfo.GetRefTypeOfImplType(i, out hRefType);
+ ComTypes.ITypeInfo currentTypeInfo;
+ typeInfo.GetRefTypeInfo(hRefType, out currentTypeInfo);
+
+ ComTypes.IMPLTYPEFLAGS implTypeFlags;
+ typeInfo.GetImplTypeFlags(i, out implTypeFlags);
+
+ bool isSourceItf = (implTypeFlags & ComTypes.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0;
+ AddInterface(currentTypeInfo, isSourceItf);
+ }
+ }
+
+ private void AddInterface(ComTypes.ITypeInfo itfTypeInfo, bool isSourceItf) {
+ string itfName = ComRuntimeHelpers.GetNameOfType(itfTypeInfo);
+
+ if (isSourceItf) {
+ if (_sourceItfs == null) {
+ _sourceItfs = new LinkedList<string>();
+ }
+ _sourceItfs.AddLast(itfName);
+ } else {
+ if (_itfs == null) {
+ _itfs = new LinkedList<string>();
+ }
+ _itfs.AddLast(itfName);
+ }
+ }
+
+ internal bool Implements(string itfName, bool isSourceItf) {
+ if (isSourceItf)
+ return _sourceItfs.Contains(itfName);
+ else
+ return _itfs.Contains(itfName);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeDesc.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeDesc.cs
new file mode 100644
index 00000000000..cf73fbb61b5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeDesc.cs
@@ -0,0 +1,227 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices.ComTypes;
+using System.Security;
+using System.Threading;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal class ComTypeDesc {
+ private string _typeName;
+ private string _documentation;
+ private Guid _guid;
+
+ //Hashtable is threadsafe for multiple readers single writer.
+ //Enumerating and writing is mutually exclusive so require locking.
+ private Hashtable _funcs;
+ private Hashtable _puts;
+ private Hashtable _putRefs;
+ private ComMethodDesc _getItem;
+ private ComMethodDesc _setItem;
+
+ private Dictionary<string, ComEventDesc> _events;
+
+ private static readonly Dictionary<string, ComEventDesc> _EmptyEventsDict = new Dictionary<string, ComEventDesc>();
+
+ internal ComTypeDesc(ITypeInfo typeInfo) {
+ if (typeInfo != null) {
+ ComRuntimeHelpers.GetInfoFromType(typeInfo, out _typeName, out _documentation);
+ }
+ }
+
+ [SecurityCritical]
+ internal static ComTypeDesc FromITypeInfo(ComTypes.ITypeInfo typeInfo, ComTypes.TYPEATTR typeAttr) {
+ if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_COCLASS) {
+ return new ComTypeClassDesc(typeInfo);
+ } else if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_ENUM) {
+ return new ComTypeEnumDesc(typeInfo);
+ } else if ((typeAttr.typekind == ComTypes.TYPEKIND.TKIND_DISPATCH) ||
+ (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_INTERFACE)) {
+
+ return new ComTypeDesc(typeInfo);
+ } else {
+ throw Error.UnsupportedEnumType();
+ }
+ }
+
+ internal static ComTypeDesc CreateEmptyTypeDesc() {
+ ComTypeDesc typeDesc = new ComTypeDesc(null);
+ typeDesc._funcs = new Hashtable();
+ typeDesc._puts = new Hashtable();
+ typeDesc._putRefs = new Hashtable();
+ typeDesc._events = _EmptyEventsDict;
+
+ return typeDesc;
+ }
+
+ internal static Dictionary<string, ComEventDesc> EmptyEvents {
+ get { return _EmptyEventsDict; }
+ }
+
+ internal Hashtable Funcs {
+ get { return _funcs; }
+ set { _funcs = value; }
+ }
+
+ internal Hashtable Puts {
+ set { _puts = value; }
+ }
+
+ internal Hashtable PutRefs {
+ set { _putRefs = value; }
+ }
+
+ internal Dictionary<string, ComEventDesc> Events {
+ get { return _events; }
+ set { _events = value; }
+ }
+
+ internal bool TryGetFunc(string name, out ComMethodDesc method) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ if (_funcs.ContainsKey(name)) {
+ method = _funcs[name] as ComMethodDesc;
+ return true;
+ }
+ method = null;
+ return false;
+ }
+
+ internal void AddFunc(string name, ComMethodDesc method) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ lock (_funcs) {
+ _funcs[name] = method;
+ }
+ }
+
+ internal bool TryGetPut(string name, out ComMethodDesc method) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ if (_puts.ContainsKey(name)) {
+ method = _puts[name] as ComMethodDesc;
+ return true;
+ }
+ method = null;
+ return false;
+ }
+
+ internal void AddPut(string name, ComMethodDesc method) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ lock (_puts) {
+ _puts[name] = method;
+ }
+ }
+
+ internal bool TryGetPutRef(string name, out ComMethodDesc method) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ if (_putRefs.ContainsKey(name)) {
+ method = _putRefs[name] as ComMethodDesc;
+ return true;
+ }
+ method = null;
+ return false;
+ }
+ internal void AddPutRef(string name, ComMethodDesc method) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ lock (_putRefs) {
+ _putRefs[name] = method;
+ }
+ }
+
+ internal bool TryGetEvent(string name, out ComEventDesc @event) {
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ return _events.TryGetValue(name, out @event);
+ }
+
+ internal string[] GetMemberNames(bool dataOnly) {
+ var names = new Dictionary<string, object>();
+
+ lock (_funcs) {
+ foreach (ComMethodDesc func in _funcs.Values) {
+ if (!dataOnly || func.IsDataMember) {
+ names.Add(func.Name, null);
+ }
+ }
+ }
+
+ if (!dataOnly) {
+ lock (_puts) {
+ foreach (ComMethodDesc func in _puts.Values) {
+ if (!names.ContainsKey(func.Name)) {
+ names.Add(func.Name, null);
+ }
+ }
+ }
+
+ lock (_putRefs) {
+ foreach (ComMethodDesc func in _putRefs.Values) {
+ if (!names.ContainsKey(func.Name)) {
+ names.Add(func.Name, null);
+ }
+ }
+ }
+
+ if (_events != null && _events.Count > 0) {
+ foreach (string name in _events.Keys) {
+ if (!names.ContainsKey(name)) {
+ names.Add(name, null);
+ }
+ }
+ }
+ }
+
+ string[] result = new string[names.Keys.Count];
+ names.Keys.CopyTo(result, 0);
+ return result;
+ }
+
+ internal string TypeName {
+ get { return _typeName; }
+ }
+
+ internal Guid Guid {
+ get { return _guid; }
+ set { _guid = value; }
+ }
+
+ internal ComMethodDesc GetItem {
+ get { return _getItem; }
+ }
+
+ internal void EnsureGetItem(ComMethodDesc candidate) {
+ Interlocked.CompareExchange(ref _getItem, candidate, null);
+ }
+
+ internal ComMethodDesc SetItem {
+ get { return _setItem; }
+ }
+
+ internal void EnsureSetItem(ComMethodDesc candidate) {
+ Interlocked.CompareExchange(ref _setItem, candidate, null);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeEnumDesc.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeEnumDesc.cs
new file mode 100644
index 00000000000..ff25fc20a6f
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeEnumDesc.cs
@@ -0,0 +1,50 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+#if CODEPLEX_40
+using System.Dynamic;
+#else
+using Microsoft.Scripting;
+#endif
+using System.Globalization;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal sealed class ComTypeEnumDesc : ComTypeDesc {
+ public override string ToString() {
+ return String.Format(CultureInfo.CurrentCulture, "<enum '{0}'>", TypeName);
+ }
+
+ internal ComTypeEnumDesc(ComTypes.ITypeInfo typeInfo) :
+ base(typeInfo) {
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeLibDesc.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeLibDesc.cs
new file mode 100644
index 00000000000..07e7af6d8d3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ComTypeLibDesc.cs
@@ -0,0 +1,109 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Globalization;
+using System.Security;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal sealed class ComTypeLibDesc {
+
+ // typically typelibs contain very small number of coclasses
+ // so we will just use the linked list as it performs better
+ // on small number of entities
+ LinkedList<ComTypeClassDesc> _classes;
+ Dictionary<string, ComTypeEnumDesc> _enums;
+ string _typeLibName;
+
+ private static readonly Dictionary<Guid, ComTypeLibDesc> _CachedTypeLibDesc = new Dictionary<Guid, ComTypeLibDesc>();
+
+ private ComTypeLibDesc() {
+ _enums = new Dictionary<string, ComTypeEnumDesc>();
+ _classes = new LinkedList<ComTypeClassDesc>();
+ }
+
+ public override string ToString() {
+ return String.Format(CultureInfo.CurrentCulture, "<type library {0}>", _typeLibName);
+ }
+
+ [SecurityCritical]
+ internal static ComTypeLibDesc GetFromTypeLib(ComTypes.ITypeLib typeLib) {
+ // check whether we have already loaded this type library
+ ComTypes.TYPELIBATTR typeLibAttr = ComRuntimeHelpers.GetTypeAttrForTypeLib(typeLib);
+ ComTypeLibDesc typeLibDesc;
+ lock (_CachedTypeLibDesc) {
+ if (_CachedTypeLibDesc.TryGetValue(typeLibAttr.guid, out typeLibDesc)) {
+ return typeLibDesc;
+ }
+ }
+
+ typeLibDesc = new ComTypeLibDesc();
+
+ typeLibDesc._typeLibName = ComRuntimeHelpers.GetNameOfLib(typeLib);
+
+ int countTypes = typeLib.GetTypeInfoCount();
+ for (int i = 0; i < countTypes; i++) {
+ ComTypes.TYPEKIND typeKind;
+ typeLib.GetTypeInfoType(i, out typeKind);
+
+ ComTypes.ITypeInfo typeInfo;
+ if (typeKind == ComTypes.TYPEKIND.TKIND_COCLASS) {
+ typeLib.GetTypeInfo(i, out typeInfo);
+ ComTypeClassDesc classDesc = new ComTypeClassDesc(typeInfo);
+ typeLibDesc._classes.AddLast(classDesc);
+ } else if (typeKind == ComTypes.TYPEKIND.TKIND_ENUM) {
+ typeLib.GetTypeInfo(i, out typeInfo);
+ ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(typeInfo);
+ typeLibDesc._enums.Add(enumDesc.TypeName, enumDesc);
+ }
+ }
+
+ // cache the typelib using the guid as the dictionary key
+ lock (_CachedTypeLibDesc) {
+ //check if we are late and somebody already added the key.
+ ComTypeLibDesc curLibDesc;
+ if (_CachedTypeLibDesc.TryGetValue(typeLibAttr.guid, out curLibDesc)) {
+ return curLibDesc;
+ }
+
+ _CachedTypeLibDesc.Add(typeLibAttr.guid, typeLibDesc);
+ }
+
+ return typeLibDesc;
+ }
+
+ internal ComTypeClassDesc GetCoClassForInterface(string itfName) {
+ foreach (ComTypeClassDesc coclass in _classes) {
+ if (coclass.Implements(itfName, false)) {
+ return coclass;
+ }
+ }
+
+ return null;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ContractUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ContractUtils.cs
new file mode 100644
index 00000000000..dd8c2ab9ea5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ContractUtils.cs
@@ -0,0 +1,57 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal static class ContractUtils {
+ internal static void Requires(bool precondition, string paramName) {
+ Assert.NotEmpty(paramName);
+
+ if (!precondition) {
+ throw new ArgumentException(Strings.InvalidArgumentValue, paramName);
+ }
+ }
+
+ internal static void Requires(bool precondition, string paramName, string message) {
+ Assert.NotEmpty(paramName);
+
+ if (!precondition) {
+ throw new ArgumentException(message, paramName);
+ }
+ }
+
+ internal static void RequiresNotNull(object value, string paramName) {
+ Assert.NotEmpty(paramName);
+
+ if (value == null) {
+ throw new ArgumentNullException(paramName);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConversionArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConversionArgBuilder.cs
new file mode 100644
index 00000000000..84494941a02
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConversionArgBuilder.cs
@@ -0,0 +1,63 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal class ConversionArgBuilder : ArgBuilder {
+ private SimpleArgBuilder _innerBuilder;
+ private Type _parameterType;
+
+ internal ConversionArgBuilder(Type parameterType, SimpleArgBuilder innerBuilder) {
+ _parameterType = parameterType;
+ _innerBuilder = innerBuilder;
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ return _innerBuilder.Marshal(Helpers.Convert(parameter, _parameterType));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ //we are not supporting conversion InOut
+ throw Assert.Unreachable;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertArgBuilder.cs
new file mode 100644
index 00000000000..a317be17d4a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertArgBuilder.cs
@@ -0,0 +1,50 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal class ConvertArgBuilder : SimpleArgBuilder {
+ private readonly Type _marshalType;
+
+ internal ConvertArgBuilder(Type parameterType, Type marshalType)
+ : base(parameterType) {
+ _marshalType = marshalType;
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ parameter = base.Marshal(parameter);
+ return Expression.Convert(parameter, _marshalType);
+ }
+
+ internal override Expression UnmarshalFromRef(Expression newValue) {
+ return base.UnmarshalFromRef(Expression.Convert(newValue, ParameterType));
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertibleArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertibleArgBuilder.cs
new file mode 100644
index 00000000000..92551049f0e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ConvertibleArgBuilder.cs
@@ -0,0 +1,50 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Globalization;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal class ConvertibleArgBuilder : ArgBuilder {
+ internal ConvertibleArgBuilder() {
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ return Helpers.Convert(parameter, typeof(IConvertible));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ //we are not supporting convertible InOut
+ throw Assert.Unreachable;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/CurrencyArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/CurrencyArgBuilder.cs
new file mode 100644
index 00000000000..90b772f49fe
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/CurrencyArgBuilder.cs
@@ -0,0 +1,71 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal sealed class CurrencyArgBuilder : SimpleArgBuilder {
+ internal CurrencyArgBuilder(Type parameterType)
+ : base(parameterType) {
+ Debug.Assert(parameterType == typeof(CurrencyWrapper));
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ // parameter.WrappedObject
+ return Expression.Property(
+ Helpers.Convert(base.Marshal(parameter), typeof(CurrencyWrapper)),
+ "WrappedObject"
+ );
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ // Decimal.ToOACurrency(parameter.WrappedObject)
+ return Expression.Call(
+ typeof(Decimal).GetMethod("ToOACurrency"),
+ Marshal(parameter)
+ );
+ }
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // Decimal.FromOACurrency(value)
+ return base.UnmarshalFromRef(
+ Expression.New(
+ typeof(CurrencyWrapper).GetConstructor(new Type[] { typeof(Decimal) }),
+ Expression.Call(
+ typeof(Decimal).GetMethod("FromOACurrency"),
+ value
+ )
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/DateTimeArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DateTimeArgBuilder.cs
new file mode 100644
index 00000000000..ada271f7a5d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DateTimeArgBuilder.cs
@@ -0,0 +1,71 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Runtime.InteropServices;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal sealed class DateTimeArgBuilder : SimpleArgBuilder {
+ internal DateTimeArgBuilder(Type parameterType)
+ : base(parameterType) {
+ Debug.Assert(parameterType == typeof(DateTime));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ // parameter.ToOADate()
+ return Expression.Call(
+ Marshal(parameter),
+ typeof(DateTime).GetMethod("ToOADate")
+ );
+ }
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // DateTime.FromOADate(value)
+ return base.UnmarshalFromRef(
+ Expression.Call(
+ typeof(DateTime).GetMethod("FromOADate"),
+ value
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallable.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallable.cs
new file mode 100644
index 00000000000..86b59b5ea55
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallable.cs
@@ -0,0 +1,85 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Dynamic;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Scripting;
+#endif
+using System.Globalization;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// This represents a bound dispmember on a IDispatch object.
+ /// </summary>
+ internal sealed class DispCallable : IDynamicMetaObjectProvider {
+
+ private readonly IDispatchComObject _dispatch;
+ private readonly string _memberName;
+ private readonly int _dispId;
+
+ internal DispCallable(IDispatchComObject dispatch, string memberName, int dispId) {
+ _dispatch = dispatch;
+ _memberName = memberName;
+ _dispId = dispId;
+ }
+
+ public override string ToString() {
+ return String.Format(CultureInfo.CurrentCulture, "<bound dispmethod {0}>", _memberName);
+ }
+
+ public IDispatchComObject DispatchComObject {
+ get { return _dispatch; }
+ }
+
+ public IDispatch DispatchObject {
+ get { return _dispatch.DispatchObject; }
+ }
+
+ public string MemberName {
+ get { return _memberName; }
+ }
+
+ public int DispId {
+ get { return _dispId; }
+ }
+
+ public DynamicMetaObject GetMetaObject(Expression parameter) {
+ return new DispCallableMetaObject(parameter, this);
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as DispCallable;
+ return other != null && other._dispatch == _dispatch && other._dispId == _dispId;
+ }
+
+ public override int GetHashCode() {
+ return _dispatch.GetHashCode() ^ _dispId;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallableMetaObject.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallableMetaObject.cs
new file mode 100644
index 00000000000..89ce41b3461
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispCallableMetaObject.cs
@@ -0,0 +1,148 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Security;
+using System.Security.Permissions;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal class DispCallableMetaObject : DynamicMetaObject {
+ private readonly DispCallable _callable;
+
+ internal DispCallableMetaObject(Expression expression, DispCallable callable)
+ : base(expression, BindingRestrictions.Empty, callable) {
+ _callable = callable;
+ }
+
+ public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
+ return BindGetOrInvoke(indexes, binder.CallInfo) ??
+ base.BindGetIndex(binder, indexes);
+ }
+
+ public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
+ return BindGetOrInvoke(args, binder.CallInfo) ??
+ base.BindInvoke(binder, args);
+ }
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ private DynamicMetaObject BindGetOrInvoke(DynamicMetaObject[] args, CallInfo callInfo) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ ComMethodDesc method;
+ var target = _callable.DispatchComObject;
+ var name = _callable.MemberName;
+
+ if (target.TryGetMemberMethod(name, out method) ||
+ target.TryGetMemberMethodExplicit(name, out method)) {
+
+ bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref args);
+ return BindComInvoke(method, args, callInfo, isByRef);
+ }
+ return null;
+ }
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ //
+ // Demand Full Trust to proceed with the binding.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ ComMethodDesc method;
+ var target = _callable.DispatchComObject;
+ var name = _callable.MemberName;
+
+ bool holdsNull = value.Value == null && value.HasValue;
+ if (target.TryGetPropertySetter(name, out method, value.LimitType, holdsNull) ||
+ target.TryGetPropertySetterExplicit(name, out method, value.LimitType, holdsNull)) {
+
+ bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref indexes);
+ isByRef = isByRef.AddLast(false);
+ var result = BindComInvoke(method, indexes.AddLast(value), binder.CallInfo, isByRef);
+
+ // Make sure to return the value; some languages need it.
+ return new DynamicMetaObject(
+ Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))),
+ result.Restrictions
+ );
+ }
+
+ return base.BindSetIndex(binder, indexes, value);
+ }
+
+ [SecurityCritical]
+ private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef) {
+ var callable = Expression;
+ var dispCall = Helpers.Convert(callable, typeof(DispCallable));
+
+ return new ComInvokeBinder(
+ callInfo,
+ indexes,
+ isByRef,
+ DispCallableRestrictions(),
+ Expression.Constant(method),
+ Expression.Property(
+ dispCall,
+ typeof(DispCallable).GetProperty("DispatchObject")
+ ),
+ method
+ ).Invoke();
+ }
+
+ [SecurityCritical]
+ private BindingRestrictions DispCallableRestrictions() {
+ var callable = Expression;
+
+ var callableTypeRestrictions = BindingRestrictions.GetTypeRestriction(callable, typeof(DispCallable));
+ var dispCall = Helpers.Convert(callable, typeof(DispCallable));
+ var dispatch = Expression.Property(dispCall, typeof(DispCallable).GetProperty("DispatchComObject"));
+ var dispId = Expression.Property(dispCall, typeof(DispCallable).GetProperty("DispId"));
+
+ var dispatchRestriction = IDispatchMetaObject.IDispatchRestriction(dispatch, _callable.DispatchComObject.ComTypeDesc);
+ var memberRestriction = BindingRestrictions.GetExpressionRestriction(
+ Expression.Equal(dispId, Expression.Constant(_callable.DispId))
+ );
+
+ return callableTypeRestrictions.Merge(dispatchRestriction).Merge(memberRestriction);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispatchArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispatchArgBuilder.cs
new file mode 100644
index 00000000000..da4f18f487b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DispatchArgBuilder.cs
@@ -0,0 +1,101 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal class DispatchArgBuilder : SimpleArgBuilder {
+ private readonly bool _isWrapper;
+
+ internal DispatchArgBuilder(Type parameterType)
+ : base(parameterType) {
+
+ _isWrapper = parameterType == typeof(DispatchWrapper);
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ parameter = base.Marshal(parameter);
+
+ // parameter.WrappedObject
+ if (_isWrapper) {
+ parameter = Expression.Property(
+ Helpers.Convert(parameter, typeof(DispatchWrapper)),
+ typeof(DispatchWrapper).GetProperty("WrappedObject")
+ );
+ };
+
+ return Helpers.Convert(parameter, typeof(object));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ parameter = Marshal(parameter);
+
+ // parameter == null ? IntPtr.Zero : Marshal.GetIDispatchForObject(parameter);
+ return Expression.Condition(
+ Expression.Equal(parameter, Expression.Constant(null)),
+ Expression.Constant(IntPtr.Zero),
+ Expression.Call(
+ typeof(Marshal).GetMethod("GetIDispatchForObject"),
+ parameter
+ )
+ );
+ }
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // value == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(value);
+ Expression unmarshal = Expression.Condition(
+ Expression.Equal(value, Expression.Constant(IntPtr.Zero)),
+ Expression.Constant(null),
+ Expression.Call(
+ typeof(Marshal).GetMethod("GetObjectForIUnknown"),
+ value
+ )
+ );
+
+ if (_isWrapper) {
+ unmarshal = Expression.New(
+ typeof(DispatchWrapper).GetConstructor(new Type[] { typeof(object) }),
+ unmarshal
+ );
+ }
+
+ return base.UnmarshalFromRef(unmarshal);
+
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ErrorArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ErrorArgBuilder.cs
new file mode 100644
index 00000000000..04618f99b13
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ErrorArgBuilder.cs
@@ -0,0 +1,66 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal class ErrorArgBuilder : SimpleArgBuilder {
+ internal ErrorArgBuilder(Type parameterType)
+ : base(parameterType) {
+
+ Debug.Assert(parameterType == typeof(ErrorWrapper));
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ // parameter.ErrorCode
+ return Expression.Property(
+ Helpers.Convert(base.Marshal(parameter), typeof(ErrorWrapper)),
+ "ErrorCode"
+ );
+ }
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // new ErrorWrapper(value)
+ return base.UnmarshalFromRef(
+ Expression.New(
+ typeof(ErrorWrapper).GetConstructor(new Type[] { typeof(int) }),
+ value
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Errors.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Errors.cs
new file mode 100644
index 00000000000..29029fda99c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Errors.cs
@@ -0,0 +1,348 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+#if MICROSOFT_DYNAMIC
+ internal static partial class Strings {
+ private static string FormatString(string format, params object[] args) {
+ return string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args);
+ }
+ }
+
+ #region Generated Com Exception Factory
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_expr_factory_com from: generate_exception_factory.py
+
+ /// <summary>
+ /// Strongly-typed and parameterized string factory.
+ /// </summary>
+
+ internal static partial class Strings {
+ /// <summary>
+ /// A string like "Invalid argument value"
+ /// </summary>
+ internal static string InvalidArgumentValue {
+ get {
+ return "Invalid argument value";
+ }
+ }
+
+ /// <summary>
+ /// A string like "COM object is expected."
+ /// </summary>
+ internal static string ComObjectExpected {
+ get {
+ return "COM object is expected.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot perform call."
+ /// </summary>
+ internal static string CannotCall {
+ get {
+ return "Cannot perform call.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "COM object does not support events."
+ /// </summary>
+ internal static string COMObjectDoesNotSupportEvents {
+ get {
+ return "COM object does not support events.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "COM object does not support specified source interface."
+ /// </summary>
+ internal static string COMObjectDoesNotSupportSourceInterface {
+ get {
+ return "COM object does not support specified source interface.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Marshal.SetComObjectData failed."
+ /// </summary>
+ internal static string SetComObjectDataFailed {
+ get {
+ return "Marshal.SetComObjectData failed.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "This method exists only to keep the compiler happy."
+ /// </summary>
+ internal static string MethodShouldNotBeCalled {
+ get {
+ return "This method exists only to keep the compiler happy.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Unexpected VarEnum {0}."
+ /// </summary>
+ internal static string UnexpectedVarEnum(object p0) {
+ return FormatString("Unexpected VarEnum {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Error while invoking {0}."
+ /// </summary>
+ internal static string DispBadParamCount(object p0) {
+ return FormatString("Error while invoking {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Error while invoking {0}."
+ /// </summary>
+ internal static string DispMemberNotFound(object p0) {
+ return FormatString("Error while invoking {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Error while invoking {0}. Named arguments are not supported."
+ /// </summary>
+ internal static string DispNoNamedArgs(object p0) {
+ return FormatString("Error while invoking {0}. Named arguments are not supported.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Error while invoking {0}."
+ /// </summary>
+ internal static string DispOverflow(object p0) {
+ return FormatString("Error while invoking {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Could not convert argument {0} for call to {1}."
+ /// </summary>
+ internal static string DispTypeMismatch(object p0, object p1) {
+ return FormatString("Could not convert argument {0} for call to {1}.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Error while invoking {0}. A required parameter was omitted."
+ /// </summary>
+ internal static string DispParamNotOptional(object p0) {
+ return FormatString("Error while invoking {0}. A required parameter was omitted.", p0);
+ }
+
+ /// <summary>
+ /// A string like "ResolveComReference.CannotRetrieveTypeInformation."
+ /// </summary>
+ internal static string CannotRetrieveTypeInformation {
+ get {
+ return "ResolveComReference.CannotRetrieveTypeInformation.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "IDispatch::GetIDsOfNames behaved unexpectedly for {0}."
+ /// </summary>
+ internal static string GetIDsOfNamesInvalid(object p0) {
+ return FormatString("IDispatch::GetIDsOfNames behaved unexpectedly for {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Attempting to wrap an unsupported enum type."
+ /// </summary>
+ internal static string UnsupportedEnumType {
+ get {
+ return "Attempting to wrap an unsupported enum type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Attempting to pass an event handler of an unsupported type."
+ /// </summary>
+ internal static string UnsupportedHandlerType {
+ get {
+ return "Attempting to pass an event handler of an unsupported type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Could not get dispatch ID for {0} (error: {1})."
+ /// </summary>
+ internal static string CouldNotGetDispId(object p0, object p1) {
+ return FormatString("Could not get dispatch ID for {0} (error: {1}).", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "There are valid conversions from {0} to {1}."
+ /// </summary>
+ internal static string AmbiguousConversion(object p0, object p1) {
+ return FormatString("There are valid conversions from {0} to {1}.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Variant.GetAccessor cannot handle {0}."
+ /// </summary>
+ internal static string VariantGetAccessorNYI(object p0) {
+ return FormatString("Variant.GetAccessor cannot handle {0}.", p0);
+ }
+
+ }
+ /// <summary>
+ /// Strongly-typed and parameterized exception factory.
+ /// </summary>
+
+ internal static partial class Error {
+ /// <summary>
+ /// ArgumentException with message like "COM object does not support events."
+ /// </summary>
+ internal static Exception COMObjectDoesNotSupportEvents() {
+ return new ArgumentException(Strings.COMObjectDoesNotSupportEvents);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "COM object does not support specified source interface."
+ /// </summary>
+ internal static Exception COMObjectDoesNotSupportSourceInterface() {
+ return new ArgumentException(Strings.COMObjectDoesNotSupportSourceInterface);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Marshal.SetComObjectData failed."
+ /// </summary>
+ internal static Exception SetComObjectDataFailed() {
+ return new InvalidOperationException(Strings.SetComObjectDataFailed);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "This method exists only to keep the compiler happy."
+ /// </summary>
+ internal static Exception MethodShouldNotBeCalled() {
+ return new InvalidOperationException(Strings.MethodShouldNotBeCalled);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Unexpected VarEnum {0}."
+ /// </summary>
+ internal static Exception UnexpectedVarEnum(object p0) {
+ return new InvalidOperationException(Strings.UnexpectedVarEnum(p0));
+ }
+
+ /// <summary>
+ /// System.Reflection.TargetParameterCountException with message like "Error while invoking {0}."
+ /// </summary>
+ internal static Exception DispBadParamCount(object p0) {
+ return new System.Reflection.TargetParameterCountException(Strings.DispBadParamCount(p0));
+ }
+
+ /// <summary>
+ /// MissingMemberException with message like "Error while invoking {0}."
+ /// </summary>
+ internal static Exception DispMemberNotFound(object p0) {
+ return new MissingMemberException(Strings.DispMemberNotFound(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Error while invoking {0}. Named arguments are not supported."
+ /// </summary>
+ internal static Exception DispNoNamedArgs(object p0) {
+ return new ArgumentException(Strings.DispNoNamedArgs(p0));
+ }
+
+ /// <summary>
+ /// OverflowException with message like "Error while invoking {0}."
+ /// </summary>
+ internal static Exception DispOverflow(object p0) {
+ return new OverflowException(Strings.DispOverflow(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Could not convert argument {0} for call to {1}."
+ /// </summary>
+ internal static Exception DispTypeMismatch(object p0, object p1) {
+ return new ArgumentException(Strings.DispTypeMismatch(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Error while invoking {0}. A required parameter was omitted."
+ /// </summary>
+ internal static Exception DispParamNotOptional(object p0) {
+ return new ArgumentException(Strings.DispParamNotOptional(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "ResolveComReference.CannotRetrieveTypeInformation."
+ /// </summary>
+ internal static Exception CannotRetrieveTypeInformation() {
+ return new InvalidOperationException(Strings.CannotRetrieveTypeInformation);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "IDispatch::GetIDsOfNames behaved unexpectedly for {0}."
+ /// </summary>
+ internal static Exception GetIDsOfNamesInvalid(object p0) {
+ return new ArgumentException(Strings.GetIDsOfNamesInvalid(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Attempting to wrap an unsupported enum type."
+ /// </summary>
+ internal static Exception UnsupportedEnumType() {
+ return new InvalidOperationException(Strings.UnsupportedEnumType);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Attempting to pass an event handler of an unsupported type."
+ /// </summary>
+ internal static Exception UnsupportedHandlerType() {
+ return new InvalidOperationException(Strings.UnsupportedHandlerType);
+ }
+
+ /// <summary>
+ /// MissingMemberException with message like "Could not get dispatch ID for {0} (error: {1})."
+ /// </summary>
+ internal static Exception CouldNotGetDispId(object p0, object p1) {
+ return new MissingMemberException(Strings.CouldNotGetDispId(p0, p1));
+ }
+
+ /// <summary>
+ /// System.Reflection.AmbiguousMatchException with message like "There are valid conversions from {0} to {1}."
+ /// </summary>
+ internal static Exception AmbiguousConversion(object p0, object p1) {
+ return new System.Reflection.AmbiguousMatchException(Strings.AmbiguousConversion(p0, p1));
+ }
+
+ /// <summary>
+ /// NotImplementedException with message like "Variant.GetAccessor cannot handle {0}."
+ /// </summary>
+ internal static Exception VariantGetAccessorNYI(object p0) {
+ return new NotImplementedException(Strings.VariantGetAccessorNYI(p0));
+ }
+
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+#endif
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/ExcepInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ExcepInfo.cs
new file mode 100644
index 00000000000..e72665d2e3f
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/ExcepInfo.cs
@@ -0,0 +1,119 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// This is similar to ComTypes.EXCEPINFO, but lets us do our own custom marshaling
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ExcepInfo {
+ private short wCode;
+ private short wReserved;
+ private IntPtr bstrSource;
+ private IntPtr bstrDescription;
+ private IntPtr bstrHelpFile;
+ private int dwHelpContext;
+ private IntPtr pvReserved;
+ private IntPtr pfnDeferredFillIn;
+ private int scode;
+
+#if DEBUG
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2207:InitializeValueTypeStaticFieldsInline")]
+ static ExcepInfo() {
+ Debug.Assert(Marshal.SizeOf(typeof(ExcepInfo)) == Marshal.SizeOf(typeof(ComTypes.EXCEPINFO)));
+ }
+#endif
+
+ [SecurityCritical]
+ private static string ConvertAndFreeBstr(ref IntPtr bstr) {
+ if (bstr == IntPtr.Zero) {
+ return null;
+ }
+
+ string result = Marshal.PtrToStringBSTR(bstr);
+ Marshal.FreeBSTR(bstr);
+ bstr = IntPtr.Zero;
+ return result;
+ }
+
+ internal void Dummy() {
+ wCode = 0;
+ wReserved = 0; wReserved++;
+ bstrSource = IntPtr.Zero;
+ bstrDescription = IntPtr.Zero;
+ bstrHelpFile = IntPtr.Zero;
+ dwHelpContext = 0;
+ pfnDeferredFillIn = IntPtr.Zero;
+ pvReserved = IntPtr.Zero;
+ scode = 0;
+
+ throw Error.MethodShouldNotBeCalled();
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [SecurityCritical]
+ internal Exception GetException() {
+ Debug.Assert(pfnDeferredFillIn == IntPtr.Zero);
+#if DEBUG
+ System.Diagnostics.Debug.Assert(wReserved != -1);
+ wReserved = -1; // to ensure that the method gets called only once
+#endif
+
+ int errorCode = (scode != 0) ? scode : wCode;
+ Exception exception = Marshal.GetExceptionForHR(errorCode);
+
+ string message = ConvertAndFreeBstr(ref bstrDescription);
+ if (message != null) {
+ // If we have a custom message, create a new Exception object with the message set correctly.
+ // We need to create a new object because "exception.Message" is a read-only property.
+ if (exception is COMException) {
+ exception = new COMException(message, errorCode);
+ } else {
+ Type exceptionType = exception.GetType();
+ ConstructorInfo ctor = exceptionType.GetConstructor(new Type[] { typeof(string) });
+ if (ctor != null) {
+ exception = (Exception)ctor.Invoke(new object[] { message });
+ }
+ }
+ }
+
+ exception.Source = ConvertAndFreeBstr(ref bstrSource);
+
+ string helpLink = ConvertAndFreeBstr(ref bstrHelpFile);
+ if (helpLink != null && dwHelpContext != 0) {
+ helpLink += "#" + dwHelpContext;
+ }
+ exception.HelpLink = helpLink;
+
+ return exception;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Helpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Helpers.cs
new file mode 100644
index 00000000000..65f5d49bbf6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Helpers.cs
@@ -0,0 +1,41 @@
+
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ // Miscellaneous helpers that don't belong anywhere else
+ internal static class Helpers {
+
+ internal static Expression Convert(Expression expression, Type type) {
+ if (expression.Type == type) {
+ return expression;
+ }
+ return Expression.Convert(expression, type);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchComObject.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchComObject.cs
new file mode 100644
index 00000000000..0b18e39c2b5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchComObject.cs
@@ -0,0 +1,643 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// An object that implements IDispatch
+ ///
+ /// This currently has the following issues:
+ /// 1. If we prefer ComObjectWithTypeInfo over IDispatchComObject, then we will often not
+ /// IDispatchComObject since implementations of IDispatch often rely on a registered type library.
+ /// If we prefer IDispatchComObject over ComObjectWithTypeInfo, users get a non-ideal experience.
+ /// 2. IDispatch cannot distinguish between properties and methods with 0 arguments (and non-0
+ /// default arguments?). So obj.foo() is ambiguous as it could mean invoking method foo,
+ /// or it could mean invoking the function pointer returned by property foo.
+ /// We are attempting to find whether we need to call a method or a property by examining
+ /// the ITypeInfo associated with the IDispatch. ITypeInfo tell's use what parameters the method
+ /// expects, is it a method or a property, what is the default property of the object, how to
+ /// create an enumerator for collections etc.
+ /// 3. IronPython processes the signature and converts ref arguments into return values.
+ /// However, since the signature of a DispMethod is not available beforehand, this conversion
+ /// is not possible. There could be other signature conversions that may be affected. How does
+ /// VB6 deal with ref arguments and IDispatch?
+ ///
+ /// We also support events for IDispatch objects:
+ /// Background:
+ /// COM objects support events through a mechanism known as Connect Points.
+ /// Connection Points are separate objects created off the actual COM
+ /// object (this is to prevent circular references between event sink
+ /// and event source). When clients want to sink events generated by
+ /// COM object they would implement callback interfaces (aka source
+ /// interfaces) and hand it over (advise) to the Connection Point.
+ ///
+ /// Implementation details:
+ /// When IDispatchComObject.TryGetMember request is received we first check
+ /// whether the requested member is a property or a method. If this check
+ /// fails we will try to determine whether an event is requested. To do
+ /// so we will do the following set of steps:
+ /// 1. Verify the COM object implements IConnectionPointContainer
+ /// 2. Attempt to find COM object's coclass's description
+ /// a. Query the object for IProvideClassInfo interface. Go to 3, if found
+ /// b. From object's IDispatch retrieve primary interface description
+ /// c. Scan coclasses declared in object's type library.
+ /// d. Find coclass implementing this particular primary interface
+ /// 3. Scan coclass for all its source interfaces.
+ /// 4. Check whether to any of the methods on the source interfaces matches
+ /// the request name
+ ///
+ /// Once we determine that TryGetMember requests an event we will return
+ /// an instance of BoundDispEvent class. This class has InPlaceAdd and
+ /// InPlaceSubtract operators defined. Calling InPlaceAdd operator will:
+ /// 1. An instance of ComEventSinksContainer class is created (unless
+ /// RCW already had one). This instance is hanged off the RCW in attempt
+ /// to bind the lifetime of event sinks to the lifetime of the RCW itself,
+ /// meaning event sink will be collected once the RCW is collected (this
+ /// is the same way event sinks lifetime is controlled by PIAs).
+ /// Notice: ComEventSinksContainer contains a Finalizer which will go and
+ /// unadvise all event sinks.
+ /// Notice: ComEventSinksContainer is a list of ComEventSink objects.
+ /// 2. Unless we have already created a ComEventSink for the required
+ /// source interface, we will create and advise a new ComEventSink. Each
+ /// ComEventSink implements a single source interface that COM object
+ /// supports.
+ /// 3. ComEventSink contains a map between method DISPIDs to the
+ /// multicast delegate that will be invoked when the event is raised.
+ /// 4. ComEventSink implements IReflect interface which is exposed as
+ /// custom IDispatch to COM consumers. This allows us to intercept calls
+ /// to IDispatch.Invoke and apply custom logic - in particular we will
+ /// just find and invoke the multicast delegate corresponding to the invoked
+ /// dispid.
+ /// </summary>
+
+ internal sealed class IDispatchComObject : ComObject, IDynamicMetaObjectProvider {
+
+ private readonly IDispatch _dispatchObject;
+ private ComTypeDesc _comTypeDesc;
+ private static readonly Dictionary<Guid, ComTypeDesc> _CacheComTypeDesc = new Dictionary<Guid, ComTypeDesc>();
+
+ internal IDispatchComObject(IDispatch rcw)
+ : base(rcw) {
+ _dispatchObject = rcw;
+ }
+
+ public override string ToString() {
+ ComTypeDesc ctd = _comTypeDesc;
+ string typeName = null;
+
+ if (ctd != null) {
+ typeName = ctd.TypeName;
+ }
+
+ if (String.IsNullOrEmpty(typeName)) {
+ typeName = "IDispatch";
+ }
+
+ return String.Format(CultureInfo.CurrentCulture, "{0} ({1})", RuntimeCallableWrapper.ToString(), typeName);
+ }
+
+ public ComTypeDesc ComTypeDesc {
+ get {
+ EnsureScanDefinedMethods();
+ return _comTypeDesc;
+ }
+ }
+
+ public IDispatch DispatchObject {
+ get {
+ return _dispatchObject;
+ }
+ }
+
+ private static int GetIDsOfNames(IDispatch dispatch, string name, out int dispId) {
+ int[] dispIds = new int[1];
+ Guid emtpyRiid = Guid.Empty;
+ int hresult = dispatch.TryGetIDsOfNames(
+ ref emtpyRiid,
+ new string[] { name },
+ 1,
+ 0,
+ dispIds);
+
+ dispId = dispIds[0];
+ return hresult;
+ }
+
+ static int Invoke(IDispatch dispatch, int memberDispId, out object result) {
+ Guid emtpyRiid = Guid.Empty;
+ ComTypes.DISPPARAMS dispParams = new ComTypes.DISPPARAMS();
+ ComTypes.EXCEPINFO excepInfo = new ComTypes.EXCEPINFO();
+ uint argErr;
+ int hresult = dispatch.TryInvoke(
+ memberDispId,
+ ref emtpyRiid,
+ 0,
+ ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
+ ref dispParams,
+ out result,
+ out excepInfo,
+ out argErr);
+
+ return hresult;
+ }
+
+ internal bool TryGetGetItem(out ComMethodDesc value) {
+ ComMethodDesc methodDesc = _comTypeDesc.GetItem;
+ if (methodDesc != null) {
+ value = methodDesc;
+ return true;
+ }
+
+ return SlowTryGetGetItem(out value);
+ }
+
+ private bool SlowTryGetGetItem(out ComMethodDesc value) {
+ EnsureScanDefinedMethods();
+
+ ComMethodDesc methodDesc = _comTypeDesc.GetItem;
+
+ // Without type information, we really don't know whether or not we have a property getter.
+ if (methodDesc == null) {
+ string name = "[PROPERTYGET, DISPID(0)]";
+
+ _comTypeDesc.EnsureGetItem(new ComMethodDesc(name, ComDispIds.DISPID_VALUE, ComTypes.INVOKEKIND.INVOKE_PROPERTYGET));
+ methodDesc = _comTypeDesc.GetItem;
+ }
+
+ value = methodDesc;
+ return true;
+ }
+
+ internal bool TryGetSetItem(out ComMethodDesc value) {
+ ComMethodDesc methodDesc = _comTypeDesc.SetItem;
+ if (methodDesc != null) {
+ value = methodDesc;
+ return true;
+ }
+
+ return SlowTryGetSetItem(out value);
+ }
+
+ private bool SlowTryGetSetItem(out ComMethodDesc value) {
+ EnsureScanDefinedMethods();
+
+ ComMethodDesc methodDesc = _comTypeDesc.SetItem;
+
+ // Without type information, we really don't know whether or not we have a property setter.
+ if (methodDesc == null) {
+ string name = "[PROPERTYPUT, DISPID(0)]";
+
+ _comTypeDesc.EnsureSetItem(new ComMethodDesc(name, ComDispIds.DISPID_VALUE, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT));
+ methodDesc = _comTypeDesc.SetItem;
+ }
+
+ value = methodDesc;
+ return true;
+ }
+
+ internal bool TryGetMemberMethod(string name, out ComMethodDesc method) {
+ EnsureScanDefinedMethods();
+ return _comTypeDesc.TryGetFunc(name, out method);
+ }
+
+ internal bool TryGetMemberEvent(string name, out ComEventDesc @event) {
+ EnsureScanDefinedEvents();
+ return _comTypeDesc.TryGetEvent(name, out @event);
+ }
+
+ internal bool TryGetMemberMethodExplicit(string name, out ComMethodDesc method) {
+ EnsureScanDefinedMethods();
+
+ int dispId;
+ int hresult = GetIDsOfNames(_dispatchObject, name, out dispId);
+
+ if (hresult == ComHresults.S_OK) {
+ ComMethodDesc cmd = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_FUNC);
+ _comTypeDesc.AddFunc(name, cmd);
+ method = cmd;
+ return true;
+ } else if (hresult == ComHresults.DISP_E_UNKNOWNNAME) {
+ method = null;
+ return false;
+ } else {
+ throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{1:X})", hresult));
+ }
+ }
+
+ internal bool TryGetPropertySetterExplicit(string name, out ComMethodDesc method, Type limitType, bool holdsNull) {
+ EnsureScanDefinedMethods();
+
+ int dispId;
+ int hresult = GetIDsOfNames(_dispatchObject, name, out dispId);
+
+ if (hresult == ComHresults.S_OK) {
+ // we do not know whether we have put or putref here
+ // and we will not guess and pretend we found both.
+ ComMethodDesc put = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT);
+ _comTypeDesc.AddPut(name, put);
+
+ ComMethodDesc putref = new ComMethodDesc(name, dispId, ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF);
+ _comTypeDesc.AddPutRef(name, putref);
+
+ if (ComBinderHelpers.PreferPut(limitType, holdsNull)) {
+ method = put;
+ } else {
+ method = putref;
+ }
+ return true;
+ } else if (hresult == ComHresults.DISP_E_UNKNOWNNAME) {
+ method = null;
+ return false;
+ } else {
+ throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{1:X})", hresult));
+ }
+ }
+
+ internal override IList<string> GetMemberNames(bool dataOnly) {
+ EnsureScanDefinedMethods();
+ EnsureScanDefinedEvents();
+
+ return ComTypeDesc.GetMemberNames(dataOnly);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ internal override IList<KeyValuePair<string, object>> GetMembers(IEnumerable<string> names) {
+ if (names == null) {
+ names = GetMemberNames(true);
+ }
+
+ Type comType = RuntimeCallableWrapper.GetType();
+
+ var members = new List<KeyValuePair<string, object>>();
+ foreach (string name in names) {
+ if (name == null) {
+ continue;
+ }
+
+ ComMethodDesc method;
+ if (ComTypeDesc.TryGetFunc(name, out method) && method.IsDataMember) {
+ try {
+ object value = comType.InvokeMember(
+ method.Name,
+ BindingFlags.GetProperty,
+ null,
+ RuntimeCallableWrapper,
+ new object[0],
+ CultureInfo.InvariantCulture
+ );
+ members.Add(new KeyValuePair<string, object>(method.Name, value));
+
+ //evaluation failed for some reason. pass exception out
+ } catch (Exception ex) {
+ members.Add(new KeyValuePair<string, object>(method.Name, ex));
+ }
+ }
+ }
+
+ return members.ToArray();
+ }
+
+ DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
+ EnsureScanDefinedMethods();
+ return new IDispatchMetaObject(parameter, this);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [SecurityCritical]
+ private static void GetFuncDescForDescIndex(ComTypes.ITypeInfo typeInfo, int funcIndex, out ComTypes.FUNCDESC funcDesc, out IntPtr funcDescHandle) {
+ IntPtr pFuncDesc = IntPtr.Zero;
+ typeInfo.GetFuncDesc(funcIndex, out pFuncDesc);
+
+ // GetFuncDesc should never return null, this is just to be safe
+ if (pFuncDesc == IntPtr.Zero) {
+ throw Error.CannotRetrieveTypeInformation();
+ }
+
+ funcDesc = (ComTypes.FUNCDESC)Marshal.PtrToStructure(pFuncDesc, typeof(ComTypes.FUNCDESC));
+ funcDescHandle = pFuncDesc;
+ }
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ private void EnsureScanDefinedEvents() {
+ // _comTypeDesc.Events is null if we have not yet attempted
+ // to scan the object for events.
+ if (_comTypeDesc != null && _comTypeDesc.Events != null) {
+ return;
+ }
+
+ //
+ // Demand Full Trust to proceed with the operation.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ // check type info in the type descriptions cache
+ ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(_dispatchObject, true);
+ if (typeInfo == null) {
+ _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc();
+ return;
+ }
+
+ ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);
+
+ if (_comTypeDesc == null) {
+ lock (_CacheComTypeDesc) {
+ if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true &&
+ _comTypeDesc.Events != null) {
+ return;
+ }
+ }
+ }
+
+ ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr);
+
+ ComTypes.ITypeInfo classTypeInfo = null;
+ Dictionary<string, ComEventDesc> events = null;
+
+ var cpc = RuntimeCallableWrapper as ComTypes.IConnectionPointContainer;
+ if (cpc == null) {
+ // No ICPC - this object does not support events
+ events = ComTypeDesc.EmptyEvents;
+ } else if ((classTypeInfo = GetCoClassTypeInfo(this.RuntimeCallableWrapper, typeInfo)) == null) {
+ // no class info found - this object may support events
+ // but we could not discover those
+ events = ComTypeDesc.EmptyEvents;
+ } else {
+ events = new Dictionary<string, ComEventDesc>();
+
+ ComTypes.TYPEATTR classTypeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(classTypeInfo);
+ for (int i = 0; i < classTypeAttr.cImplTypes; i++) {
+ int hRefType;
+ classTypeInfo.GetRefTypeOfImplType(i, out hRefType);
+
+ ComTypes.ITypeInfo interfaceTypeInfo;
+ classTypeInfo.GetRefTypeInfo(hRefType, out interfaceTypeInfo);
+
+ ComTypes.IMPLTYPEFLAGS flags;
+ classTypeInfo.GetImplTypeFlags(i, out flags);
+ if ((flags & ComTypes.IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0) {
+ ScanSourceInterface(interfaceTypeInfo, ref events);
+ }
+ }
+
+ if (events.Count == 0) {
+ events = ComTypeDesc.EmptyEvents;
+ }
+ }
+
+ lock (_CacheComTypeDesc) {
+ ComTypeDesc cachedTypeDesc;
+ if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) {
+ _comTypeDesc = cachedTypeDesc;
+ } else {
+ _comTypeDesc = typeDesc;
+ _CacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc);
+ }
+ _comTypeDesc.Events = events;
+ }
+ }
+
+ [SecurityCritical]
+ private static void ScanSourceInterface(ComTypes.ITypeInfo sourceTypeInfo, ref Dictionary<string, ComEventDesc> events) {
+ ComTypes.TYPEATTR sourceTypeAttribute = ComRuntimeHelpers.GetTypeAttrForTypeInfo(sourceTypeInfo);
+
+ for (int index = 0; index < sourceTypeAttribute.cFuncs; index++) {
+ IntPtr funcDescHandleToRelease = IntPtr.Zero;
+
+ try {
+ ComTypes.FUNCDESC funcDesc;
+ GetFuncDescForDescIndex(sourceTypeInfo, index, out funcDesc, out funcDescHandleToRelease);
+
+ // we are not interested in hidden or restricted functions for now.
+ if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FHIDDEN) != 0) {
+ continue;
+ }
+ if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) {
+ continue;
+ }
+
+ string name = ComRuntimeHelpers.GetNameOfMethod(sourceTypeInfo, funcDesc.memid);
+ name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+
+ // Sometimes coclass has multiple source interfaces. Usually this is caused by
+ // adding new events and putting them on new interfaces while keeping the
+ // old interfaces around. This may cause name collisioning which we are
+ // resolving by keeping only the first event with the same name.
+ if (events.ContainsKey(name) == false) {
+ ComEventDesc eventDesc = new ComEventDesc();
+ eventDesc.dispid = funcDesc.memid;
+ eventDesc.sourceIID = sourceTypeAttribute.guid;
+ events.Add(name, eventDesc);
+ }
+ } finally {
+ if (funcDescHandleToRelease != IntPtr.Zero) {
+ sourceTypeInfo.ReleaseFuncDesc(funcDescHandleToRelease);
+ }
+ }
+ }
+ }
+
+ [SecurityCritical]
+ private static ComTypes.ITypeInfo GetCoClassTypeInfo(object rcw, ComTypes.ITypeInfo typeInfo) {
+ Debug.Assert(typeInfo != null);
+
+ IProvideClassInfo provideClassInfo = rcw as IProvideClassInfo;
+ if (provideClassInfo != null) {
+ IntPtr typeInfoPtr = IntPtr.Zero;
+ try {
+ provideClassInfo.GetClassInfo(out typeInfoPtr);
+ if (typeInfoPtr != IntPtr.Zero) {
+ return Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
+ }
+ } finally {
+ if (typeInfoPtr != IntPtr.Zero) {
+ Marshal.Release(typeInfoPtr);
+ }
+ }
+ }
+
+ // retrieving class information through IPCI has failed -
+ // we can try scanning the typelib to find the coclass
+
+ ComTypes.ITypeLib typeLib;
+ int typeInfoIndex;
+ typeInfo.GetContainingTypeLib(out typeLib, out typeInfoIndex);
+ string typeName = ComRuntimeHelpers.GetNameOfType(typeInfo);
+
+ ComTypeLibDesc typeLibDesc = ComTypeLibDesc.GetFromTypeLib(typeLib);
+ ComTypeClassDesc coclassDesc = typeLibDesc.GetCoClassForInterface(typeName);
+ if (coclassDesc == null) {
+ return null;
+ }
+
+ ComTypes.ITypeInfo typeInfoCoClass;
+ Guid coclassGuid = coclassDesc.Guid;
+ typeLib.GetTypeInfoOfGuid(ref coclassGuid, out typeInfoCoClass);
+ return typeInfoCoClass;
+ }
+
+#if MICROSOFT_DYNAMIC
+ [SecurityCritical, SecurityTreatAsSafe]
+#else
+ [SecuritySafeCritical]
+#endif
+ private void EnsureScanDefinedMethods() {
+ if (_comTypeDesc != null && _comTypeDesc.Funcs != null) {
+ return;
+ }
+
+ //
+ // Demand Full Trust to proceed with the operation.
+ //
+
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+
+ ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(_dispatchObject, true);
+ if (typeInfo == null) {
+ _comTypeDesc = ComTypeDesc.CreateEmptyTypeDesc();
+ return;
+ }
+
+ ComTypes.TYPEATTR typeAttr = ComRuntimeHelpers.GetTypeAttrForTypeInfo(typeInfo);
+
+ if (_comTypeDesc == null) {
+ lock (_CacheComTypeDesc) {
+ if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out _comTypeDesc) == true &&
+ _comTypeDesc.Funcs != null) {
+ return;
+ }
+ }
+ }
+
+ ComTypeDesc typeDesc = ComTypeDesc.FromITypeInfo(typeInfo, typeAttr);
+
+ ComMethodDesc getItem = null;
+ ComMethodDesc setItem = null;
+ Hashtable funcs = new Hashtable(typeAttr.cFuncs);
+ Hashtable puts = new Hashtable();
+ Hashtable putrefs = new Hashtable();
+
+ for (int definedFuncIndex = 0; definedFuncIndex < typeAttr.cFuncs; definedFuncIndex++) {
+ IntPtr funcDescHandleToRelease = IntPtr.Zero;
+
+ try {
+ ComTypes.FUNCDESC funcDesc;
+ GetFuncDescForDescIndex(typeInfo, definedFuncIndex, out funcDesc, out funcDescHandleToRelease);
+
+ if ((funcDesc.wFuncFlags & (int)ComTypes.FUNCFLAGS.FUNCFLAG_FRESTRICTED) != 0) {
+ // This function is not meant for the script user to use.
+ continue;
+ }
+
+ ComMethodDesc method = new ComMethodDesc(typeInfo, funcDesc);
+ string name = method.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+
+ if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT) != 0) {
+ puts.Add(name, method);
+
+ // for the special dispId == 0, we need to store
+ // the method descriptor for the Do(SetItem) binder.
+ if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) {
+ setItem = method;
+ }
+ continue;
+ }
+ if ((funcDesc.invkind & ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF) != 0) {
+ putrefs.Add(name, method);
+ // for the special dispId == 0, we need to store
+ // the method descriptor for the Do(SetItem) binder.
+ if (method.DispId == ComDispIds.DISPID_VALUE && setItem == null) {
+ setItem = method;
+ }
+ continue;
+ }
+
+ if (funcDesc.memid == ComDispIds.DISPID_NEWENUM) {
+ funcs.Add("GETENUMERATOR", method);
+ continue;
+ }
+
+ funcs.Add(name, method);
+
+ // for the special dispId == 0, we need to store the method descriptor
+ // for the Do(GetItem) binder.
+ if (funcDesc.memid == ComDispIds.DISPID_VALUE) {
+ getItem = method;
+ }
+ } finally {
+ if (funcDescHandleToRelease != IntPtr.Zero) {
+ typeInfo.ReleaseFuncDesc(funcDescHandleToRelease);
+ }
+ }
+ }
+
+ lock (_CacheComTypeDesc) {
+ ComTypeDesc cachedTypeDesc;
+ if (_CacheComTypeDesc.TryGetValue(typeAttr.guid, out cachedTypeDesc)) {
+ _comTypeDesc = cachedTypeDesc;
+ } else {
+ _comTypeDesc = typeDesc;
+ _CacheComTypeDesc.Add(typeAttr.guid, _comTypeDesc);
+ }
+ _comTypeDesc.Funcs = funcs;
+ _comTypeDesc.Puts = puts;
+ _comTypeDesc.PutRefs = putrefs;
+ _comTypeDesc.EnsureGetItem(getItem);
+ _comTypeDesc.EnsureSetItem(setItem);
+ }
+ }
+
+ internal bool TryGetPropertySetter(string name, out ComMethodDesc method, Type limitType, bool holdsNull) {
+ EnsureScanDefinedMethods();
+
+ if (ComBinderHelpers.PreferPut(limitType, holdsNull)) {
+ return _comTypeDesc.TryGetPut(name, out method) ||
+ _comTypeDesc.TryGetPutRef(name, out method);
+ } else {
+ return _comTypeDesc.TryGetPutRef(name, out method) ||
+ _comTypeDesc.TryGetPut(name, out method);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchMetaObject.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchMetaObject.cs
new file mode 100644
index 00000000000..967086810a0
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/IDispatchMetaObject.cs
@@ -0,0 +1,273 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal sealed class IDispatchMetaObject : ComFallbackMetaObject {
+ private readonly IDispatchComObject _self;
+
+ internal IDispatchMetaObject(Expression expression, IDispatchComObject self)
+ : base(expression, BindingRestrictions.Empty, self) {
+ _self = self;
+ }
+
+ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ ComMethodDesc method;
+ if (_self.TryGetMemberMethod(binder.Name, out method) ||
+ _self.TryGetMemberMethodExplicit(binder.Name, out method)) {
+
+ bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref args);
+ return BindComInvoke(args, method, binder.CallInfo, isByRef);
+ }
+
+ return base.BindInvokeMember(binder, args);
+ }
+
+ public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ ComMethodDesc method;
+ if (_self.TryGetGetItem(out method)) {
+
+ bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref args);
+ return BindComInvoke(args, method, binder.CallInfo, isByRef);
+ }
+
+ return base.BindInvoke(binder, args);
+ }
+
+ private DynamicMetaObject BindComInvoke(DynamicMetaObject[] args, ComMethodDesc method, CallInfo callInfo, bool[] isByRef) {
+ return new ComInvokeBinder(
+ callInfo,
+ args,
+ isByRef,
+ IDispatchRestriction(),
+ Expression.Constant(method),
+ Expression.Property(
+ Helpers.Convert(Expression, typeof(IDispatchComObject)),
+ typeof(IDispatchComObject).GetProperty("DispatchObject")
+ ),
+ method
+ ).Invoke();
+ }
+
+ public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
+ ComBinder.ComGetMemberBinder comBinder = binder as ComBinder.ComGetMemberBinder;
+ bool canReturnCallables = comBinder == null ? false : comBinder._CanReturnCallables;
+
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ ComMethodDesc method;
+ ComEventDesc @event;
+
+ // 1. Try methods
+ if (_self.TryGetMemberMethod(binder.Name, out method)) {
+ return BindGetMember(method, canReturnCallables);
+ }
+
+ // 2. Try events
+ if (_self.TryGetMemberEvent(binder.Name, out @event)) {
+ return BindEvent(@event);
+ }
+
+ // 3. Try methods explicitly by name
+ if (_self.TryGetMemberMethodExplicit(binder.Name, out method)) {
+ return BindGetMember(method, canReturnCallables);
+
+ }
+
+ // 4. Fallback
+ return base.BindGetMember(binder);
+ }
+
+ private DynamicMetaObject BindGetMember(ComMethodDesc method, bool canReturnCallables) {
+ if (method.IsDataMember) {
+ if (method.ParamCount == 0) {
+ return BindComInvoke(DynamicMetaObject.EmptyMetaObjects, method, new CallInfo(0) , new bool[]{});
+ }
+ }
+
+ // ComGetMemberBinder does not expect callables. Try to call always.
+ if (!canReturnCallables) {
+ return BindComInvoke(DynamicMetaObject.EmptyMetaObjects, method, new CallInfo(0), new bool[0]);
+ }
+
+ return new DynamicMetaObject(
+ Expression.Call(
+ typeof(ComRuntimeHelpers).GetMethod("CreateDispCallable"),
+ Helpers.Convert(Expression, typeof(IDispatchComObject)),
+ Expression.Constant(method)
+ ),
+ IDispatchRestriction()
+ );
+ }
+
+ private DynamicMetaObject BindEvent(ComEventDesc @event) {
+ // BoundDispEvent CreateComEvent(object rcw, Guid sourceIid, int dispid)
+ Expression result =
+ Expression.Call(
+ typeof(ComRuntimeHelpers).GetMethod("CreateComEvent"),
+ ComObject.RcwFromComObject(Expression),
+ Expression.Constant(@event.sourceIID),
+ Expression.Constant(@event.dispid)
+ );
+
+ return new DynamicMetaObject(
+ result,
+ IDispatchRestriction()
+ );
+ }
+
+ public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ ComMethodDesc getItem;
+ if (_self.TryGetGetItem(out getItem)) {
+
+ bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref indexes);
+ return BindComInvoke(indexes, getItem, binder.CallInfo , isByRef);
+ }
+
+ return base.BindGetIndex(binder, indexes);
+ }
+
+ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ ComMethodDesc setItem;
+ if (_self.TryGetSetItem(out setItem)) {
+
+ bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(ref indexes);
+ isByRef = isByRef.AddLast(false);
+
+ var result = BindComInvoke(indexes.AddLast(value), setItem, binder.CallInfo, isByRef);
+
+ // Make sure to return the value; some languages need it.
+ return new DynamicMetaObject(
+ Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))),
+ result.Restrictions
+ );
+ }
+
+ return base.BindSetIndex(binder, indexes, value);
+ }
+
+ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ return
+ // 1. Check for simple property put
+ TryPropertyPut(binder, value) ??
+
+ // 2. Check for event handler hookup where the put is dropped
+ TryEventHandlerNoop(binder, value) ??
+
+ // 3. Fallback
+ base.BindSetMember(binder, value);
+ }
+
+ private DynamicMetaObject TryPropertyPut(SetMemberBinder binder, DynamicMetaObject value) {
+ ComMethodDesc method;
+ bool holdsNull = value.Value == null && value.HasValue;
+ if (_self.TryGetPropertySetter(binder.Name, out method, value.LimitType, holdsNull) ||
+ _self.TryGetPropertySetterExplicit(binder.Name, out method, value.LimitType, holdsNull)) {
+ BindingRestrictions restrictions = IDispatchRestriction();
+ Expression dispatch =
+ Expression.Property(
+ Helpers.Convert(Expression, typeof(IDispatchComObject)),
+ typeof(IDispatchComObject).GetProperty("DispatchObject")
+ );
+
+ var result = new ComInvokeBinder(
+ new CallInfo(1),
+ new[] { value },
+ new bool[] { false },
+ restrictions,
+ Expression.Constant(method),
+ dispatch,
+ method
+ ).Invoke();
+
+ // Make sure to return the value; some languages need it.
+ return new DynamicMetaObject(
+ Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))),
+ result.Restrictions
+ );
+ }
+
+ return null;
+ }
+
+ private DynamicMetaObject TryEventHandlerNoop(SetMemberBinder binder, DynamicMetaObject value) {
+ ComEventDesc @event;
+ if (_self.TryGetMemberEvent(binder.Name, out @event) && value.LimitType == typeof(BoundDispEvent)) {
+ // Drop the event property set.
+ return new DynamicMetaObject(
+ Expression.Constant(null),
+ value.Restrictions.Merge(IDispatchRestriction()).Merge(BindingRestrictions.GetTypeRestriction(value.Expression, typeof(BoundDispEvent)))
+ );
+ }
+
+ return null;
+ }
+
+ private BindingRestrictions IDispatchRestriction() {
+ return IDispatchRestriction(Expression, _self.ComTypeDesc);
+ }
+
+ internal static BindingRestrictions IDispatchRestriction(Expression expr, ComTypeDesc typeDesc) {
+ return BindingRestrictions.GetTypeRestriction(
+ expr, typeof(IDispatchComObject)
+ ).Merge(
+ BindingRestrictions.GetExpressionRestriction(
+ Expression.Equal(
+ Expression.Property(
+ Helpers.Convert(expr, typeof(IDispatchComObject)),
+ typeof(IDispatchComObject).GetProperty("ComTypeDesc")
+ ),
+ Expression.Constant(typeDesc)
+ )
+ )
+ );
+ }
+
+ protected override ComUnwrappedMetaObject UnwrapSelf() {
+ return new ComUnwrappedMetaObject(
+ ComObject.RcwFromComObject(Expression),
+ IDispatchRestriction(),
+ _self.RuntimeCallableWrapper
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Microsoft.Dynamic.csproj b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Microsoft.Dynamic.csproj
new file mode 100644
index 00000000000..f799b702cdb
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Microsoft.Dynamic.csproj
@@ -0,0 +1,134 @@
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{D4AE44AD-07B9-41DC-BB3B-1FDCDE3C987D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <RootNamespace>System.Dynamic</RootNamespace>
+ <AssemblyName>Microsoft.Dynamic</AssemblyName>
+<DocumentationFile>$(OutputPath)\Microsoft.Dynamic.XML</DocumentationFile>
+ <NoWarn>1591</NoWarn>
+<AssemblyOriginatorKeyFile>$(SolutionDir)\Runtime\MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly Condition="'$(SignAssembly)' == '' And Exists('$(AssemblyOriginatorKeyFile)')">true</SignAssembly>
+ <SignedSym Condition="'$(SignAssembly)' == 'true'">SIGNED</SignedSym>
+ <DelaySign>true</DelaySign>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FxCop|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\fxcop\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym);MICROSOFT_DYNAMIC</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <CodeAnalysisRules>-Microsoft.Usage#CA2209;+!Microsoft.Design#CA1012;-!Microsoft.Design#CA2210;+!Microsoft.Design#CA1040;+!Microsoft.Design#CA1005;+!Microsoft.Design#CA1020;-!Microsoft.Design#CA1021;+!Microsoft.Design#CA1010;+!Microsoft.Design#CA1011;+!Microsoft.Design#CA1009;+!Microsoft.Design#CA1050;+!Microsoft.Design#CA1026;+!Microsoft.Design#CA1019;+!Microsoft.Design#CA1031;+!Microsoft.Design#CA1047;+!Microsoft.Design#CA1000;+!Microsoft.Design#CA1048;+!Microsoft.Design#CA1051;+!Microsoft.Design#CA1002;+!Microsoft.Design#CA1061;+!Microsoft.Design#CA1006;+!Microsoft.Design#CA1046;+!Microsoft.Design#CA1045;+!Microsoft.Design#CA1065;+!Microsoft.Design#CA1038;+!Microsoft.Design#CA1008;+!Microsoft.Design#CA1028;+!Microsoft.Design#CA1064;-!Microsoft.Design#CA1004;+!Microsoft.Design#CA1035;+!Microsoft.Design#CA1063;+!Microsoft.Design#CA1032;+!Microsoft.Design#CA1023;+!Microsoft.Design#CA1033;+!Microsoft.Design#CA1039;+!Microsoft.Design#CA1016;+!Microsoft.Design#CA1014;+!Microsoft.Design#CA1017;+!Microsoft.Design#CA1018;+!Microsoft.Design#CA1027;+!Microsoft.Design#CA1059;+!Microsoft.Design#CA1060;+!Microsoft.Design#CA1034;+!Microsoft.Design#CA1013;+!Microsoft.Design#CA1036;+!Microsoft.Design#CA1044;+!Microsoft.Design#CA1041;+!Microsoft.Design#CA1025;+!Microsoft.Design#CA1052;+!Microsoft.Design#CA1053;+!Microsoft.Design#CA1057;+!Microsoft.Design#CA1058;+!Microsoft.Design#CA1001;+!Microsoft.Design#CA1049;+!Microsoft.Design#CA1054;+!Microsoft.Design#CA1056;+!Microsoft.Design#CA1055;+!Microsoft.Design#CA1030;+!Microsoft.Design#CA1003;+!Microsoft.Design#CA1007;+!Microsoft.Design#CA1043;+!Microsoft.Design#CA1024;+!Microsoft.Globalization#CA1301;+!Microsoft.Globalization#CA1302;+!Microsoft.Globalization#CA1308;+!Microsoft.Globalization#CA1306;+!Microsoft.Globalization#CA1304;+!Microsoft.Globalization#CA1305;+!Microsoft.Globalization#CA2101;+!Microsoft.Globalization#CA1300;+!Microsoft.Globalization#CA1307;+!Microsoft.Globalization#CA1309;+!Microsoft.Interoperability#CA1403;+!Microsoft.Interoperability#CA1406;+!Microsoft.Interoperability#CA1413;+!Microsoft.Interoperability#CA1402;+!Microsoft.Interoperability#CA1407;+!Microsoft.Interoperability#CA1404;+!Microsoft.Interoperability#CA1410;+!Microsoft.Interoperability#CA1411;+!Microsoft.Interoperability#CA1405;+!Microsoft.Interoperability#CA1409;+!Microsoft.Interoperability#CA1415;+!Microsoft.Interoperability#CA1408;+!Microsoft.Interoperability#CA1414;+!Microsoft.Interoperability#CA1412;+!Microsoft.Interoperability#CA1400;+!Microsoft.Interoperability#CA1401;+!Microsoft.Maintainability#CA1506;+!Microsoft.Maintainability#CA1502;+!Microsoft.Maintainability#CA1501;+!Microsoft.Maintainability#CA1505;+!Microsoft.Maintainability#CA1504;+!Microsoft.Maintainability#CA1500;+!Microsoft.Mobility#CA1600;+!Microsoft.Mobility#CA1601;-!Microsoft.Naming#CA1702;+!Microsoft.Naming#CA1700;+!Microsoft.Naming#CA1712;+!Microsoft.Naming#CA1713;+!Microsoft.Naming#CA1714;+!Microsoft.Naming#CA1709;-!Microsoft.Naming#CA1704;+!Microsoft.Naming#CA1708;+!Microsoft.Naming#CA1715;-!Microsoft.Naming#CA1710;+!Microsoft.Naming#CA1720;+!Microsoft.Naming#CA1707;+!Microsoft.Naming#CA1722;-!Microsoft.Naming#CA1711;+!Microsoft.Naming#CA1716;+!Microsoft.Naming#CA1717;+!Microsoft.Naming#CA1725;+!Microsoft.Naming#CA1719;+!Microsoft.Naming#CA1721;+!Microsoft.Naming#CA1701;+!Microsoft.Naming#CA1703;+!Microsoft.Naming#CA1724;-!Microsoft.Naming#CA1726;+!Microsoft.Performance#CA1809;+!Microsoft.Performance#CA1811;+!Microsoft.Performance#CA1812;+!Microsoft.Performance#CA1813;+!Microsoft.Performance#CA1823;+!Microsoft.Performance#CA1800;+!Microsoft.Performance#CA1805;+!Microsoft.Performance#CA1810;+!Microsoft.Performance#CA1824;+!Microsoft.Performance#CA1822;+!Microsoft.Performance#CA1815;+!Microsoft.Performance#CA1814;+!Microsoft.Performance#CA1819;+!Microsoft.Performance#CA1821;+!Microsoft.Performance#CA1804;+!Microsoft.Performance#CA1820;+!Microsoft.Performance#CA1802;+!Microsoft.Portability#CA1901;+!Microsoft.Portability#CA1900;+!Microsoft.Reliability#CA2001;+!Microsoft.Reliability#CA2002;+!Microsoft.Reliability#CA2003;+!Microsoft.Reliability#CA2004;+!Microsoft.Reliability#CA2006;+!Microsoft.Security#CA2116;+!Microsoft.Security#CA2117;+!Microsoft.Security#CA2105;+!Microsoft.Security#CA2115;+!Microsoft.Security#CA2102;+!Microsoft.Security#CA2104;+!Microsoft.Security#CA2122;+!Microsoft.Security#CA2114;+!Microsoft.Security#CA2123;+!Microsoft.Security#CA2111;+!Microsoft.Security#CA2108;+!Microsoft.Security#CA2107;+!Microsoft.Security#CA2103;+!Microsoft.Security#CA2118;+!Microsoft.Security#CA2109;+!Microsoft.Security#CA2119;+!Microsoft.Security#CA2106;+!Microsoft.Security#CA2112;+!Microsoft.Security#CA2120;+!Microsoft.Security#CA2121;+!Microsoft.Security#CA2126;+!Microsoft.Security#CA2124;+!Microsoft.Security#CA2127;+!Microsoft.Security#CA2128;+!Microsoft.Security#CA2129;+!Microsoft.Usage#CA2243;+!Microsoft.Usage#CA2236;+!Microsoft.Usage#CA1816;+!Microsoft.Usage#CA2227;+!Microsoft.Usage#CA2213;+!Microsoft.Usage#CA2216;+!Microsoft.Usage#CA2214;+!Microsoft.Usage#CA2222;+!Microsoft.Usage#CA1806;+!Microsoft.Usage#CA2217;+!Microsoft.Usage#CA2212;+!Microsoft.Usage#CA2219;+!Microsoft.Usage#CA2201;+!Microsoft.Usage#CA2228;+!Microsoft.Usage#CA2221;+!Microsoft.Usage#CA2220;+!Microsoft.Usage#CA2240;+!Microsoft.Usage#CA2229;+!Microsoft.Usage#CA2238;+!Microsoft.Usage#CA2207;+!Microsoft.Usage#CA2208;+!Microsoft.Usage#CA2235;+!Microsoft.Usage#CA2237;+!Microsoft.Usage#CA2232;+!Microsoft.Usage#CA2223;+!Microsoft.Usage#CA2211;+!Microsoft.Usage#CA2233;+!Microsoft.Usage#CA2225;+!Microsoft.Usage#CA2226;+!Microsoft.Usage#CA2231;+!Microsoft.Usage#CA2224;+!Microsoft.Usage#CA2218;+!Microsoft.Usage#CA2234;+!Microsoft.Usage#CA2239;+!Microsoft.Usage#CA2200;+!Microsoft.Usage#CA1801;+!Microsoft.Usage#CA2242;+!Microsoft.Usage#CA2205;+!Microsoft.Usage#CA2230</CodeAnalysisRules>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Debug\</OutputPath>
+<DocumentationFile>$(OutputPath)\Microsoft.Dynamic.xml</DocumentationFile>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym);MICROSOFT_DYNAMIC</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Release\</OutputPath>
+<DocumentationFile>$(OutputPath)\Microsoft.Dynamic.XML</DocumentationFile>
+ <DefineConstants>TRACE;$(SignedSym);MICROSOFT_DYNAMIC</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <BaseAddress>1929379840</BaseAddress>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Microsoft.Scripting.Core\Microsoft.Scripting.Core.csproj">
+ <Project>{2AE75F5A-CD1F-4925-9647-AF4D1C282FB4}</Project>
+ <Name>Microsoft.Scripting.Core</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\Microsoft.Scripting.Core\Microsoft.Scripting.ExtensionAttribute.csproj">
+ <Project>{8B0F1074-750E-4D64-BF23-A1E0F54261E5}</Project>
+ <Name>Microsoft.Scripting.ExtensionAttribute</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ConvertArgBuilder.cs" />
+ <Compile Include="Properties\GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ArgBuilder.cs" />
+ <Compile Include="Assert.cs" />
+ <Compile Include="BoolArgBuilder.cs" />
+ <Compile Include="BoundDispEvent.cs" />
+ <Compile Include="CollectionExtensions.cs" />
+ <Compile Include="ComBinder.cs" />
+ <Compile Include="ComBinderHelpers.cs" />
+ <Compile Include="ComDispIds.cs" />
+ <Compile Include="ComEventDesc.cs" />
+ <Compile Include="ComEventSink.cs" />
+ <Compile Include="ComEventSinkProxy.cs" />
+ <Compile Include="ComEventSinksContainer.cs" />
+ <Compile Include="ComFallbackMetaObject.cs" />
+ <Compile Include="ComHresults.cs" />
+ <Compile Include="ComInterop.cs" />
+ <Compile Include="ComInvokeAction.cs" />
+ <Compile Include="ComInvokeBinder.cs" />
+ <Compile Include="ComMetaObject.cs" />
+ <Compile Include="ComMethodDesc.cs" />
+ <Compile Include="ComObject.cs" />
+ <Compile Include="ComRuntimeHelpers.cs" />
+ <Compile Include="ComTypeClassDesc.cs" />
+ <Compile Include="ComTypeDesc.cs" />
+ <Compile Include="ComTypeEnumDesc.cs" />
+ <Compile Include="ComTypeLibDesc.cs" />
+ <Compile Include="ContractUtils.cs" />
+ <Compile Include="ConversionArgBuilder.cs" />
+ <Compile Include="ConvertibleArgBuilder.cs" />
+ <Compile Include="CurrencyArgBuilder.cs" />
+ <Compile Include="DateTimeArgBuilder.cs" />
+ <Compile Include="DispatchArgBuilder.cs" />
+ <Compile Include="DispCallable.cs" />
+ <Compile Include="DispCallableMetaObject.cs" />
+ <Compile Include="Errors.cs" />
+ <Compile Include="ErrorArgBuilder.cs" />
+ <Compile Include="ExcepInfo.cs" />
+ <Compile Include="Helpers.cs" />
+ <Compile Include="IDispatchComObject.cs" />
+ <Compile Include="IDispatchMetaObject.cs" />
+ <Compile Include="NullArgBuilder.cs" />
+ <Compile Include="SimpleArgBuilder.cs" />
+ <Compile Include="SplatCallSite.cs" />
+ <Compile Include="StringArgBuilder.cs" />
+ <Compile Include="TypeUtils.cs" />
+ <Compile Include="UnknownArgBuilder.cs" />
+ <Compile Include="VarEnumSelector.cs" />
+ <Compile Include="Variant.cs" />
+ <Compile Include="VariantArgBuilder.cs" />
+ <Compile Include="VariantArray.cs" />
+ <Compile Include="VariantBuilder.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/NullArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/NullArgBuilder.cs
new file mode 100644
index 00000000000..11e48775c3c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/NullArgBuilder.cs
@@ -0,0 +1,45 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// ArgBuilder which always produces null.
+ /// </summary>
+ internal sealed class NullArgBuilder : ArgBuilder {
+ internal NullArgBuilder() { }
+
+ internal override Expression Marshal(Expression parameter) {
+ return Expression.Constant(null);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/AssemblyInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..f7c7effa408
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/AssemblyInfo.cs
@@ -0,0 +1,79 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Runtime.InteropServices;
+using System.Security;
+
+#if MICROSOFT_DYNAMIC
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Dynamic.ComInterop")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Microsoft.Dynamic.ComInterop")]
+[assembly: AssemblyCopyright("� Microsoft Corporation. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+[assembly: CLSCompliant(true)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: System.Resources.NeutralResourcesLanguage("en-US")]
+
+[assembly: AssemblyVersion("0.9.6.10")]
+[assembly: AssemblyFileVersion("1.0.0.00")]
+[assembly: AssemblyInformationalVersion("1.0")]
+[assembly: AllowPartiallyTrustedCallers]
+#if CODEPLEX_40
+[assembly: SecurityRules(SecurityRuleSet.Level1)]
+#endif
+
+#else
+
+[assembly: InternalsVisibleTo("Microsoft.CSharp, PublicKey =" +
+ "002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9" +
+ "f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad2361321" +
+ "02900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93" +
+ "c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc09334" +
+ "4d5ad293")]
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/GlobalSuppressions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/GlobalSuppressions.cs
new file mode 100644
index 00000000000..253f679b7e6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Properties/GlobalSuppressions.cs
@@ -0,0 +1,17 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.SR.#GetObject(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.SR.#GetString(System.String,System.Boolean&)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.SR.#Resources")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.Error.#ArgumentNull(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.Error.#ArgumentOutOfRange(System.String)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.Error.#NotImplemented()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Dynamic.Error.#NotSupported()")]
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/SimpleArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/SimpleArgBuilder.cs
new file mode 100644
index 00000000000..f5734224567
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/SimpleArgBuilder.cs
@@ -0,0 +1,61 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// SimpleArgBuilder produces the value produced by the user as the argument value. It
+ /// also tracks information about the original parameter and is used to create extended
+ /// methods for params arrays and param dictionary functions.
+ /// </summary>
+ internal class SimpleArgBuilder : ArgBuilder {
+ private readonly Type _parameterType;
+
+ internal SimpleArgBuilder(Type parameterType) {
+ _parameterType = parameterType;
+ }
+
+ internal Type ParameterType {
+ get { return _parameterType; }
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ Debug.Assert(parameter != null);
+ return Helpers.Convert(parameter, _parameterType);
+ }
+
+ internal override Expression UnmarshalFromRef(Expression newValue) {
+ Debug.Assert(newValue != null && newValue.Type.IsAssignableFrom(_parameterType));
+
+ return base.UnmarshalFromRef(newValue);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/SplatCallSite.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/SplatCallSite.cs
new file mode 100644
index 00000000000..548373b3d6d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/SplatCallSite.cs
@@ -0,0 +1,67 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal sealed class SplatCallSite {
+ // Stored callable Delegate or IDynamicMetaObjectProvider.
+ internal readonly object _callable;
+
+ // Can the number of arguments to a given event change each call?
+ // If not, we don't need this level of indirection--we could cache a
+ // delegate that does the splatting.
+ internal CallSite<Func<CallSite, object, object[], object>> _site;
+
+ internal SplatCallSite(object callable) {
+ Debug.Assert(callable != null);
+ _callable = callable;
+ }
+
+ internal object Invoke(object[] args) {
+ Debug.Assert(args != null);
+
+ // If it is a delegate, just let DynamicInvoke do the binding.
+ var d = _callable as Delegate;
+ if (d != null) {
+ return d.DynamicInvoke(args);
+ }
+
+ // Otherwise, create a CallSite and invoke it.
+ if (_site == null) {
+ _site = CallSite<Func<CallSite, object, object[], object>>.Create(SplatInvokeBinder.Instance);
+ }
+
+ return _site.Target(_site, _callable, args);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/StringArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/StringArgBuilder.cs
new file mode 100644
index 00000000000..f93f23c33cc
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/StringArgBuilder.cs
@@ -0,0 +1,100 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal class StringArgBuilder : SimpleArgBuilder {
+ private readonly bool _isWrapper;
+
+ internal StringArgBuilder(Type parameterType)
+ : base(parameterType) {
+
+ Debug.Assert(parameterType == typeof(string) ||
+ parameterType == typeof(BStrWrapper));
+
+ _isWrapper = parameterType == typeof(BStrWrapper);
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ parameter = base.Marshal(parameter);
+
+ // parameter.WrappedObject
+ if (_isWrapper) {
+ parameter = Expression.Property(
+ Helpers.Convert(parameter, typeof(BStrWrapper)),
+ typeof(BStrWrapper).GetProperty("WrappedObject")
+ );
+ };
+
+ return parameter;
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ parameter = Marshal(parameter);
+
+
+ // Marshal.StringToBSTR(parameter)
+ return Expression.Call(
+ typeof(Marshal).GetMethod("StringToBSTR"),
+ parameter
+ );
+ }
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // value == IntPtr.Zero ? null : Marshal.PtrToStringBSTR(value);
+ Expression unmarshal = Expression.Condition(
+ Expression.Equal(value, Expression.Constant(IntPtr.Zero)),
+ Expression.Constant(null, typeof(string)), // default value
+ Expression.Call(
+ typeof(Marshal).GetMethod("PtrToStringBSTR"),
+ value
+ )
+ );
+
+ if (_isWrapper) {
+ unmarshal = Expression.New(
+ typeof(BStrWrapper).GetConstructor(new Type[] { typeof(string) }),
+ unmarshal
+ );
+ };
+
+ return base.UnmarshalFromRef(unmarshal);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.csproj b/mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.csproj
new file mode 100644
index 00000000000..45abeb113ff
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.csproj
@@ -0,0 +1,124 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+
+
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{D4AE44AD-07B9-41DC-BB3B-1FDCDE3C987D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <RootNamespace>System.Dynamic</RootNamespace>
+ <AssemblyName>System.Dynamic</AssemblyName>
+<DocumentationFile>$(OutputPath)\System.Dynamic.XML</DocumentationFile>
+ <NoWarn>1591</NoWarn>
+<AssemblyOriginatorKeyFile>$(SolutionDir)\Runtime\MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly Condition="'$(SignAssembly)' == '' And Exists('$(AssemblyOriginatorKeyFile)')">true</SignAssembly>
+ <SignedSym Condition="'$(SignAssembly)' == 'true'">SIGNED</SignedSym>
+ <DelaySign>true</DelaySign>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FxCop|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\fxcop\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym);MICROSOFT_SCRIPTING_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <CodeAnalysisRules>-Microsoft.Usage#CA2209;+!Microsoft.Design#CA1012;-!Microsoft.Design#CA2210;+!Microsoft.Design#CA1040;+!Microsoft.Design#CA1005;+!Microsoft.Design#CA1020;-!Microsoft.Design#CA1021;+!Microsoft.Design#CA1010;+!Microsoft.Design#CA1011;+!Microsoft.Design#CA1009;+!Microsoft.Design#CA1050;+!Microsoft.Design#CA1026;+!Microsoft.Design#CA1019;+!Microsoft.Design#CA1031;+!Microsoft.Design#CA1047;+!Microsoft.Design#CA1000;+!Microsoft.Design#CA1048;+!Microsoft.Design#CA1051;+!Microsoft.Design#CA1002;+!Microsoft.Design#CA1061;+!Microsoft.Design#CA1006;+!Microsoft.Design#CA1046;+!Microsoft.Design#CA1045;+!Microsoft.Design#CA1065;+!Microsoft.Design#CA1038;+!Microsoft.Design#CA1008;+!Microsoft.Design#CA1028;+!Microsoft.Design#CA1064;-!Microsoft.Design#CA1004;+!Microsoft.Design#CA1035;+!Microsoft.Design#CA1063;+!Microsoft.Design#CA1032;+!Microsoft.Design#CA1023;+!Microsoft.Design#CA1033;+!Microsoft.Design#CA1039;+!Microsoft.Design#CA1016;+!Microsoft.Design#CA1014;+!Microsoft.Design#CA1017;+!Microsoft.Design#CA1018;+!Microsoft.Design#CA1027;+!Microsoft.Design#CA1059;+!Microsoft.Design#CA1060;+!Microsoft.Design#CA1034;+!Microsoft.Design#CA1013;+!Microsoft.Design#CA1036;+!Microsoft.Design#CA1044;+!Microsoft.Design#CA1041;+!Microsoft.Design#CA1025;+!Microsoft.Design#CA1052;+!Microsoft.Design#CA1053;+!Microsoft.Design#CA1057;+!Microsoft.Design#CA1058;+!Microsoft.Design#CA1001;+!Microsoft.Design#CA1049;+!Microsoft.Design#CA1054;+!Microsoft.Design#CA1056;+!Microsoft.Design#CA1055;+!Microsoft.Design#CA1030;+!Microsoft.Design#CA1003;+!Microsoft.Design#CA1007;+!Microsoft.Design#CA1043;+!Microsoft.Design#CA1024;+!Microsoft.Globalization#CA1301;+!Microsoft.Globalization#CA1302;+!Microsoft.Globalization#CA1308;+!Microsoft.Globalization#CA1306;+!Microsoft.Globalization#CA1304;+!Microsoft.Globalization#CA1305;+!Microsoft.Globalization#CA2101;+!Microsoft.Globalization#CA1300;+!Microsoft.Globalization#CA1307;+!Microsoft.Globalization#CA1309;+!Microsoft.Interoperability#CA1403;+!Microsoft.Interoperability#CA1406;+!Microsoft.Interoperability#CA1413;+!Microsoft.Interoperability#CA1402;+!Microsoft.Interoperability#CA1407;+!Microsoft.Interoperability#CA1404;+!Microsoft.Interoperability#CA1410;+!Microsoft.Interoperability#CA1411;+!Microsoft.Interoperability#CA1405;+!Microsoft.Interoperability#CA1409;+!Microsoft.Interoperability#CA1415;+!Microsoft.Interoperability#CA1408;+!Microsoft.Interoperability#CA1414;+!Microsoft.Interoperability#CA1412;+!Microsoft.Interoperability#CA1400;+!Microsoft.Interoperability#CA1401;+!Microsoft.Maintainability#CA1506;+!Microsoft.Maintainability#CA1502;+!Microsoft.Maintainability#CA1501;+!Microsoft.Maintainability#CA1505;+!Microsoft.Maintainability#CA1504;+!Microsoft.Maintainability#CA1500;+!Microsoft.Mobility#CA1600;+!Microsoft.Mobility#CA1601;-!Microsoft.Naming#CA1702;+!Microsoft.Naming#CA1700;+!Microsoft.Naming#CA1712;+!Microsoft.Naming#CA1713;+!Microsoft.Naming#CA1714;+!Microsoft.Naming#CA1709;-!Microsoft.Naming#CA1704;+!Microsoft.Naming#CA1708;+!Microsoft.Naming#CA1715;-!Microsoft.Naming#CA1710;+!Microsoft.Naming#CA1720;+!Microsoft.Naming#CA1707;+!Microsoft.Naming#CA1722;-!Microsoft.Naming#CA1711;+!Microsoft.Naming#CA1716;+!Microsoft.Naming#CA1717;+!Microsoft.Naming#CA1725;+!Microsoft.Naming#CA1719;+!Microsoft.Naming#CA1721;+!Microsoft.Naming#CA1701;+!Microsoft.Naming#CA1703;+!Microsoft.Naming#CA1724;-!Microsoft.Naming#CA1726;+!Microsoft.Performance#CA1809;+!Microsoft.Performance#CA1811;+!Microsoft.Performance#CA1812;+!Microsoft.Performance#CA1813;+!Microsoft.Performance#CA1823;+!Microsoft.Performance#CA1800;+!Microsoft.Performance#CA1805;+!Microsoft.Performance#CA1810;+!Microsoft.Performance#CA1824;+!Microsoft.Performance#CA1822;+!Microsoft.Performance#CA1815;+!Microsoft.Performance#CA1814;+!Microsoft.Performance#CA1819;+!Microsoft.Performance#CA1821;+!Microsoft.Performance#CA1804;+!Microsoft.Performance#CA1820;+!Microsoft.Performance#CA1802;+!Microsoft.Portability#CA1901;+!Microsoft.Portability#CA1900;+!Microsoft.Reliability#CA2001;+!Microsoft.Reliability#CA2002;+!Microsoft.Reliability#CA2003;+!Microsoft.Reliability#CA2004;+!Microsoft.Reliability#CA2006;+!Microsoft.Security#CA2116;+!Microsoft.Security#CA2117;+!Microsoft.Security#CA2105;+!Microsoft.Security#CA2115;+!Microsoft.Security#CA2102;+!Microsoft.Security#CA2104;+!Microsoft.Security#CA2122;+!Microsoft.Security#CA2114;+!Microsoft.Security#CA2123;+!Microsoft.Security#CA2111;+!Microsoft.Security#CA2108;+!Microsoft.Security#CA2107;+!Microsoft.Security#CA2103;+!Microsoft.Security#CA2118;+!Microsoft.Security#CA2109;+!Microsoft.Security#CA2119;+!Microsoft.Security#CA2106;+!Microsoft.Security#CA2112;+!Microsoft.Security#CA2120;+!Microsoft.Security#CA2121;+!Microsoft.Security#CA2126;+!Microsoft.Security#CA2124;+!Microsoft.Security#CA2127;+!Microsoft.Security#CA2128;+!Microsoft.Security#CA2129;+!Microsoft.Usage#CA2243;+!Microsoft.Usage#CA2236;+!Microsoft.Usage#CA1816;+!Microsoft.Usage#CA2227;+!Microsoft.Usage#CA2213;+!Microsoft.Usage#CA2216;+!Microsoft.Usage#CA2214;+!Microsoft.Usage#CA2222;+!Microsoft.Usage#CA1806;+!Microsoft.Usage#CA2217;+!Microsoft.Usage#CA2212;+!Microsoft.Usage#CA2219;+!Microsoft.Usage#CA2201;+!Microsoft.Usage#CA2228;+!Microsoft.Usage#CA2221;+!Microsoft.Usage#CA2220;+!Microsoft.Usage#CA2240;+!Microsoft.Usage#CA2229;+!Microsoft.Usage#CA2238;+!Microsoft.Usage#CA2207;+!Microsoft.Usage#CA2208;+!Microsoft.Usage#CA2235;+!Microsoft.Usage#CA2237;+!Microsoft.Usage#CA2232;+!Microsoft.Usage#CA2223;+!Microsoft.Usage#CA2211;+!Microsoft.Usage#CA2233;+!Microsoft.Usage#CA2225;+!Microsoft.Usage#CA2226;+!Microsoft.Usage#CA2231;+!Microsoft.Usage#CA2224;+!Microsoft.Usage#CA2218;+!Microsoft.Usage#CA2234;+!Microsoft.Usage#CA2239;+!Microsoft.Usage#CA2200;+!Microsoft.Usage#CA1801;+!Microsoft.Usage#CA2242;+!Microsoft.Usage#CA2205;+!Microsoft.Usage#CA2230</CodeAnalysisRules>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Debug\</OutputPath>
+<DocumentationFile>$(OutputPath)\System.Dynamic.xml</DocumentationFile>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym);MICROSOFT_SCRIPTING_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Release\</OutputPath>
+<DocumentationFile>$(OutputPath)\System.Dynamic.XML</DocumentationFile>
+ <DefineConstants>TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <BaseAddress>1929379840</BaseAddress>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ArgBuilder.cs" />
+ <Compile Include="Assert.cs" />
+ <Compile Include="BoolArgBuilder.cs" />
+ <Compile Include="BoundDispEvent.cs" />
+ <Compile Include="CollectionExtensions.cs" />
+ <Compile Include="ComBinder.cs" />
+ <Compile Include="ComBinderHelpers.cs" />
+ <Compile Include="ComDispIds.cs" />
+ <Compile Include="ComEventDesc.cs" />
+ <Compile Include="ComEventSink.cs" />
+ <Compile Include="ComEventSinkProxy.cs" />
+ <Compile Include="ComEventSinksContainer.cs" />
+ <Compile Include="ComFallbackMetaObject.cs" />
+ <Compile Include="ComHresults.cs" />
+ <Compile Include="ComInterop.cs" />
+ <Compile Include="ComInvokeAction.cs" />
+ <Compile Include="ComInvokeBinder.cs" />
+ <Compile Include="ComMetaObject.cs" />
+ <Compile Include="ComMethodDesc.cs" />
+ <Compile Include="ComObject.cs" />
+ <Compile Include="ComRuntimeHelpers.cs" />
+ <Compile Include="ComTypeClassDesc.cs" />
+ <Compile Include="ComTypeDesc.cs" />
+ <Compile Include="ComTypeEnumDesc.cs" />
+ <Compile Include="ComTypeLibDesc.cs" />
+ <Compile Include="ContractUtils.cs" />
+ <Compile Include="ConversionArgBuilder.cs" />
+ <Compile Include="ConvertibleArgBuilder.cs" />
+ <Compile Include="CurrencyArgBuilder.cs" />
+ <Compile Include="DateTimeArgBuilder.cs" />
+ <Compile Include="DispatchArgBuilder.cs" />
+ <Compile Include="DispCallable.cs" />
+ <Compile Include="DispCallableMetaObject.cs" />
+ <Compile Include="Errors.cs" />
+ <Compile Include="ErrorArgBuilder.cs" />
+ <Compile Include="ExcepInfo.cs" />
+ <Compile Include="Helpers.cs" />
+ <Compile Include="IDispatchComObject.cs" />
+ <Compile Include="IDispatchMetaObject.cs" />
+ <Compile Include="NullArgBuilder.cs" />
+ <Compile Include="SimpleArgBuilder.cs" />
+ <Compile Include="SplatCallSite.cs" />
+ <Compile Include="StringArgBuilder.cs" />
+ <Compile Include="TypeUtils.cs" />
+ <Compile Include="UnknownArgBuilder.cs" />
+ <Compile Include="VarEnumSelector.cs" />
+ <Compile Include="Variant.cs" />
+ <Compile Include="VariantArgBuilder.cs" />
+ <Compile Include="VariantArray.cs" />
+ <Compile Include="VariantBuilder.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.txt b/mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.txt
new file mode 100644
index 00000000000..b76067884b4
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/System.Dynamic.txt
@@ -0,0 +1,72 @@
+#####################################################################################
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# This source code is subject to terms and conditions of the Microsoft Public License. A
+# copy of the license can be found in the License.html file at the root of this distribution. If
+# you cannot locate the Microsoft Public License, please send an email to
+# dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+# by the terms of the Microsoft Public License.
+#
+# You must not remove this notice, or any other, from this software.
+#
+#
+#####################################################################################
+
+InvalidArgumentValue=Invalid argument value
+ComObjectExpected=COM object is expected.
+CannotCall=Cannot perform call.
+
+## ExceptionType=ArgumentException
+COMObjectDoesNotSupportEvents=COM object does not support events.
+
+## ExceptionType=ArgumentException
+COMObjectDoesNotSupportSourceInterface=COM object does not support specified source interface.
+
+## ExceptionType=InvalidOperationException
+SetComObjectDataFailed=Marshal.SetComObjectData failed.
+
+## ExceptionType=InvalidOperationException
+MethodShouldNotBeCalled=This method exists only to keep the compiler happy.
+
+## ExceptionType=InvalidOperationException
+UnexpectedVarEnum=Unexpected VarEnum {0}.
+
+## ExceptionType=System.Reflection.TargetParameterCountException
+DispBadParamCount=Error while invoking {0}.
+
+## ExceptionType=MissingMemberException
+DispMemberNotFound=Error while invoking {0}.
+
+## ExceptionType=ArgumentException
+DispNoNamedArgs=Error while invoking {0}. Named arguments are not supported.
+
+## ExceptionType=OverflowException
+DispOverflow=Error while invoking {0}.
+
+## ExceptionType=ArgumentException
+DispTypeMismatch=Could not convert argument {0} for call to {1}.
+
+## ExceptionType=ArgumentException
+DispParamNotOptional=Error while invoking {0}. A required parameter was omitted.
+
+## ExceptionType=InvalidOperationException
+CannotRetrieveTypeInformation=ResolveComReference.CannotRetrieveTypeInformation.
+
+## ExceptionType=ArgumentException
+GetIDsOfNamesInvalid=IDispatch::GetIDsOfNames behaved unexpectedly for {0}.
+
+## ExceptionType=InvalidOperationException
+UnsupportedEnumType=Attempting to wrap an unsupported enum type.
+
+## ExceptionType=InvalidOperationException
+UnsupportedHandlerType=Attempting to pass an event handler of an unsupported type.
+
+## ExceptionType=MissingMemberException
+CouldNotGetDispId=Could not get dispatch ID for {0} (error: {1}).
+
+## ExceptionType=System.Reflection.AmbiguousMatchException
+AmbiguousConversion=There are valid conversions from {0} to {1}.
+
+## ExceptionType=NotImplementedException
+VariantGetAccessorNYI=Variant.GetAccessor cannot handle {0}.
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/TypeUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/TypeUtils.cs
new file mode 100644
index 00000000000..7228ceafa23
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/TypeUtils.cs
@@ -0,0 +1,260 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ internal static class TypeUtils {
+ private const BindingFlags AnyStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+ internal const MethodAttributes PublicStatic = MethodAttributes.Public | MethodAttributes.Static;
+
+ //CONFORMING
+ internal static Type GetNonNullableType(Type type) {
+ if (IsNullableType(type)) {
+ return type.GetGenericArguments()[0];
+ }
+ return type;
+ }
+
+ //CONFORMING
+ internal static bool IsNullableType(this Type type) {
+ return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+ //CONFORMING
+ internal static bool AreReferenceAssignable(Type dest, Type src) {
+ // WARNING: This actually implements "Is this identity assignable and/or reference assignable?"
+ if (dest == src) {
+ return true;
+ }
+ if (!dest.IsValueType && !src.IsValueType && AreAssignable(dest, src)) {
+ return true;
+ }
+ return false;
+ }
+ //CONFORMING
+ internal static bool AreAssignable(Type dest, Type src) {
+ if (dest == src) {
+ return true;
+ }
+ if (dest.IsAssignableFrom(src)) {
+ return true;
+ }
+ if (dest.IsArray && src.IsArray && dest.GetArrayRank() == src.GetArrayRank() && AreReferenceAssignable(dest.GetElementType(), src.GetElementType())) {
+ return true;
+ }
+ if (src.IsArray && dest.IsGenericType &&
+ (dest.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IEnumerable<>)
+ || dest.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IList<>)
+ || dest.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection<>))
+ && dest.GetGenericArguments()[0] == src.GetElementType()) {
+ return true;
+ }
+ return false;
+ }
+
+ //CONFORMING
+ internal static bool IsImplicitlyConvertible(Type source, Type destination) {
+ return IsIdentityConversion(source, destination) ||
+ IsImplicitNumericConversion(source, destination) ||
+ IsImplicitReferenceConversion(source, destination) ||
+ IsImplicitBoxingConversion(source, destination);
+ }
+
+ internal static bool IsImplicitlyConvertible(Type source, Type destination, bool considerUserDefined) {
+ return IsImplicitlyConvertible(source, destination) ||
+ (considerUserDefined && GetUserDefinedCoercionMethod(source, destination, true) != null);
+ }
+
+ //CONFORMING
+ internal static MethodInfo GetUserDefinedCoercionMethod(Type convertFrom, Type convertToType, bool implicitOnly) {
+ // check for implicit coercions first
+ Type nnExprType = TypeUtils.GetNonNullableType(convertFrom);
+ Type nnConvType = TypeUtils.GetNonNullableType(convertToType);
+ // try exact match on types
+ MethodInfo[] eMethods = nnExprType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ MethodInfo method = FindConversionOperator(eMethods, convertFrom, convertToType, implicitOnly);
+ if (method != null) {
+ return method;
+ }
+ MethodInfo[] cMethods = nnConvType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ method = FindConversionOperator(cMethods, convertFrom, convertToType, implicitOnly);
+ if (method != null) {
+ return method;
+ }
+ // try lifted conversion
+ if (nnExprType != convertFrom || nnConvType != convertToType) {
+ method = FindConversionOperator(eMethods, nnExprType, nnConvType, implicitOnly);
+ if (method == null) {
+ method = FindConversionOperator(cMethods, nnExprType, nnConvType, implicitOnly);
+ }
+ if (method != null) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ //CONFORMING
+ internal static MethodInfo FindConversionOperator(MethodInfo[] methods, Type typeFrom, Type typeTo, bool implicitOnly) {
+ foreach (MethodInfo mi in methods) {
+ if (mi.Name != "op_Implicit" && (implicitOnly || mi.Name != "op_Explicit"))
+ continue;
+ if (mi.ReturnType != typeTo)
+ continue;
+ ParameterInfo[] pis = mi.GetParameters();
+ if (pis[0].ParameterType != typeFrom)
+ continue;
+ return mi;
+ }
+ return null;
+ }
+
+
+ //CONFORMING
+ private static bool IsIdentityConversion(Type source, Type destination) {
+ return source == destination;
+ }
+
+ //CONFORMING
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static bool IsImplicitNumericConversion(Type source, Type destination) {
+ TypeCode tcSource = Type.GetTypeCode(source);
+ TypeCode tcDest = Type.GetTypeCode(destination);
+
+ switch (tcSource) {
+ case TypeCode.SByte:
+ switch (tcDest) {
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Byte:
+ switch (tcDest) {
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Int16:
+ switch (tcDest) {
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.UInt16:
+ switch (tcDest) {
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Int32:
+ switch (tcDest) {
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.UInt32:
+ switch (tcDest) {
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ switch (tcDest) {
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Char:
+ switch (tcDest) {
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Single:
+ return (tcDest == TypeCode.Double);
+ }
+ return false;
+ }
+
+ //CONFORMING
+ private static bool IsImplicitReferenceConversion(Type source, Type destination) {
+ return AreAssignable(destination, source);
+ }
+
+ //CONFORMING
+ private static bool IsImplicitBoxingConversion(Type source, Type destination) {
+ if (source.IsValueType && (destination == typeof(object) || destination == typeof(System.ValueType)))
+ return true;
+ if (source.IsEnum && destination == typeof(System.Enum))
+ return true;
+ return false;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/UnknownArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/UnknownArgBuilder.cs
new file mode 100644
index 00000000000..ec73054ce62
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/UnknownArgBuilder.cs
@@ -0,0 +1,100 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal class UnknownArgBuilder : SimpleArgBuilder {
+ private readonly bool _isWrapper;
+
+ internal UnknownArgBuilder(Type parameterType)
+ : base(parameterType) {
+
+ _isWrapper = parameterType == typeof(UnknownWrapper);
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ parameter = base.Marshal(parameter);
+
+ // parameter.WrappedObject
+ if (_isWrapper) {
+ parameter = Expression.Property(
+ Helpers.Convert(parameter, typeof(UnknownWrapper)),
+ typeof(UnknownWrapper).GetProperty("WrappedObject")
+ );
+ };
+
+ return Helpers.Convert(parameter, typeof(object));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ parameter = Marshal(parameter);
+
+ // parameter == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(parameter);
+ return Expression.Condition(
+ Expression.Equal(parameter, Expression.Constant(null)),
+ Expression.Constant(IntPtr.Zero),
+ Expression.Call(
+ typeof(Marshal).GetMethod("GetIUnknownForObject"),
+ parameter
+ )
+ );
+ }
+
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // value == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(value);
+ Expression unmarshal = Expression.Condition(
+ Expression.Equal(value, Expression.Constant(IntPtr.Zero)),
+ Expression.Constant(null),
+ Expression.Call(
+ typeof(Marshal).GetMethod("GetObjectForIUnknown"),
+ value
+ )
+ );
+
+ if (_isWrapper) {
+ unmarshal = Expression.New(
+ typeof(UnknownWrapper).GetConstructor(new Type[] { typeof(object) }),
+ unmarshal
+ );
+ };
+
+ return base.UnmarshalFromRef(unmarshal);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/VarEnumSelector.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VarEnumSelector.cs
new file mode 100644
index 00000000000..ec08acd675e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VarEnumSelector.cs
@@ -0,0 +1,475 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// If a managed user type (as opposed to a primitive type or a COM object) is passed as an argument to a COM call, we need
+ /// to determine the VarEnum type we will marshal it as. We have the following options:
+ /// 1. Raise an exception. Languages with their own version of primitive types would not be able to call
+ /// COM methods using the language's types (for eg. strings in IronRuby are not System.String). An explicit
+ /// cast would be needed.
+ /// 2. We could marshal it as VT_DISPATCH. Then COM code will be able to access all the APIs in a late-bound manner,
+ /// but old COM components will probably malfunction if they expect a primitive type.
+ /// 3. We could guess which primitive type is the closest match. This will make COM components be as easily
+ /// accessible as .NET methods.
+ /// 4. We could use the type library to check what the expected type is. However, the type library may not be available.
+ ///
+ /// VarEnumSelector implements option # 3
+ /// </summary>
+ internal class VarEnumSelector {
+ private readonly VariantBuilder[] _variantBuilders;
+
+ private static readonly Dictionary<VarEnum, Type> _ComToManagedPrimitiveTypes = CreateComToManagedPrimitiveTypes();
+ private static readonly IList<IList<VarEnum>> _ComPrimitiveTypeFamilies = CreateComPrimitiveTypeFamilies();
+
+ internal VarEnumSelector(Type[] explicitArgTypes) {
+ _variantBuilders = new VariantBuilder[explicitArgTypes.Length];
+
+ for (int i = 0; i < explicitArgTypes.Length; i++) {
+ _variantBuilders[i] = GetVariantBuilder(explicitArgTypes[i]);
+ }
+ }
+
+ internal VariantBuilder[] VariantBuilders {
+ get {
+ return _variantBuilders;
+ }
+ }
+
+ /// <summary>
+ /// Gets the managed type that an object needs to be coverted to in order for it to be able
+ /// to be represented as a Variant.
+ ///
+ /// In general, there is a many-to-many mapping between Type and VarEnum. However, this method
+ /// returns a simple mapping that is needed for the current implementation. The reason for the
+ /// many-to-many relation is:
+ /// 1. Int32 maps to VT_I4 as well as VT_ERROR, and Decimal maps to VT_DECIMAL and VT_CY. However,
+ /// this changes if you throw the wrapper types into the mix.
+ /// 2. There is no Type to represent COM types. __ComObject is a private type, and Object is too
+ /// general.
+ /// </summary>
+ internal static Type GetManagedMarshalType(VarEnum varEnum) {
+ Debug.Assert((varEnum & VarEnum.VT_BYREF) == 0);
+
+ if (varEnum == VarEnum.VT_CY) {
+ return typeof(CurrencyWrapper);
+ }
+
+ if (Variant.IsPrimitiveType(varEnum)) {
+ return _ComToManagedPrimitiveTypes[varEnum];
+ }
+
+ switch (varEnum) {
+ case VarEnum.VT_EMPTY:
+ case VarEnum.VT_NULL:
+ case VarEnum.VT_UNKNOWN:
+ case VarEnum.VT_DISPATCH:
+ case VarEnum.VT_VARIANT:
+ return typeof(Object);
+
+ case VarEnum.VT_ERROR:
+ return typeof(ErrorWrapper);
+
+ default:
+ throw Error.UnexpectedVarEnum(varEnum);
+ }
+ }
+
+ private static Dictionary<VarEnum, Type> CreateComToManagedPrimitiveTypes() {
+ Dictionary<VarEnum, Type> dict = new Dictionary<VarEnum, Type>();
+
+ #region Generated ComToManagedPrimitiveTypes
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_ComToManagedPrimitiveTypes from: generate_comdispatch.py
+
+ dict[VarEnum.VT_I1] = typeof(SByte);
+ dict[VarEnum.VT_I2] = typeof(Int16);
+ dict[VarEnum.VT_I4] = typeof(Int32);
+ dict[VarEnum.VT_I8] = typeof(Int64);
+ dict[VarEnum.VT_UI1] = typeof(Byte);
+ dict[VarEnum.VT_UI2] = typeof(UInt16);
+ dict[VarEnum.VT_UI4] = typeof(UInt32);
+ dict[VarEnum.VT_UI8] = typeof(UInt64);
+ dict[VarEnum.VT_INT] = typeof(IntPtr);
+ dict[VarEnum.VT_UINT] = typeof(UIntPtr);
+ dict[VarEnum.VT_BOOL] = typeof(Boolean);
+ dict[VarEnum.VT_R4] = typeof(Single);
+ dict[VarEnum.VT_R8] = typeof(Double);
+ dict[VarEnum.VT_DECIMAL] = typeof(Decimal);
+ dict[VarEnum.VT_DATE] = typeof(DateTime);
+ dict[VarEnum.VT_BSTR] = typeof(String);
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ dict[VarEnum.VT_CY] = typeof(CurrencyWrapper);
+ dict[VarEnum.VT_ERROR] = typeof(ErrorWrapper);
+
+ return dict;
+ }
+
+ #region Primitive COM types
+
+ /// <summary>
+ /// Creates a family of COM types such that within each family, there is a completely non-lossy
+ /// conversion from a type to an earlier type in the family.
+ /// </summary>
+ private static IList<IList<VarEnum>> CreateComPrimitiveTypeFamilies() {
+ VarEnum[][] typeFamilies = new VarEnum[][] {
+ new VarEnum[] { VarEnum.VT_I8, VarEnum.VT_I4, VarEnum.VT_I2, VarEnum.VT_I1 },
+ new VarEnum[] { VarEnum.VT_UI8, VarEnum.VT_UI4, VarEnum.VT_UI2, VarEnum.VT_UI1 },
+ new VarEnum[] { VarEnum.VT_INT },
+ new VarEnum[] { VarEnum.VT_UINT },
+ new VarEnum[] { VarEnum.VT_BOOL },
+ new VarEnum[] { VarEnum.VT_DATE },
+ new VarEnum[] { VarEnum.VT_R8, VarEnum.VT_R4 },
+ new VarEnum[] { VarEnum.VT_DECIMAL },
+ new VarEnum[] { VarEnum.VT_BSTR },
+
+ // wrappers
+ new VarEnum[] { VarEnum.VT_CY },
+ new VarEnum[] { VarEnum.VT_ERROR },
+ };
+
+ return typeFamilies;
+ }
+
+ /// <summary>
+ /// Get the (one representative type for each) primitive type families that the argument can be converted to
+ /// </summary>
+ private static List<VarEnum> GetConversionsToComPrimitiveTypeFamilies(Type argumentType) {
+ List<VarEnum> compatibleComTypes = new List<VarEnum>();
+
+ foreach (IList<VarEnum> typeFamily in _ComPrimitiveTypeFamilies) {
+ foreach (VarEnum candidateType in typeFamily) {
+ Type candidateManagedType = _ComToManagedPrimitiveTypes[candidateType];
+ if (TypeUtils.IsImplicitlyConvertible(argumentType, candidateManagedType, true)) {
+ compatibleComTypes.Add(candidateType);
+ // Move on to the next type family. We need atmost one type from each family
+ break;
+ }
+ }
+ }
+ return compatibleComTypes;
+ }
+
+ /// <summary>
+ /// If there is more than one type family that the argument can be converted to, we will throw a
+ /// AmbiguousMatchException instead of randomly picking a winner.
+ /// </summary>
+ private static void CheckForAmbiguousMatch(Type argumentType, List<VarEnum> compatibleComTypes) {
+ if (compatibleComTypes.Count <= 1) {
+ return;
+ }
+
+ String typeNames = "";
+ for (int i = 0; i < compatibleComTypes.Count; i++) {
+ string typeName = _ComToManagedPrimitiveTypes[compatibleComTypes[i]].Name;
+ if (i == (compatibleComTypes.Count - 1)) {
+ typeNames += " and ";
+ } else if (i != 0) {
+ typeNames += ", ";
+ }
+ typeNames += typeName;
+ }
+
+
+ throw Error.AmbiguousConversion(argumentType.Name, typeNames);
+ }
+
+ private static bool TryGetPrimitiveComType(Type argumentType, out VarEnum primitiveVarEnum) {
+
+ #region Generated Managed To COM Primitive Type Map
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_ManagedToComPrimitiveTypes from: generate_comdispatch.py
+
+ switch (Type.GetTypeCode(argumentType)) {
+ case TypeCode.Boolean:
+ primitiveVarEnum = VarEnum.VT_BOOL;
+ return true;
+ case TypeCode.Char:
+ primitiveVarEnum = VarEnum.VT_UI2;
+ return true;
+ case TypeCode.SByte:
+ primitiveVarEnum = VarEnum.VT_I1;
+ return true;
+ case TypeCode.Byte:
+ primitiveVarEnum = VarEnum.VT_UI1;
+ return true;
+ case TypeCode.Int16:
+ primitiveVarEnum = VarEnum.VT_I2;
+ return true;
+ case TypeCode.UInt16:
+ primitiveVarEnum = VarEnum.VT_UI2;
+ return true;
+ case TypeCode.Int32:
+ primitiveVarEnum = VarEnum.VT_I4;
+ return true;
+ case TypeCode.UInt32:
+ primitiveVarEnum = VarEnum.VT_UI4;
+ return true;
+ case TypeCode.Int64:
+ primitiveVarEnum = VarEnum.VT_I8;
+ return true;
+ case TypeCode.UInt64:
+ primitiveVarEnum = VarEnum.VT_UI8;
+ return true;
+ case TypeCode.Single:
+ primitiveVarEnum = VarEnum.VT_R4;
+ return true;
+ case TypeCode.Double:
+ primitiveVarEnum = VarEnum.VT_R8;
+ return true;
+ case TypeCode.Decimal:
+ primitiveVarEnum = VarEnum.VT_DECIMAL;
+ return true;
+ case TypeCode.DateTime:
+ primitiveVarEnum = VarEnum.VT_DATE;
+ return true;
+ case TypeCode.String:
+ primitiveVarEnum = VarEnum.VT_BSTR;
+ return true;
+ }
+
+ if (argumentType == typeof(CurrencyWrapper)) {
+ primitiveVarEnum = VarEnum.VT_CY;
+ return true;
+ }
+
+ if (argumentType == typeof(ErrorWrapper)) {
+ primitiveVarEnum = VarEnum.VT_ERROR;
+ return true;
+ }
+
+ if (argumentType == typeof(IntPtr)) {
+ primitiveVarEnum = VarEnum.VT_INT;
+ return true;
+ }
+
+ if (argumentType == typeof(UIntPtr)) {
+ primitiveVarEnum = VarEnum.VT_UINT;
+ return true;
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ primitiveVarEnum = VarEnum.VT_VOID; // error
+ return false;
+ }
+
+ /// <summary>
+ /// Is there a unique primitive type that has the best conversion for the argument
+ /// </summary>
+ private static bool TryGetPrimitiveComTypeViaConversion(Type argumentType, out VarEnum primitiveVarEnum) {
+ // Look for a unique type family that the argument can be converted to.
+ List<VarEnum> compatibleComTypes = GetConversionsToComPrimitiveTypeFamilies(argumentType);
+ CheckForAmbiguousMatch(argumentType, compatibleComTypes);
+ if (compatibleComTypes.Count == 1) {
+ primitiveVarEnum = compatibleComTypes[0];
+ return true;
+ }
+
+ primitiveVarEnum = VarEnum.VT_VOID; // error
+ return false;
+ }
+
+ #endregion
+
+ // Type.InvokeMember tries to marshal objects as VT_DISPATCH, and falls back to VT_UNKNOWN
+ // VT_RECORD here just indicates that we have user defined type.
+ // We will try VT_DISPATCH and then call GetNativeVariantForObject.
+ const VarEnum VT_DEFAULT = VarEnum.VT_RECORD;
+
+ private VarEnum GetComType(ref Type argumentType) {
+ if (argumentType == typeof(Missing)) {
+ //actual variant type will be VT_ERROR | E_PARAMNOTFOUND
+ return VarEnum.VT_RECORD;
+ }
+
+ if (argumentType.IsArray) {
+ //actual variant type will be VT_ARRAY | VT_<ELEMENT_TYPE>
+ return VarEnum.VT_ARRAY;
+ }
+
+ if (argumentType == typeof(UnknownWrapper)) {
+ return VarEnum.VT_UNKNOWN;
+ } else if (argumentType == typeof(DispatchWrapper)) {
+ return VarEnum.VT_DISPATCH;
+ } else if (argumentType == typeof(VariantWrapper)) {
+ return VarEnum.VT_VARIANT;
+ } else if (argumentType == typeof(BStrWrapper)) {
+ return VarEnum.VT_BSTR;
+ } else if (argumentType == typeof(ErrorWrapper)) {
+ return VarEnum.VT_ERROR;
+ } else if (argumentType == typeof(CurrencyWrapper)) {
+ return VarEnum.VT_CY;
+ }
+
+ // Many languages require an explicit cast for an enum to be used as the underlying type.
+ // However, we want to allow this conversion for COM without requiring an explicit cast
+ // so that enums from interop assemblies can be used as arguments.
+ if (argumentType.IsEnum) {
+ argumentType = Enum.GetUnderlyingType(argumentType);
+ return GetComType(ref argumentType);
+ }
+
+ // COM cannot express valuetype nulls so we will convert to underlying type
+ // it will throw if there is no value
+ if (TypeUtils.IsNullableType(argumentType)) {
+ argumentType = TypeUtils.GetNonNullableType(argumentType);
+ return GetComType(ref argumentType);
+ }
+
+ //generic types cannot be exposed to COM so they do not implement COM interfaces.
+ if (argumentType.IsGenericType) {
+ return VarEnum.VT_UNKNOWN;
+ }
+
+ VarEnum primitiveVarEnum;
+ if (TryGetPrimitiveComType(argumentType, out primitiveVarEnum)) {
+ return primitiveVarEnum;
+ }
+
+ // We could not find a way to marshal the type as a specific COM type
+ return VT_DEFAULT;
+ }
+
+ /// <summary>
+ /// Get the COM Variant type that argument should be marshaled as for a call to COM
+ /// </summary>
+ private VariantBuilder GetVariantBuilder(Type argumentType) {
+ //argumentType is coming from MarshalType, null means the dynamic object holds
+ //a null value and not byref
+ if (argumentType == null) {
+ return new VariantBuilder(VarEnum.VT_EMPTY, new NullArgBuilder());
+ }
+
+ if (argumentType == typeof(DBNull)) {
+ return new VariantBuilder(VarEnum.VT_NULL, new NullArgBuilder());
+ }
+
+ ArgBuilder argBuilder;
+
+ if (argumentType.IsByRef) {
+ Type elementType = argumentType.GetElementType();
+
+ VarEnum elementVarEnum;
+ if (elementType == typeof(object) || elementType == typeof(DBNull)) {
+ //no meaningful value to pass ByRef.
+ //perhaps the calee will replace it with something.
+ //need to pass as a variant reference
+ elementVarEnum = VarEnum.VT_VARIANT;
+ } else {
+ elementVarEnum = GetComType(ref elementType);
+ }
+
+ argBuilder = GetSimpleArgBuilder(elementType, elementVarEnum);
+ return new VariantBuilder(elementVarEnum | VarEnum.VT_BYREF, argBuilder);
+ }
+
+ VarEnum varEnum = GetComType(ref argumentType);
+ argBuilder = GetByValArgBuilder(argumentType, ref varEnum);
+
+ return new VariantBuilder(varEnum, argBuilder);
+ }
+
+
+ // This helper is called when we are looking for a ByVal marhsalling
+ // In a ByVal case we can take into account conversions or IConvertible if all other
+ // attempts to find marshalling type failed
+ private static ArgBuilder GetByValArgBuilder(Type elementType, ref VarEnum elementVarEnum) {
+ // if VT indicates that marshalling type is unknown
+ if (elementVarEnum == VT_DEFAULT) {
+ //trying to find a conversion.
+ VarEnum convertibleTo;
+ if (TryGetPrimitiveComTypeViaConversion(elementType, out convertibleTo)) {
+ elementVarEnum = convertibleTo;
+ Type marshalType = GetManagedMarshalType(elementVarEnum);
+ return new ConversionArgBuilder(elementType, GetSimpleArgBuilder(marshalType, elementVarEnum));
+ }
+
+ //checking for IConvertible.
+ if (typeof(IConvertible).IsAssignableFrom(elementType)) {
+ return new ConvertibleArgBuilder();
+ }
+ }
+ return GetSimpleArgBuilder(elementType, elementVarEnum);
+ }
+
+ // This helper can produce a builder for types that are directly supported by Variant.
+ private static SimpleArgBuilder GetSimpleArgBuilder(Type elementType, VarEnum elementVarEnum) {
+ SimpleArgBuilder argBuilder;
+
+ switch (elementVarEnum) {
+ case VarEnum.VT_BSTR:
+ argBuilder = new StringArgBuilder(elementType);
+ break;
+ case VarEnum.VT_BOOL:
+ argBuilder = new BoolArgBuilder(elementType);
+ break;
+ case VarEnum.VT_DATE:
+ argBuilder = new DateTimeArgBuilder(elementType);
+ break;
+ case VarEnum.VT_CY:
+ argBuilder = new CurrencyArgBuilder(elementType);
+ break;
+ case VarEnum.VT_DISPATCH:
+ argBuilder = new DispatchArgBuilder(elementType);
+ break;
+ case VarEnum.VT_UNKNOWN:
+ argBuilder = new UnknownArgBuilder(elementType);
+ break;
+ case VarEnum.VT_VARIANT:
+ case VarEnum.VT_ARRAY:
+ case VarEnum.VT_RECORD:
+ argBuilder = new VariantArgBuilder(elementType);
+ break;
+ case VarEnum.VT_ERROR:
+ argBuilder = new ErrorArgBuilder(elementType);
+ break;
+ default:
+ var marshalType = GetManagedMarshalType(elementVarEnum);
+ if (elementType == marshalType) {
+ argBuilder = new SimpleArgBuilder(elementType);
+ } else {
+ argBuilder = new ConvertArgBuilder(elementType, marshalType);
+ }
+ break;
+ }
+
+ return argBuilder;
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Variant.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Variant.cs
new file mode 100644
index 00000000000..1dfa33627ef
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Variant.cs
@@ -0,0 +1,985 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Variant is the basic COM type for late-binding. It can contain any other COM data type.
+ /// This type definition precisely matches the unmanaged data layout so that the struct can be passed
+ /// to and from COM calls.
+ /// </summary>
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct Variant {
+
+#if DEBUG
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2207:InitializeValueTypeStaticFieldsInline")]
+ static Variant() {
+ // Variant size is the size of 4 pointers (16 bytes) on a 32-bit processor,
+ // and 3 pointers (24 bytes) on a 64-bit processor.
+ int intPtrSize = Marshal.SizeOf(typeof(IntPtr));
+ int variantSize = Marshal.SizeOf(typeof(Variant));
+ if (intPtrSize == 4) {
+ Debug.Assert(variantSize == (4 * intPtrSize));
+ } else {
+ Debug.Assert(intPtrSize == 8);
+ Debug.Assert(variantSize == (3 * intPtrSize));
+ }
+ }
+#endif
+
+ // Most of the data types in the Variant are carried in _typeUnion
+ [FieldOffset(0)]
+ private TypeUnion _typeUnion;
+
+ // Decimal is the largest data type and it needs to use the space that is normally unused in TypeUnion._wReserved1, etc.
+ // Hence, it is declared to completely overlap with TypeUnion. A Decimal does not use the first two bytes, and so
+ // TypeUnion._vt can still be used to encode the type.
+ [FieldOffset(0)]
+ private Decimal _decimal;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct TypeUnion {
+ internal ushort _vt;
+ internal ushort _wReserved1;
+ internal ushort _wReserved2;
+ internal ushort _wReserved3;
+
+ internal UnionTypes _unionTypes;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct Record {
+ private IntPtr _record;
+ private IntPtr _recordInfo;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+ [StructLayout(LayoutKind.Explicit)]
+ private struct UnionTypes {
+ #region Generated Variant union types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_UnionTypes from: generate_comdispatch.py
+
+ [FieldOffset(0)] internal SByte _i1;
+ [FieldOffset(0)] internal Int16 _i2;
+ [FieldOffset(0)] internal Int32 _i4;
+ [FieldOffset(0)] internal Int64 _i8;
+ [FieldOffset(0)] internal Byte _ui1;
+ [FieldOffset(0)] internal UInt16 _ui2;
+ [FieldOffset(0)] internal UInt32 _ui4;
+ [FieldOffset(0)] internal UInt64 _ui8;
+ [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [FieldOffset(0)] internal IntPtr _int;
+ [FieldOffset(0)] internal UIntPtr _uint;
+ [FieldOffset(0)] internal Int16 _bool;
+ [FieldOffset(0)] internal Int32 _error;
+ [FieldOffset(0)] internal Single _r4;
+ [FieldOffset(0)] internal Double _r8;
+ [FieldOffset(0)] internal Int64 _cy;
+ [FieldOffset(0)] internal Double _date;
+ [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ [FieldOffset(0)] internal IntPtr _bstr;
+ [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [FieldOffset(0)] internal IntPtr _unknown;
+ [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [FieldOffset(0)] internal IntPtr _dispatch;
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ [FieldOffset(0)]
+ internal IntPtr _byref;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ [FieldOffset(0)]
+ internal Record _record;
+ }
+
+ public override string ToString() {
+ return String.Format(CultureInfo.CurrentCulture, "Variant ({0})", VariantType);
+ }
+
+ /// <summary>
+ /// Primitive types are the basic COM types. It includes valuetypes like ints, but also reference types
+ /// like BStrs. It does not include composite types like arrays and user-defined COM types (IUnknown/IDispatch).
+ /// </summary>
+ internal static bool IsPrimitiveType(VarEnum varEnum) {
+ switch (varEnum) {
+ #region Generated Variant IsPrimitiveType
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_IsPrimitiveType from: generate_comdispatch.py
+
+ case VarEnum.VT_I1:
+ case VarEnum.VT_I2:
+ case VarEnum.VT_I4:
+ case VarEnum.VT_I8:
+ case VarEnum.VT_UI1:
+ case VarEnum.VT_UI2:
+ case VarEnum.VT_UI4:
+ case VarEnum.VT_UI8:
+ case VarEnum.VT_INT:
+ case VarEnum.VT_UINT:
+ case VarEnum.VT_BOOL:
+ case VarEnum.VT_ERROR:
+ case VarEnum.VT_R4:
+ case VarEnum.VT_R8:
+ case VarEnum.VT_DECIMAL:
+ case VarEnum.VT_CY:
+ case VarEnum.VT_DATE:
+ case VarEnum.VT_BSTR:
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Get the managed object representing the Variant.
+ /// </summary>
+ /// <returns></returns>
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public object ToObject() {
+ // Check the simple case upfront
+ if (IsEmpty) {
+ return null;
+ }
+
+ switch (VariantType) {
+ case VarEnum.VT_NULL: return DBNull.Value;
+
+ #region Generated Variant ToObject
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_ToObject from: generate_comdispatch.py
+
+ case VarEnum.VT_I1: return AsI1;
+ case VarEnum.VT_I2: return AsI2;
+ case VarEnum.VT_I4: return AsI4;
+ case VarEnum.VT_I8: return AsI8;
+ case VarEnum.VT_UI1: return AsUi1;
+ case VarEnum.VT_UI2: return AsUi2;
+ case VarEnum.VT_UI4: return AsUi4;
+ case VarEnum.VT_UI8: return AsUi8;
+ case VarEnum.VT_INT: return AsInt;
+ case VarEnum.VT_UINT: return AsUint;
+ case VarEnum.VT_BOOL: return AsBool;
+ case VarEnum.VT_ERROR: return AsError;
+ case VarEnum.VT_R4: return AsR4;
+ case VarEnum.VT_R8: return AsR8;
+ case VarEnum.VT_DECIMAL: return AsDecimal;
+ case VarEnum.VT_CY: return AsCy;
+ case VarEnum.VT_DATE: return AsDate;
+ case VarEnum.VT_BSTR: return AsBstr;
+ case VarEnum.VT_UNKNOWN: return AsUnknown;
+ case VarEnum.VT_DISPATCH: return AsDispatch;
+ case VarEnum.VT_VARIANT: return AsVariant;
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default:
+ return AsVariant;
+ }
+ }
+
+ /// <summary>
+ /// Release any unmanaged memory associated with the Variant
+ /// </summary>
+ /// <returns></returns>
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void Clear() {
+ // We do not need to call OLE32's VariantClear for primitive types or ByRefs
+ // to safe ourselves the cost of interop transition.
+ // ByRef indicates the memory is not owned by the VARIANT itself while
+ // primitive types do not have any resources to free up.
+ // Hence, only safearrays, BSTRs, interfaces and user types are
+ // handled differently.
+ VarEnum vt = VariantType;
+ if ((vt & VarEnum.VT_BYREF) != 0) {
+ VariantType = VarEnum.VT_EMPTY;
+ } else if (
+ ((vt & VarEnum.VT_ARRAY) != 0) ||
+ ((vt) == VarEnum.VT_BSTR) ||
+ ((vt) == VarEnum.VT_UNKNOWN) ||
+ ((vt) == VarEnum.VT_DISPATCH) ||
+ ((vt) == VarEnum.VT_RECORD)
+ ) {
+ IntPtr variantPtr = UnsafeMethods.ConvertVariantByrefToPtr(ref this);
+ NativeMethods.VariantClear(variantPtr);
+ Debug.Assert(IsEmpty);
+ } else {
+ VariantType = VarEnum.VT_EMPTY;
+ }
+ }
+
+ public VarEnum VariantType {
+ get {
+ return (VarEnum)_typeUnion._vt;
+ }
+ set {
+ _typeUnion._vt = (ushort)value;
+ }
+ }
+
+ internal bool IsEmpty {
+ get {
+ return _typeUnion._vt == ((ushort)VarEnum.VT_EMPTY);
+ }
+ }
+
+ public void SetAsNull() {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_NULL;
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsIConvertible(IConvertible value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+
+ TypeCode tc = value.GetTypeCode();
+ CultureInfo ci = CultureInfo.CurrentCulture;
+
+ switch (tc) {
+ case TypeCode.Empty: break;
+ case TypeCode.Object: AsUnknown = value; break;
+ case TypeCode.DBNull: SetAsNull(); break;
+ case TypeCode.Boolean: AsBool = value.ToBoolean(ci); break;
+ case TypeCode.Char: AsUi2 = value.ToChar(ci); break;
+ case TypeCode.SByte: AsI1 = value.ToSByte(ci); break;
+ case TypeCode.Byte: AsUi1 = value.ToByte(ci); break;
+ case TypeCode.Int16: AsI2 = value.ToInt16(ci); break;
+ case TypeCode.UInt16: AsUi2 = value.ToUInt16(ci); break;
+ case TypeCode.Int32: AsI4 = value.ToInt32(ci); break;
+ case TypeCode.UInt32: AsUi4 = value.ToUInt32(ci); break;
+ case TypeCode.Int64: AsI8 = value.ToInt64(ci); break;
+ case TypeCode.UInt64: AsI8 = value.ToInt64(ci); break;
+ case TypeCode.Single: AsR4 = value.ToSingle(ci); break;
+ case TypeCode.Double: AsR8 = value.ToDouble(ci); break;
+ case TypeCode.Decimal: AsDecimal = value.ToDecimal(ci); break;
+ case TypeCode.DateTime: AsDate = value.ToDateTime(ci); break;
+ case TypeCode.String: AsBstr = value.ToString(ci); break;
+
+ default:
+ throw Assert.Unreachable;
+ }
+ }
+
+ #region Generated Variant accessors
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_accessors from: generate_comdispatch.py
+
+ // VT_I1
+ public SByte AsI1 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_I1);
+ return _typeUnion._unionTypes._i1;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I1;
+ _typeUnion._unionTypes._i1 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefI1(ref SByte value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_I1 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertSByteByrefToPtr(ref value);
+ }
+
+ // VT_I2
+ public Int16 AsI2 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_I2);
+ return _typeUnion._unionTypes._i2;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I2;
+ _typeUnion._unionTypes._i2 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefI2(ref Int16 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_I2 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertInt16ByrefToPtr(ref value);
+ }
+
+ // VT_I4
+ public Int32 AsI4 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_I4);
+ return _typeUnion._unionTypes._i4;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I4;
+ _typeUnion._unionTypes._i4 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefI4(ref Int32 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_I4 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertInt32ByrefToPtr(ref value);
+ }
+
+ // VT_I8
+ public Int64 AsI8 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_I8);
+ return _typeUnion._unionTypes._i8;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I8;
+ _typeUnion._unionTypes._i8 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefI8(ref Int64 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_I8 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertInt64ByrefToPtr(ref value);
+ }
+
+ // VT_UI1
+ public Byte AsUi1 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_UI1);
+ return _typeUnion._unionTypes._ui1;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI1;
+ _typeUnion._unionTypes._ui1 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefUi1(ref Byte value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_UI1 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertByteByrefToPtr(ref value);
+ }
+
+ // VT_UI2
+ public UInt16 AsUi2 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_UI2);
+ return _typeUnion._unionTypes._ui2;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI2;
+ _typeUnion._unionTypes._ui2 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefUi2(ref UInt16 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_UI2 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertUInt16ByrefToPtr(ref value);
+ }
+
+ // VT_UI4
+ public UInt32 AsUi4 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_UI4);
+ return _typeUnion._unionTypes._ui4;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI4;
+ _typeUnion._unionTypes._ui4 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefUi4(ref UInt32 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_UI4 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertUInt32ByrefToPtr(ref value);
+ }
+
+ // VT_UI8
+ public UInt64 AsUi8 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_UI8);
+ return _typeUnion._unionTypes._ui8;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI8;
+ _typeUnion._unionTypes._ui8 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefUi8(ref UInt64 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_UI8 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertUInt64ByrefToPtr(ref value);
+ }
+
+ // VT_INT
+ public IntPtr AsInt {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_INT);
+ return _typeUnion._unionTypes._int;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_INT;
+ _typeUnion._unionTypes._int = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefInt(ref IntPtr value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_INT | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertIntPtrByrefToPtr(ref value);
+ }
+
+ // VT_UINT
+ public UIntPtr AsUint {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_UINT);
+ return _typeUnion._unionTypes._uint;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UINT;
+ _typeUnion._unionTypes._uint = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefUint(ref UIntPtr value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_UINT | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertUIntPtrByrefToPtr(ref value);
+ }
+
+ // VT_BOOL
+ public Boolean AsBool {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_BOOL);
+ return _typeUnion._unionTypes._bool != 0;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_BOOL;
+ _typeUnion._unionTypes._bool = value ? (Int16)(-1) : (Int16)0;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefBool(ref Int16 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_BOOL | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertInt16ByrefToPtr(ref value);
+ }
+
+ // VT_ERROR
+ public Int32 AsError {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_ERROR);
+ return _typeUnion._unionTypes._error;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_ERROR;
+ _typeUnion._unionTypes._error = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefError(ref Int32 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_ERROR | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertInt32ByrefToPtr(ref value);
+ }
+
+ // VT_R4
+ public Single AsR4 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_R4);
+ return _typeUnion._unionTypes._r4;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_R4;
+ _typeUnion._unionTypes._r4 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefR4(ref Single value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_R4 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertSingleByrefToPtr(ref value);
+ }
+
+ // VT_R8
+ public Double AsR8 {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_R8);
+ return _typeUnion._unionTypes._r8;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_R8;
+ _typeUnion._unionTypes._r8 = value;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefR8(ref Double value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_R8 | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertDoubleByrefToPtr(ref value);
+ }
+
+ // VT_DECIMAL
+ public Decimal AsDecimal {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_DECIMAL);
+ // The first byte of Decimal is unused, but usually set to 0
+ Variant v = this;
+ v._typeUnion._vt = 0;
+ return v._decimal;
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_DECIMAL;
+ _decimal = value;
+ // _vt overlaps with _decimal, and should be set after setting _decimal
+ _typeUnion._vt = (ushort)VarEnum.VT_DECIMAL;
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefDecimal(ref Decimal value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_DECIMAL | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertDecimalByrefToPtr(ref value);
+ }
+
+ // VT_CY
+ public Decimal AsCy {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_CY);
+ return Decimal.FromOACurrency(_typeUnion._unionTypes._cy);
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_CY;
+ _typeUnion._unionTypes._cy = Decimal.ToOACurrency(value);
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefCy(ref Int64 value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_CY | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertInt64ByrefToPtr(ref value);
+ }
+
+ // VT_DATE
+ public DateTime AsDate {
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_DATE);
+ return DateTime.FromOADate(_typeUnion._unionTypes._date);
+ }
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_DATE;
+ _typeUnion._unionTypes._date = value.ToOADate();
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefDate(ref Double value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_DATE | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertDoubleByrefToPtr(ref value);
+ }
+
+ // VT_BSTR
+ public String AsBstr {
+ #if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+ #endif
+ [SecurityCritical]
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_BSTR);
+ if (_typeUnion._unionTypes._bstr != IntPtr.Zero) {
+ return Marshal.PtrToStringBSTR(_typeUnion._unionTypes._bstr);
+ } else {
+ return null;
+ }
+ }
+ #if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+ #endif
+ [SecurityCritical]
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_BSTR;
+ if (value != null) {
+ Marshal.GetNativeVariantForObject(value, UnsafeMethods.ConvertVariantByrefToPtr(ref this));
+ }
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefBstr(ref IntPtr value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_BSTR | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertIntPtrByrefToPtr(ref value);
+ }
+
+ // VT_UNKNOWN
+ public Object AsUnknown {
+ #if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+ #endif
+ [SecurityCritical]
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_UNKNOWN);
+ if (_typeUnion._unionTypes._dispatch != IntPtr.Zero) {
+ return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._unknown);
+ } else {
+ return null;
+ }
+ }
+ #if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+ #endif
+ [SecurityCritical]
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UNKNOWN;
+ if (value != null) {
+ _typeUnion._unionTypes._unknown = Marshal.GetIUnknownForObject(value);
+ }
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefUnknown(ref IntPtr value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_UNKNOWN | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertIntPtrByrefToPtr(ref value);
+ }
+
+ // VT_DISPATCH
+ public Object AsDispatch {
+ #if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+ #endif
+ [SecurityCritical]
+ get {
+ Debug.Assert(VariantType == VarEnum.VT_DISPATCH);
+ if (_typeUnion._unionTypes._dispatch != IntPtr.Zero) {
+ return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._dispatch);
+ } else {
+ return null;
+ }
+ }
+ #if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+ #endif
+ [SecurityCritical]
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_DISPATCH;
+ if (value != null) {
+ _typeUnion._unionTypes._unknown = Marshal.GetIDispatchForObject(value);
+ }
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefDispatch(ref IntPtr value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_DISPATCH | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertIntPtrByrefToPtr(ref value);
+ }
+
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+
+ // VT_VARIANT
+
+ public Object AsVariant {
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ get {
+ return Marshal.GetObjectForNativeVariant(UnsafeMethods.ConvertVariantByrefToPtr(ref this));
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ set {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ if (value != null) {
+ UnsafeMethods.InitVariantForObject(value, ref this);
+ }
+ }
+ }
+
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefVariant(ref Variant value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = (VarEnum.VT_VARIANT | VarEnum.VT_BYREF);
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertVariantByrefToPtr(ref value);
+ }
+
+ // constructs a ByRef variant to pass contents of another variant ByRef.
+#if MICROSOFT_DYNAMIC
+ [PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+ [SecurityCritical]
+ public void SetAsByrefVariantIndirect(ref Variant value) {
+ Debug.Assert(IsEmpty); // The setter can only be called once as VariantClear might be needed otherwise
+ Debug.Assert((value.VariantType & VarEnum.VT_BYREF) == 0, "double indirection");
+
+ switch (value.VariantType) {
+ case VarEnum.VT_EMPTY:
+ case VarEnum.VT_NULL:
+ // these cannot combine with VT_BYREF. Should try passing as a variant reference
+ SetAsByrefVariant(ref value);
+ return;
+ case VarEnum.VT_RECORD:
+ // VT_RECORD's are weird in that regardless of is the VT_BYREF flag is set or not
+ // they have the same internal representation.
+ _typeUnion._unionTypes._record = value._typeUnion._unionTypes._record;
+ break;
+ case VarEnum.VT_DECIMAL:
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertDecimalByrefToPtr(ref value._decimal);
+ break;
+ default:
+ _typeUnion._unionTypes._byref = UnsafeMethods.ConvertIntPtrByrefToPtr(ref value._typeUnion._unionTypes._byref);
+ break;
+ }
+ VariantType = (value.VariantType | VarEnum.VT_BYREF);
+ }
+
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ internal static System.Reflection.PropertyInfo GetAccessor(VarEnum varType) {
+ switch (varType) {
+
+ #region Generated Variant accessors PropertyInfos
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_accessor_propertyinfo from: generate_comdispatch.py
+
+ case VarEnum.VT_I1: return typeof(Variant).GetProperty("AsI1");
+ case VarEnum.VT_I2: return typeof(Variant).GetProperty("AsI2");
+ case VarEnum.VT_I4: return typeof(Variant).GetProperty("AsI4");
+ case VarEnum.VT_I8: return typeof(Variant).GetProperty("AsI8");
+ case VarEnum.VT_UI1: return typeof(Variant).GetProperty("AsUi1");
+ case VarEnum.VT_UI2: return typeof(Variant).GetProperty("AsUi2");
+ case VarEnum.VT_UI4: return typeof(Variant).GetProperty("AsUi4");
+ case VarEnum.VT_UI8: return typeof(Variant).GetProperty("AsUi8");
+ case VarEnum.VT_INT: return typeof(Variant).GetProperty("AsInt");
+ case VarEnum.VT_UINT: return typeof(Variant).GetProperty("AsUint");
+ case VarEnum.VT_BOOL: return typeof(Variant).GetProperty("AsBool");
+ case VarEnum.VT_ERROR: return typeof(Variant).GetProperty("AsError");
+ case VarEnum.VT_R4: return typeof(Variant).GetProperty("AsR4");
+ case VarEnum.VT_R8: return typeof(Variant).GetProperty("AsR8");
+ case VarEnum.VT_DECIMAL: return typeof(Variant).GetProperty("AsDecimal");
+ case VarEnum.VT_CY: return typeof(Variant).GetProperty("AsCy");
+ case VarEnum.VT_DATE: return typeof(Variant).GetProperty("AsDate");
+ case VarEnum.VT_BSTR: return typeof(Variant).GetProperty("AsBstr");
+ case VarEnum.VT_UNKNOWN: return typeof(Variant).GetProperty("AsUnknown");
+ case VarEnum.VT_DISPATCH: return typeof(Variant).GetProperty("AsDispatch");
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ case VarEnum.VT_VARIANT:
+ case VarEnum.VT_RECORD:
+ case VarEnum.VT_ARRAY:
+ return typeof(Variant).GetProperty("AsVariant");
+
+ default:
+ throw Error.VariantGetAccessorNYI(varType);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ internal static System.Reflection.MethodInfo GetByrefSetter(VarEnum varType) {
+ switch (varType) {
+
+ #region Generated Variant byref setter
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_byref_setters from: generate_comdispatch.py
+
+ case VarEnum.VT_I1: return typeof(Variant).GetMethod("SetAsByrefI1");
+ case VarEnum.VT_I2: return typeof(Variant).GetMethod("SetAsByrefI2");
+ case VarEnum.VT_I4: return typeof(Variant).GetMethod("SetAsByrefI4");
+ case VarEnum.VT_I8: return typeof(Variant).GetMethod("SetAsByrefI8");
+ case VarEnum.VT_UI1: return typeof(Variant).GetMethod("SetAsByrefUi1");
+ case VarEnum.VT_UI2: return typeof(Variant).GetMethod("SetAsByrefUi2");
+ case VarEnum.VT_UI4: return typeof(Variant).GetMethod("SetAsByrefUi4");
+ case VarEnum.VT_UI8: return typeof(Variant).GetMethod("SetAsByrefUi8");
+ case VarEnum.VT_INT: return typeof(Variant).GetMethod("SetAsByrefInt");
+ case VarEnum.VT_UINT: return typeof(Variant).GetMethod("SetAsByrefUint");
+ case VarEnum.VT_BOOL: return typeof(Variant).GetMethod("SetAsByrefBool");
+ case VarEnum.VT_ERROR: return typeof(Variant).GetMethod("SetAsByrefError");
+ case VarEnum.VT_R4: return typeof(Variant).GetMethod("SetAsByrefR4");
+ case VarEnum.VT_R8: return typeof(Variant).GetMethod("SetAsByrefR8");
+ case VarEnum.VT_DECIMAL: return typeof(Variant).GetMethod("SetAsByrefDecimal");
+ case VarEnum.VT_CY: return typeof(Variant).GetMethod("SetAsByrefCy");
+ case VarEnum.VT_DATE: return typeof(Variant).GetMethod("SetAsByrefDate");
+ case VarEnum.VT_BSTR: return typeof(Variant).GetMethod("SetAsByrefBstr");
+ case VarEnum.VT_UNKNOWN: return typeof(Variant).GetMethod("SetAsByrefUnknown");
+ case VarEnum.VT_DISPATCH: return typeof(Variant).GetMethod("SetAsByrefDispatch");
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ case VarEnum.VT_VARIANT:
+ return typeof(Variant).GetMethod("SetAsByrefVariant");
+ case VarEnum.VT_RECORD:
+ case VarEnum.VT_ARRAY:
+ return typeof(Variant).GetMethod("SetAsByrefVariantIndirect");
+
+ default:
+ throw Error.VariantGetAccessorNYI(varType);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArgBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArgBuilder.cs
new file mode 100644
index 00000000000..978ea4076ff
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArgBuilder.cs
@@ -0,0 +1,94 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal class VariantArgBuilder : SimpleArgBuilder {
+ private readonly bool _isWrapper;
+
+ internal VariantArgBuilder(Type parameterType)
+ : base(parameterType) {
+
+ _isWrapper = parameterType == typeof(VariantWrapper);
+ }
+
+ internal override Expression Marshal(Expression parameter) {
+ parameter = base.Marshal(parameter);
+
+ // parameter.WrappedObject
+ if (_isWrapper) {
+ parameter = Expression.Property(
+ Helpers.Convert(parameter, typeof(VariantWrapper)),
+ typeof(VariantWrapper).GetProperty("WrappedObject")
+ );
+ };
+
+ return Helpers.Convert(parameter, typeof(object));
+ }
+
+ internal override Expression MarshalToRef(Expression parameter) {
+ parameter = Marshal(parameter);
+
+ // parameter == UnsafeMethods.GetVariantForObject(parameter);
+ return Expression.Call(
+ typeof(UnsafeMethods).GetMethod("GetVariantForObject", BindingFlags.Static | System.Reflection.BindingFlags.NonPublic),
+ parameter
+ );
+ }
+
+
+ internal override Expression UnmarshalFromRef(Expression value) {
+ // value == IntPtr.Zero ? null : Marshal.GetObjectForNativeVariant(value);
+
+ Expression unmarshal = Expression.Call(
+ typeof(UnsafeMethods).GetMethod("GetObjectForVariant"),
+ value
+ );
+
+ if (_isWrapper) {
+ unmarshal = Expression.New(
+ typeof(VariantWrapper).GetConstructor(new Type[] { typeof(object) }),
+ unmarshal
+ );
+ };
+
+ return base.UnmarshalFromRef(unmarshal);
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArray.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArray.cs
new file mode 100644
index 00000000000..d108eaadd4d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantArray.cs
@@ -0,0 +1,114 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct VariantArray1 {
+ public Variant Element0;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct VariantArray2 {
+ public Variant Element0, Element1;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct VariantArray4 {
+ public Variant Element0, Element1, Element2, Element3;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct VariantArray8 {
+ public Variant Element0, Element1, Element2, Element3, Element4, Element5, Element6, Element7;
+ }
+
+ //
+ // Helper for getting the right VariantArray struct for a given number of
+ // arguments. Will generate a struct if needed.
+ //
+ // We use this because we don't have stackalloc or pinning in Expression
+ // Trees, so we can't create an array of Variants directly.
+ //
+ internal static class VariantArray {
+ // Don't need a dictionary for this, it will have very few elements
+ // (guarenteed less than 28, in practice 0-2)
+ private static readonly List<Type> _generatedTypes = new List<Type>(0);
+
+ internal static MemberExpression GetStructField(ParameterExpression variantArray, int field) {
+ return Expression.Field(variantArray, "Element" + field);
+ }
+
+ internal static Type GetStructType(int args) {
+ Debug.Assert(args >= 0);
+ if (args <= 1) return typeof(VariantArray1);
+ if (args <= 2) return typeof(VariantArray2);
+ if (args <= 4) return typeof(VariantArray4);
+ if (args <= 8) return typeof(VariantArray8);
+
+ int size = 1;
+ while (args > size) {
+ size *= 2;
+ }
+
+ lock (_generatedTypes) {
+ // See if we can find an existing type
+ foreach (Type t in _generatedTypes) {
+ int arity = int.Parse(t.Name.Substring("VariantArray".Length), CultureInfo.InvariantCulture);
+ if (size == arity) {
+ return t;
+ }
+ }
+
+ // Else generate a new type
+ Type type = CreateCustomType(size).MakeGenericType(new Type[]{typeof(Variant)});
+ _generatedTypes.Add(type);
+ return type;
+ }
+ }
+
+ private static Type CreateCustomType(int size) {
+ var attrs = TypeAttributes.NotPublic | TypeAttributes.SequentialLayout;
+ TypeBuilder type = UnsafeMethods.DynamicModule.DefineType("VariantArray" + size, attrs, typeof(ValueType));
+ var T = type.DefineGenericParameters(new string[] { "T" })[0];
+ for (int i = 0; i < size; i++) {
+ type.DefineField("Element" + i, T, FieldAttributes.Public);
+ }
+ return type.CreateType();
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantBuilder.cs
new file mode 100644
index 00000000000..6b91d1045ad
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/VariantBuilder.cs
@@ -0,0 +1,177 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if !SILVERLIGHT // ComObject
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.InteropServices;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// VariantBuilder handles packaging of arguments into a Variant for a call to IDispatch.Invoke
+ /// </summary>
+ internal class VariantBuilder {
+
+ private MemberExpression _variant;
+ private readonly ArgBuilder _argBuilder;
+ private readonly VarEnum _targetComType;
+ internal ParameterExpression TempVariable { get; private set; }
+
+ internal VariantBuilder(VarEnum targetComType, ArgBuilder builder) {
+ _targetComType = targetComType;
+ _argBuilder = builder;
+ }
+
+ internal bool IsByRef {
+ get { return (_targetComType & VarEnum.VT_BYREF) != 0; }
+ }
+
+ internal Expression InitializeArgumentVariant(MemberExpression variant, Expression parameter) {
+ //NOTE: we must remember our variant
+ //the reason is that argument order does not map exactly to the order of variants for invoke
+ //and when we are doing clean-up we must be sure we are cleaning the variant we have initialized.
+
+ _variant = variant;
+
+ if (IsByRef) {
+ // temp = argument
+ // paramVariants._elementN.SetAsByrefT(ref temp)
+ Debug.Assert(TempVariable == null);
+ var argExpr = _argBuilder.MarshalToRef(parameter);
+
+ TempVariable = Expression.Variable(argExpr.Type, null);
+ return Expression.Block(
+ Expression.Assign(TempVariable, argExpr),
+ Expression.Call(
+ variant,
+ Variant.GetByrefSetter(_targetComType & ~VarEnum.VT_BYREF),
+ TempVariable
+ )
+ );
+ }
+
+ Expression argument = _argBuilder.Marshal(parameter);
+
+ // we are forced to special case ConvertibleArgBuilder since it does not have
+ // a corresponding _targetComType.
+ if (_argBuilder is ConvertibleArgBuilder) {
+ return Expression.Call(
+ variant,
+ typeof(Variant).GetMethod("SetAsIConvertible"),
+ argument
+ );
+ }
+
+ if (Variant.IsPrimitiveType(_targetComType) ||
+ (_targetComType == VarEnum.VT_DISPATCH) ||
+ (_targetComType == VarEnum.VT_UNKNOWN) ||
+ (_targetComType == VarEnum.VT_VARIANT) ||
+ (_targetComType == VarEnum.VT_RECORD) ||
+ (_targetComType == VarEnum.VT_ARRAY)){
+ // paramVariants._elementN.AsT = (cast)argN
+ return Expression.Assign(
+ Expression.Property(
+ variant,
+ Variant.GetAccessor(_targetComType)
+ ),
+ argument
+ );
+ }
+
+ switch (_targetComType) {
+ case VarEnum.VT_EMPTY:
+ return null;
+
+ case VarEnum.VT_NULL:
+ // paramVariants._elementN.SetAsNull();
+ return Expression.Call(variant, typeof(Variant).GetMethod("SetAsNull"));
+
+ default:
+ Debug.Assert(false, "Unexpected VarEnum");
+ return null;
+ }
+ }
+
+ private static Expression Release(Expression pUnk) {
+ return Expression.Call(typeof(UnsafeMethods).GetMethod("IUnknownReleaseNotZero"), pUnk);
+ }
+
+ internal Expression Clear() {
+ if (IsByRef) {
+ if (_argBuilder is StringArgBuilder) {
+ Debug.Assert(TempVariable != null);
+ return Expression.Call(typeof(Marshal).GetMethod("FreeBSTR"), TempVariable);
+ } else if (_argBuilder is DispatchArgBuilder) {
+ Debug.Assert(TempVariable != null);
+ return Release(TempVariable);
+ } else if (_argBuilder is UnknownArgBuilder) {
+ Debug.Assert(TempVariable != null);
+ return Release(TempVariable);
+ } else if (_argBuilder is VariantArgBuilder) {
+ Debug.Assert(TempVariable != null);
+ return Expression.Call(TempVariable, typeof(Variant).GetMethod("Clear"));
+ }
+ return null;
+ }
+
+
+ switch (_targetComType) {
+ case VarEnum.VT_EMPTY:
+ case VarEnum.VT_NULL:
+ return null;
+
+ case VarEnum.VT_BSTR:
+ case VarEnum.VT_UNKNOWN:
+ case VarEnum.VT_DISPATCH:
+ case VarEnum.VT_ARRAY:
+ case VarEnum.VT_RECORD:
+ case VarEnum.VT_VARIANT:
+ // paramVariants._elementN.Clear()
+ return Expression.Call(_variant, typeof(Variant).GetMethod("Clear"));
+
+ default:
+ Debug.Assert(Variant.IsPrimitiveType(_targetComType), "Unexpected VarEnum");
+ return null;
+ }
+ }
+
+ internal Expression UpdateFromReturn(Expression parameter) {
+ if (TempVariable == null) {
+ return null;
+ }
+ return Expression.Assign(
+ parameter,
+ Helpers.Convert(
+ _argBuilder.UnmarshalFromRef(TempVariable),
+ parameter.Type
+ )
+ );
+ }
+ }
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BinaryOperationBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BinaryOperationBinder.cs
new file mode 100644
index 00000000000..b9b7df7e7aa
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BinaryOperationBinder.cs
@@ -0,0 +1,154 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the binary dynamic operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class BinaryOperationBinder : DynamicMetaObjectBinder {
+ private ExpressionType _operation;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BinaryOperationBinder"/> class.
+ /// </summary>
+ /// <param name="operation">The binary operation kind.</param>
+ protected BinaryOperationBinder(ExpressionType operation) {
+ ContractUtils.Requires(OperationIsValid(operation), "operation");
+ _operation = operation;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// The binary operation kind.
+ /// </summary>
+ public ExpressionType Operation {
+ get {
+ return _operation;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the binary dynamic operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic binary operation.</param>
+ /// <param name="arg">The right hand side operand of the dynamic binary operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg) {
+ return FallbackBinaryOperation(target, arg, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the binary dynamic operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic binary operation.</param>
+ /// <param name="arg">The right hand side operand of the dynamic binary operation.</param>
+ /// <param name="errorSuggestion">The binding result in case the binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic binary operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic operation.</param>
+ /// <param name="args">An array of arguments of the dynamic operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNull(args, "args");
+ ContractUtils.Requires(args.Length == 1, "args");
+
+ var arg0 = args[0];
+ ContractUtils.RequiresNotNull(arg0, "args");
+
+ return target.BindBinaryOperation(this, arg0);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ internal static bool OperationIsValid(ExpressionType operation) {
+ switch (operation) {
+ #region Generated Binary Operation Binder Validator
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_binop_validator from: generate_tree.py
+
+ case ExpressionType.Add:
+ case ExpressionType.And:
+ case ExpressionType.Divide:
+ case ExpressionType.Equal:
+ case ExpressionType.ExclusiveOr:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.LeftShift:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.Modulo:
+ case ExpressionType.Multiply:
+ case ExpressionType.NotEqual:
+ case ExpressionType.Or:
+ case ExpressionType.Power:
+ case ExpressionType.RightShift:
+ case ExpressionType.Subtract:
+ case ExpressionType.AddAssign:
+ case ExpressionType.AndAssign:
+ case ExpressionType.DivideAssign:
+ case ExpressionType.ExclusiveOrAssign:
+ case ExpressionType.LeftShiftAssign:
+ case ExpressionType.ModuloAssign:
+ case ExpressionType.MultiplyAssign:
+ case ExpressionType.OrAssign:
+ case ExpressionType.PowerAssign:
+ case ExpressionType.RightShiftAssign:
+ case ExpressionType.SubtractAssign:
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ case ExpressionType.Extension:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BindingRestrictions.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BindingRestrictions.cs
new file mode 100644
index 00000000000..7d4ae41edde
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/BindingRestrictions.cs
@@ -0,0 +1,377 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Represents a set of binding restrictions on the <see cref="DynamicMetaObject"/>under which the dynamic binding is valid.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(BindingRestrictionsProxy)), DebuggerDisplay("{DebugView}")]
+#endif
+ public abstract class BindingRestrictions {
+ /// <summary>
+ /// Represents an empty set of binding restrictions. This field is read only.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly BindingRestrictions Empty = new CustomRestriction(Expression.Constant(true));
+
+ private const int TypeRestrictionHash = 0x10000000;
+ private const int InstanceRestrictionHash = 0x20000000;
+ private const int CustomRestrictionHash = 0x40000000;
+
+ private BindingRestrictions() {
+ }
+
+ // Overridden by specialized subclasses
+ internal abstract Expression GetExpression();
+
+ /// <summary>
+ /// Merges the set of binding restrictions with the current binding restrictions.
+ /// </summary>
+ /// <param name="restrictions">The set of restrictions with which to merge the current binding restrictions.</param>
+ /// <returns>The new set of binding restrictions.</returns>
+ public BindingRestrictions Merge(BindingRestrictions restrictions) {
+ ContractUtils.RequiresNotNull(restrictions, "restrictions");
+ if (this == Empty) {
+ return restrictions;
+ }
+ if (restrictions == Empty) {
+ return this;
+ }
+ return new MergedRestriction(this, restrictions);
+ }
+
+ /// <summary>
+ /// Creates the binding restriction that check the expression for runtime type identity.
+ /// </summary>
+ /// <param name="expression">The expression to test.</param>
+ /// <param name="type">The exact type to test.</param>
+ /// <returns>The new binding restrictions.</returns>
+ public static BindingRestrictions GetTypeRestriction(Expression expression, Type type) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+
+ return new TypeRestriction(expression, type);
+ }
+
+ /// <summary>
+ /// The method takes a DynamicMetaObject, and returns an instance restriction for testing null if the object
+ /// holds a null value, otherwise returns a type restriction.
+ /// </summary>
+ internal static BindingRestrictions GetTypeRestriction(DynamicMetaObject obj) {
+ if (obj.Value == null && obj.HasValue) {
+ return BindingRestrictions.GetInstanceRestriction(obj.Expression, null);
+ } else {
+ return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType);
+ }
+ }
+
+ /// <summary>
+ /// Creates the binding restriction that checks the expression for object instance identity.
+ /// </summary>
+ /// <param name="expression">The expression to test.</param>
+ /// <param name="instance">The exact object instance to test.</param>
+ /// <returns>The new binding restrictions.</returns>
+ public static BindingRestrictions GetInstanceRestriction(Expression expression, object instance) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+
+ return new InstanceRestriction(expression, instance);
+ }
+
+ /// <summary>
+ /// Creates the binding restriction that checks the expression for arbitrary immutable properties.
+ /// </summary>
+ /// <param name="expression">The expression expression the restrictions.</param>
+ /// <returns>The new binding restrictions.</returns>
+ /// <remarks>
+ /// By convention, the general restrictions created by this method must only test
+ /// immutable object properties.
+ /// </remarks>
+ public static BindingRestrictions GetExpressionRestriction(Expression expression) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+ ContractUtils.Requires(expression.Type == typeof(bool), "expression");
+ return new CustomRestriction(expression);
+ }
+
+ /// <summary>
+ /// Combines binding restrictions from the list of <see cref="DynamicMetaObject"/> instances into one set of restrictions.
+ /// </summary>
+ /// <param name="contributingObjects">The list of <see cref="DynamicMetaObject"/> instances from which to combine restrictions.</param>
+ /// <returns>The new set of binding restrictions.</returns>
+ public static BindingRestrictions Combine(IList<DynamicMetaObject> contributingObjects) {
+ BindingRestrictions res = BindingRestrictions.Empty;
+ if (contributingObjects != null) {
+ foreach (DynamicMetaObject mo in contributingObjects) {
+ if (mo != null) {
+ res = res.Merge(mo.Restrictions);
+ }
+ }
+ }
+ return res;
+ }
+
+ /// <summary>
+ /// Builds a balanced tree of AndAlso nodes.
+ /// We do this so the compiler won't stack overflow if we have many
+ /// restrictions.
+ /// </summary>
+ private sealed class TestBuilder {
+ private readonly Set<BindingRestrictions> _unique = new Set<BindingRestrictions>();
+ private readonly Stack<AndNode> _tests = new Stack<AndNode>();
+
+ private struct AndNode {
+ internal int Depth;
+ internal Expression Node;
+ }
+
+ internal void Append(BindingRestrictions restrictions) {
+ if (_unique.Contains(restrictions)) {
+ return;
+ }
+ _unique.Add(restrictions);
+
+ Push(restrictions.GetExpression(), 0);
+ }
+
+ internal Expression ToExpression() {
+ Expression result = _tests.Pop().Node;
+ while (_tests.Count > 0) {
+ result = Expression.AndAlso(_tests.Pop().Node, result);
+ }
+ return result;
+ }
+
+ private void Push(Expression node, int depth) {
+ while (_tests.Count > 0 && _tests.Peek().Depth == depth) {
+ node = Expression.AndAlso(_tests.Pop().Node, node);
+ depth++;
+ }
+ _tests.Push(new AndNode { Node = node, Depth = depth });
+ }
+ }
+
+ /// <summary>
+ /// Creates the <see cref="Expression"/> representing the binding restrictions.
+ /// </summary>
+ /// <returns>The expression tree representing the restrictions.</returns>
+ public Expression ToExpression() {
+ // We could optimize this better, e.g. common subexpression elimination
+ // But for now, it's good enough.
+
+ if (this == Empty) {
+ return Expression.Constant(true);
+ }
+
+ var testBuilder = new TestBuilder();
+
+ // Visit the tree, left to right.
+ // Use an explicit stack so we don't stack overflow.
+ //
+ // Left-most node is on top of the stack, so we always expand the
+ // left most node each iteration.
+ var stack = new Stack<BindingRestrictions>();
+ stack.Push(this);
+ do {
+ var top = stack.Pop();
+ var m = top as MergedRestriction;
+ if (m != null) {
+ stack.Push(m.Right);
+ stack.Push(m.Left);
+ } else {
+ testBuilder.Append(top);
+ }
+ } while (stack.Count > 0);
+
+ return testBuilder.ToExpression();
+ }
+
+ private sealed class MergedRestriction : BindingRestrictions {
+ internal readonly BindingRestrictions Left;
+ internal readonly BindingRestrictions Right;
+
+ internal MergedRestriction(BindingRestrictions left, BindingRestrictions right) {
+ Left = left;
+ Right = right;
+ }
+ internal override Expression GetExpression() {
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ private sealed class CustomRestriction : BindingRestrictions {
+ private readonly Expression _expression;
+
+ internal CustomRestriction(Expression expression) {
+ _expression = expression;
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as CustomRestriction;
+ return other != null && other._expression == _expression;
+ }
+
+ public override int GetHashCode() {
+ return CustomRestrictionHash ^ _expression.GetHashCode();
+ }
+
+ internal override Expression GetExpression() {
+ return _expression;
+ }
+ }
+
+ private sealed class TypeRestriction : BindingRestrictions {
+ private readonly Expression _expression;
+ private readonly Type _type;
+
+ internal TypeRestriction(Expression parameter, Type type) {
+ _expression = parameter;
+ _type = type;
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as TypeRestriction;
+ return other != null && TypeUtils.AreEquivalent(other._type, _type) && other._expression == _expression;
+ }
+
+ public override int GetHashCode() {
+ return TypeRestrictionHash ^ _expression.GetHashCode() ^ _type.GetHashCode();
+ }
+
+ internal override Expression GetExpression() {
+ return Expression.TypeEqual(_expression, _type);
+ }
+ }
+
+ private sealed class InstanceRestriction : BindingRestrictions {
+ private readonly Expression _expression;
+ private readonly object _instance;
+
+ internal InstanceRestriction(Expression parameter, object instance) {
+ _expression = parameter;
+ _instance = instance;
+ }
+
+ public override bool Equals(object obj) {
+ var other = obj as InstanceRestriction;
+ return other != null && other._instance == _instance && other._expression == _expression;
+ }
+
+ public override int GetHashCode() {
+ return InstanceRestrictionHash ^ RuntimeHelpers.GetHashCode(_instance) ^ _expression.GetHashCode();
+ }
+
+ internal override Expression GetExpression() {
+ if (_instance == null) {
+ return Expression.Equal(
+ Expression.Convert(_expression, typeof(object)),
+ Expression.Constant(null)
+ );
+ }
+
+ ParameterExpression temp = Expression.Parameter(typeof(object), null);
+ return Expression.Block(
+ new[] { temp },
+ Expression.Assign(
+ temp,
+ Expression.Property(
+ Expression.Constant(new WeakReference(_instance)),
+ typeof(WeakReference).GetProperty("Target")
+ )
+ ),
+ Expression.AndAlso(
+ //check that WeekReference was not collected.
+ Expression.NotEqual(temp, Expression.Constant(null)),
+ Expression.Equal(
+ Expression.Convert(_expression, typeof(object)),
+ temp
+ )
+ )
+ );
+ }
+ }
+
+ private string DebugView {
+ get { return ToExpression().ToString(); }
+ }
+
+ private sealed class BindingRestrictionsProxy {
+ private readonly BindingRestrictions _node;
+
+ public BindingRestrictionsProxy(BindingRestrictions node) {
+ _node = node;
+ }
+
+ public bool IsEmpty {
+ get { return _node == Empty; }
+ }
+
+ public Expression Test {
+ get { return _node.ToExpression(); }
+ }
+
+ public BindingRestrictions[] Restrictions {
+ get {
+ var restrictions = new List<BindingRestrictions>();
+
+ // Visit the tree, left to right
+ //
+ // Left-most node is on top of the stack, so we always expand the
+ // left most node each iteration.
+ var stack = new Stack<BindingRestrictions>();
+ stack.Push(_node);
+ do {
+ var top = stack.Pop();
+ var m = top as MergedRestriction;
+ if (m != null) {
+ stack.Push(m.Right);
+ stack.Push(m.Left);
+ } else {
+ restrictions.Add(top);
+ }
+ } while (stack.Count > 0);
+
+ return restrictions.ToArray();
+ }
+ }
+
+ public override string ToString() {
+ // To prevent fxcop warning about this field
+ return _node.DebugView;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallInfo.cs
new file mode 100644
index 00000000000..cf77f1ee12b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallInfo.cs
@@ -0,0 +1,115 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Describes arguments in the dynamic binding process.
+ /// </summary>
+ /// <remarks>
+ /// ArgumentCount - all inclusive number of arguments.
+ /// ArgumentNames - names for those arguments that are named.
+ ///
+ /// Argument names match to the argument values in left to right order
+ /// and last name corresponds to the last argument.
+ ///
+ /// Example:
+ /// Foo(arg1, arg2, arg3, name1 = arg4, name2 = arg5, name3 = arg6)
+ ///
+ /// will correspond to:
+ /// ArgumentCount: 6
+ /// ArgumentNames: {"name1", "name2", "name3"}
+ /// </remarks>
+ public sealed class CallInfo {
+ private readonly int _argCount;
+ private readonly ReadOnlyCollection<string> _argNames;
+
+ /// <summary>
+ /// Creates a new PositionalArgumentInfo.
+ /// </summary>
+ /// <param name="argCount">The number of arguments.</param>
+ /// <param name="argNames">The argument names.</param>
+ /// <returns>The new CallInfo</returns>
+ public CallInfo(int argCount, params string[] argNames)
+ : this(argCount, (IEnumerable<string>)argNames) {
+ }
+
+ /// <summary>
+ /// Creates a new CallInfo that represents arguments in the dynamic binding process.
+ /// </summary>
+ /// <param name="argCount">The number of arguments.</param>
+ /// <param name="argNames">The argument names.</param>
+ /// <returns>The new CallInfo</returns>
+ public CallInfo(int argCount, IEnumerable<string> argNames) {
+ ContractUtils.RequiresNotNull(argNames, "argNames");
+
+ var argNameCol = argNames.ToReadOnly();
+
+ ContractUtils.Requires(argCount >= argNameCol.Count, "argCount", Strings.ArgCntMustBeGreaterThanNameCnt);
+ ContractUtils.RequiresNotNullItems(argNameCol, "argNames");
+
+ _argCount = argCount;
+ _argNames = argNameCol;
+ }
+
+ /// <summary>
+ /// The number of arguments.
+ /// </summary>
+ public int ArgumentCount {
+ get { return _argCount; }
+ }
+
+ /// <summary>
+ /// The argument names.
+ /// </summary>
+ public ReadOnlyCollection<string> ArgumentNames {
+ get { return _argNames; }
+ }
+
+ /// <summary>
+ /// Serves as a hash function for the current CallInfo.
+ /// </summary>
+ /// <returns>A hash code for the current CallInfo.</returns>
+ public override int GetHashCode() {
+ return _argCount ^ _argNames.ListHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified CallInfo instance is considered equal to the current.
+ /// </summary>
+ /// <param name="obj">The instance of CallInfo to compare with the current instance.</param>
+ /// <returns>true if the specified instance is equal to the current one otherwise, false.</returns>
+ public override bool Equals(object obj) {
+ var other = obj as CallInfo;
+ return _argCount == other._argCount && _argNames.ListEquals(other._argNames);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSite.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSite.cs
new file mode 100644
index 00000000000..3158164274a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSite.cs
@@ -0,0 +1,709 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+
+ //
+ // A CallSite provides a fast mechanism for call-site caching of dynamic dispatch
+ // behvaior. Each site will hold onto a delegate that provides a fast-path dispatch
+ // based on previous types that have been seen at the call-site. This delegate will
+ // call UpdateAndExecute if it is called with types that it hasn't seen before.
+ // Updating the binding will typically create (or lookup) a new delegate
+ // that supports fast-paths for both the new type and for any types that
+ // have been seen previously.
+ //
+ // DynamicSites will generate the fast-paths specialized for sets of runtime argument
+ // types. However, they will generate exactly the right amount of code for the types
+ // that are seen in the program so that int addition will remain as fast as it would
+ // be with custom implementation of the addition, and the user-defined types can be
+ // as fast as ints because they will all have the same optimal dynamically generated
+ // fast-paths.
+ //
+ // DynamicSites don't encode any particular caching policy, but use their
+ // CallSiteBinding to encode a caching policy.
+ //
+
+
+ /// <summary>
+ /// A Dynamic Call Site base class. This type is used as a parameter type to the
+ /// dynamic site targets. The first parameter of the delegate (T) below must be
+ /// of this type.
+ /// </summary>
+ public class CallSite {
+
+ // Cache of CallSite constructors for a given delegate type
+ private static CacheDict<Type, Func<CallSiteBinder, CallSite>> _SiteCtors;
+
+ /// <summary>
+ /// The Binder responsible for binding operations at this call site.
+ /// This binder is invoked by the UpdateAndExecute below if all Level 0,
+ /// Level 1 and Level 2 caches experience cache miss.
+ /// </summary>
+ internal readonly CallSiteBinder _binder;
+
+ // only CallSite<T> derives from this
+ internal CallSite(CallSiteBinder binder) {
+ _binder = binder;
+ }
+
+ /// <summary>
+ /// used by Matchmaker sites to indicate rule match.
+ /// </summary>
+ internal bool _match;
+
+ /// <summary>
+ /// Class responsible for binding dynamic operations on the dynamic site.
+ /// </summary>
+ public CallSiteBinder Binder {
+ get { return _binder; }
+ }
+
+ /// <summary>
+ /// Creates a CallSite with the given delegate type and binder.
+ /// </summary>
+ /// <param name="delegateType">The CallSite delegate type.</param>
+ /// <param name="binder">The CallSite binder.</param>
+ /// <returns>The new CallSite.</returns>
+ public static CallSite Create(Type delegateType, CallSiteBinder binder) {
+ ContractUtils.RequiresNotNull(delegateType, "delegateType");
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.Requires(delegateType.IsSubclassOf(typeof(Delegate)), "delegateType", Strings.TypeMustBeDerivedFromSystemDelegate);
+
+ if (_SiteCtors == null) {
+ // It's okay to just set this, worst case we're just throwing away some data
+ _SiteCtors = new CacheDict<Type, Func<CallSiteBinder, CallSite>>(100);
+ }
+ Func<CallSiteBinder, CallSite> ctor;
+
+ var ctors = _SiteCtors;
+ lock (ctors) {
+ if (!ctors.TryGetValue(delegateType, out ctor)) {
+ MethodInfo method = typeof(CallSite<>).MakeGenericType(delegateType).GetMethod("Create");
+ ctor = (Func<CallSiteBinder, CallSite>)Delegate.CreateDelegate(typeof(Func<CallSiteBinder, CallSite>), method);
+ ctors.Add(delegateType, ctor);
+ }
+ }
+ return ctor(binder);
+ }
+ }
+
+ /// <summary>
+ /// Dynamic site type.
+ /// </summary>
+ /// <typeparam name="T">The delegate type.</typeparam>
+ public sealed partial class CallSite<T> : CallSite where T : class {
+ /// <summary>
+ /// The update delegate. Called when the dynamic site experiences cache miss.
+ /// </summary>
+ /// <returns>The update delegate.</returns>
+ public T Update {
+ get {
+ // if this site is set up for match making, then use NoMatch as an Update
+ if (_match) {
+ Debug.Assert(_CachedNoMatch != null, "all normal sites should have Update cached once there is an instance.");
+ return _CachedNoMatch;
+ } else {
+ Debug.Assert(_CachedUpdate != null, "all normal sites should have Update cached once there is an instance.");
+ return _CachedUpdate;
+ }
+ }
+ }
+
+ /// <summary>
+ /// The Level 0 cache - a delegate specialized based on the site history.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
+ public T Target;
+
+
+ /// <summary>
+ /// The Level 1 cache - a history of the dynamic site.
+ /// </summary>
+ internal T[] Rules;
+
+
+ // Cached update delegate for all sites with a given T
+ private static T _CachedUpdate;
+
+ // Cached noMatch delegate for all sites with a given T
+ private static T _CachedNoMatch;
+
+ private CallSite(CallSiteBinder binder)
+ : base(binder) {
+ Target = GetUpdateDelegate();
+ }
+
+ private CallSite()
+ : base(null) {
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ internal CallSite<T> CreateMatchMaker() {
+ return new CallSite<T>();
+ }
+
+ /// <summary>
+ /// Creates an instance of the dynamic call site, initialized with the binder responsible for the
+ /// runtime binding of the dynamic operations at this call site.
+ /// </summary>
+ /// <param name="binder">The binder responsible for the runtime binding of the dynamic operations at this call site.</param>
+ /// <returns>The new instance of dynamic call site.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
+ public static CallSite<T> Create(CallSiteBinder binder) {
+ return new CallSite<T>(binder);
+ }
+
+ private T GetUpdateDelegate() {
+ // This is intentionally non-static to speed up creation - in particular MakeUpdateDelegate
+ // as static generic methods are more expensive than instance methods. We call a ref helper
+ // so we only access the generic static field once.
+ return GetUpdateDelegate(ref _CachedUpdate);
+ }
+
+ private T GetUpdateDelegate(ref T addr) {
+ if (addr == null) {
+ // reduce creation cost by not using Interlocked.CompareExchange. Calling I.CE causes
+ // us to spend 25% of our creation time in JIT_GenericHandle. Instead we'll rarely
+ // create 2 delegates with no other harm caused.
+ addr = MakeUpdateDelegate();
+ }
+ return addr;
+ }
+
+ /// <summary>
+ /// Clears the rule cache ... used by the call site tests.
+ /// </summary>
+ private void ClearRuleCache() {
+ // make sure it initialized/atomized etc...
+ Binder.GetRuleCache<T>();
+
+ var cache = Binder.Cache;
+
+ if (cache != null) {
+ lock (cache) {
+ cache.Clear();
+ }
+ }
+ }
+
+ const int MaxRules = 10;
+ internal void AddRule(T newRule) {
+ T[] rules = Rules;
+ if (rules == null) {
+ Rules = new[] { newRule };
+ return;
+ }
+
+ T[] temp;
+ if (rules.Length < (MaxRules - 1)) {
+ temp = new T[rules.Length + 1];
+ Array.Copy(rules, 0, temp, 1, rules.Length);
+ } else {
+ temp = new T[MaxRules];
+ Array.Copy(rules, 0, temp, 1, MaxRules - 1);
+ }
+ temp[0] = newRule;
+ Rules = temp;
+ }
+
+ // moves rule +2 up.
+ internal void MoveRule(int i) {
+ var rules = Rules;
+ var rule = rules[i];
+
+ rules[i] = rules[i - 1];
+ rules[i - 1] = rules[i - 2];
+ rules[i - 2] = rule;
+ }
+
+ internal T MakeUpdateDelegate() {
+ Type target = typeof(T);
+ Type[] args;
+ MethodInfo invoke = target.GetMethod("Invoke");
+
+
+ if (target.IsGenericType && IsSimpleSignature(invoke, out args)) {
+ MethodInfo method = null;
+ MethodInfo noMatchMethod = null;
+
+ if (invoke.ReturnType == typeof(void)) {
+ if (target == DelegateHelpers.GetActionType(args.AddFirst(typeof(CallSite)))) {
+ method = typeof(UpdateDelegates).GetMethod("UpdateAndExecuteVoid" + args.Length, BindingFlags.NonPublic | BindingFlags.Static);
+ noMatchMethod = typeof(UpdateDelegates).GetMethod("NoMatchVoid" + args.Length, BindingFlags.NonPublic | BindingFlags.Static);
+ }
+ } else {
+ if (target == DelegateHelpers.GetFuncType(args.AddFirst(typeof(CallSite)))) {
+ method = typeof(UpdateDelegates).GetMethod("UpdateAndExecute" + (args.Length - 1), BindingFlags.NonPublic | BindingFlags.Static);
+ noMatchMethod = typeof(UpdateDelegates).GetMethod("NoMatch" + (args.Length - 1), BindingFlags.NonPublic | BindingFlags.Static);
+ }
+ }
+ if (method != null) {
+ _CachedNoMatch = (T)(object)noMatchMethod.MakeGenericMethod(args).CreateDelegate(target);
+ return (T)(object)method.MakeGenericMethod(args).CreateDelegate(target);
+ }
+ }
+
+ _CachedNoMatch = CreateCustomNoMatchDelegate(invoke);
+ return CreateCustomUpdateDelegate(invoke);
+ }
+
+
+ private static bool IsSimpleSignature(MethodInfo invoke, out Type[] sig) {
+ ParameterInfo[] pis = invoke.GetParametersCached();
+ ContractUtils.Requires(pis.Length > 0 && pis[0].ParameterType == typeof(CallSite), "T");
+
+ Type[] args = new Type[invoke.ReturnType != typeof(void) ? pis.Length : pis.Length - 1];
+ bool supported = true;
+
+ for (int i = 1; i < pis.Length; i++) {
+ ParameterInfo pi = pis[i];
+ if (pi.IsByRefParameter()) {
+ supported = false;
+ }
+ args[i - 1] = pi.ParameterType;
+ }
+ if (invoke.ReturnType != typeof(void)) {
+ args[args.Length - 1] = invoke.ReturnType;
+ }
+ sig = args;
+ return supported;
+ }
+
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ private T CreateCustomNoMatchDelegate(MethodInfo invoke) {
+ var @params = invoke.GetParametersCached().Map(p => Expression.Parameter(p.ParameterType, p.Name));
+ var site = @params[0];
+ return Expression.Lambda<T>(
+ Expression.Block(
+ Expression.Call(
+ typeof(CallSiteOps).GetMethod("SetNotMatched"),
+ @params.First()
+ ),
+ Expression.Default(invoke.GetReturnType())
+ ),
+ @params
+ ).Compile();
+ }
+
+ //
+ // WARNING: If you're changing this method, make sure you update the
+ // pregenerated versions as well, which are generated by
+ // generate_dynsites.py
+ // The two implementations *must* be kept functionally equivalent!
+ //
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ private T CreateCustomUpdateDelegate(MethodInfo invoke) {
+ var body = new List<Expression>();
+ var vars = new List<ParameterExpression>();
+ var @params = invoke.GetParametersCached().Map(p => Expression.Parameter(p.ParameterType, p.Name));
+ var @return = Expression.Label(invoke.GetReturnType());
+ var typeArgs = new[] { typeof(T) };
+
+ var site = @params[0];
+ var arguments = @params.RemoveFirst();
+
+ //var @this = (CallSite<T>)site;
+ var @this = Expression.Variable(typeof(CallSite<T>), "this");
+ vars.Add(@this);
+ body.Add(Expression.Assign(@this, Expression.Convert(site, @this.Type)));
+
+ //T[] applicable;
+ var applicable = Expression.Variable(typeof(T[]), "applicable");
+ vars.Add(applicable);
+
+ //T rule, originalRule = @this.Target;
+ var rule = Expression.Variable(typeof(T), "rule");
+ vars.Add(rule);
+
+ var originalRule = Expression.Variable(typeof(T), "originalRule");
+ vars.Add(originalRule);
+ body.Add(Expression.Assign(originalRule, Expression.Field(@this, "Target")));
+
+ //TRet result;
+ ParameterExpression result = null;
+ if (@return.Type != typeof(void)) {
+ vars.Add(result = Expression.Variable(@return.Type, "result"));
+ }
+
+ //int count, index;
+ var count = Expression.Variable(typeof(int), "count");
+ vars.Add(count);
+ var index = Expression.Variable(typeof(int), "index");
+ vars.Add(index);
+
+ ////
+ //// Create matchmaker site. We'll need it regardless.
+ ////
+ //site = CallSiteOps.CreateMatchmaker();
+ body.Add(
+ Expression.Assign(
+ site,
+ Expression.Call(
+ typeof(CallSiteOps),
+ "CreateMatchmaker",
+ typeArgs,
+ @this
+ )
+ )
+ );
+
+ ////
+ //// Level 1 cache lookup
+ ////
+ //if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ // for (index = 0, count = applicable.Length; index < count; index++) {
+ // @this.Target = rule = applicable[i];
+
+ // //
+ // // Execute the rule
+ // //
+ //
+ // // if we've already tried it skip it...
+ // if ((object)rule != (object)originalRule) {
+ // %(setResult)s rule(site, %(args)s);
+ // if (CallSiteOps.GetMatch(site)) {
+ // CallSiteOps.UpdateRules(@this, i);
+ // %(returnResult)s;
+ // }
+ //
+ // // Rule didn't match, try the next one
+ // CallSiteOps.ClearMatch(site);
+ // }
+ // }
+ //}
+ Expression invokeRule;
+
+ Expression getMatch = Expression.Call(
+ typeof(CallSiteOps).GetMethod("GetMatch"),
+ site
+ );
+
+ Expression resetMatch = Expression.Call(
+ typeof(CallSiteOps).GetMethod("ClearMatch"),
+ site
+ );
+
+ var onMatch = Expression.Call(
+ typeof(CallSiteOps),
+ "UpdateRules",
+ typeArgs,
+ @this,
+ index
+ );
+
+ if (@return.Type == typeof(void)) {
+ invokeRule = Expression.Block(
+ Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params)),
+ Expression.IfThen(
+ getMatch,
+ Expression.Block(onMatch, Expression.Return(@return))
+ )
+ );
+ } else {
+ invokeRule = Expression.Block(
+ Expression.Assign(result, Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params))),
+ Expression.IfThen(
+ getMatch,
+ Expression.Block(onMatch, Expression.Return(@return, result))
+ )
+ );
+ }
+
+ Expression getRule = Expression.Assign(rule, Expression.ArrayAccess(applicable, index));
+
+ var @break = Expression.Label();
+
+ var breakIfDone = Expression.IfThen(
+ Expression.Equal(index, count),
+ Expression.Break(@break)
+ );
+
+ var incrementIndex = Expression.PreIncrementAssign(index);
+
+ body.Add(
+ Expression.IfThen(
+ Expression.NotEqual(
+ Expression.Assign(applicable, Expression.Call(typeof(CallSiteOps), "GetRules", typeArgs, @this)),
+ Expression.Constant(null, applicable.Type)
+ ),
+ Expression.Block(
+ Expression.Assign(count, Expression.ArrayLength(applicable)),
+ Expression.Assign(index, Expression.Constant(0)),
+ Expression.Loop(
+ Expression.Block(
+ breakIfDone,
+ getRule,
+ Expression.IfThen(
+ Expression.NotEqual(
+ Expression.Convert(rule, typeof(object)),
+ Expression.Convert(originalRule, typeof(object))
+ ),
+ Expression.Block(
+ Expression.Assign(
+ Expression.Field(@this, "Target"),
+ rule
+ ),
+ invokeRule,
+ resetMatch
+ )
+ ),
+ incrementIndex
+ ),
+ @break,
+ null
+ )
+ )
+ )
+ );
+
+ ////
+ //// Level 2 cache lookup
+ ////
+ //
+ ////
+ //// Any applicable rules in level 2 cache?
+ ////
+ //
+ // var cache = CallSiteOps.GetRuleCache(@this);
+
+ var cache = Expression.Variable(typeof(RuleCache<T>), "cache");
+ vars.Add(cache);
+
+ body.Add(
+ Expression.Assign(
+ cache,
+ Expression.Call(typeof(CallSiteOps), "GetRuleCache", typeArgs, @this)
+ )
+ );
+
+ // applicable = cache.GetRules();
+
+ body.Add(
+ Expression.Assign(
+ applicable,
+ Expression.Call(typeof(CallSiteOps), "GetCachedRules", typeArgs, cache)
+ )
+ );
+
+ // for (int i = 0, count = applicable.Length; i < count; i++) {
+ // @this.Target = rule = applicable[i];
+ //
+ // //
+ // // Execute the rule
+ // //
+ //
+ // try {
+ // result = rule(site, arg0);
+ // if (match) {
+ // return result;
+ // }
+ // } finally {
+ // if (CallSiteOps.GetMatch(site)) {
+ // //
+ // // Rule worked. Add it to level 1 cache
+ // //
+ //
+ // CallSiteOps.AddRule(@this, rule);
+ // // and then move it to the front of the L2 cache
+ // CallSiteOps.MoveRule(cache, rule, index);
+ // }
+ // }
+ //
+ // // Rule didn't match, try the next one
+ // CallSiteOps.ClearMatch(site);
+ // }
+ //
+
+
+ // L2 invokeRule is different (no onMatch)
+ if (@return.Type == typeof(void)) {
+ invokeRule = Expression.Block(
+ Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params)),
+ Expression.IfThen(
+ getMatch,
+ Expression.Return(@return)
+ )
+ );
+ } else {
+ invokeRule = Expression.Block(
+ Expression.Assign(result, Expression.Invoke(rule, new TrueReadOnlyCollection<Expression>(@params))),
+ Expression.IfThen(
+ getMatch,
+ Expression.Return(@return, result)
+ )
+ );
+ }
+
+ var tryRule = Expression.TryFinally(
+ invokeRule,
+ Expression.IfThen(
+ getMatch,
+ Expression.Block(
+ Expression.Call(typeof(CallSiteOps), "AddRule", typeArgs, @this, rule),
+ Expression.Call(typeof(CallSiteOps), "MoveRule", typeArgs, cache, rule, index)
+ )
+ )
+ );
+
+ getRule = Expression.Assign(
+ Expression.Field(@this, "Target"),
+ Expression.Assign(rule, Expression.ArrayAccess(applicable, index))
+ );
+
+ body.Add(Expression.Assign(index, Expression.Constant(0)));
+ body.Add(Expression.Assign(count, Expression.ArrayLength(applicable)));
+ body.Add(
+ Expression.Loop(
+ Expression.Block(
+ breakIfDone,
+ getRule,
+ tryRule,
+ resetMatch,
+ incrementIndex
+ ),
+ @break,
+ null
+ )
+ );
+
+ ////
+ //// Miss on Level 0, 1 and 2 caches. Create new rule
+ ////
+
+ //rule = null;
+ body.Add(Expression.Assign(rule, Expression.Constant(null, rule.Type)));
+
+ //var args = new object[] { arg0, arg1, ... };
+ var args = Expression.Variable(typeof(object[]), "args");
+ vars.Add(args);
+ body.Add(
+ Expression.Assign(
+ args,
+ Expression.NewArrayInit(typeof(object), arguments.Map(p => Convert(p, typeof(object))))
+ )
+ );
+
+ //for (; ; ) {
+ // @this.Target = originalRule;
+ // rule = @this.Target = @this.Binder.BindDelegate(@this, args);
+
+ // //
+ // // Execute the rule on the matchmaker site
+ // //
+
+ // try {
+ // %(setResult)s ruleTarget(site, %(args)s);
+ // if (match) {
+ // %(returnResult)s;
+ // }
+ // } finally {
+ // if (match) {
+ // //
+ // // The rule worked. Add it to level 1 cache.
+ // //
+ // CallSiteOps.AddRule(@this, rule);
+ // }
+ // }
+
+ // // Rule we got back didn't work, try another one
+ // match = true;
+ //}
+
+ Expression setOldTarget = Expression.Assign(
+ Expression.Field(@this, "Target"),
+ originalRule
+ );
+
+ getRule = Expression.Assign(
+ Expression.Field(@this, "Target"),
+ Expression.Assign(
+ rule,
+ Expression.Call(
+ typeof(CallSiteOps),
+ "Bind",
+ typeArgs,
+ Expression.Property(@this, "Binder"),
+ @this,
+ args
+ )
+ )
+ );
+
+ tryRule = Expression.TryFinally(
+ invokeRule,
+ Expression.IfThen(
+ getMatch,
+ Expression.Call(typeof(CallSiteOps), "AddRule", typeArgs, @this, rule)
+ )
+ );
+
+ body.Add(
+ Expression.Loop(
+ Expression.Block(setOldTarget, getRule, tryRule, resetMatch),
+ null, null
+ )
+ );
+
+ body.Add(Expression.Default(@return.Type));
+
+ var lambda = Expression.Lambda<T>(
+ Expression.Label(
+ @return,
+ Expression.Block(
+ new ReadOnlyCollection<ParameterExpression>(vars),
+ new ReadOnlyCollection<Expression>(body)
+ )
+ ),
+ "CallSite.Target",
+ true, // always compile the rules with tail call optimization
+ new ReadOnlyCollection<ParameterExpression>(@params)
+ );
+
+ // Need to compile with forceDynamic because T could be invisible,
+ // or one of the argument types could be invisible
+ return lambda.Compile();
+ }
+
+ private static Expression Convert(Expression arg, Type type) {
+ if (TypeUtils.AreReferenceAssignable(type, arg.Type)) {
+ return arg;
+ }
+ return Expression.Convert(arg, type);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteBinder.cs
new file mode 100644
index 00000000000..bfd76825ced
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteBinder.cs
@@ -0,0 +1,239 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+using System.Threading;
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// Class responsible for runtime binding of the dynamic operations on the dynamic call site.
+ /// </summary>
+ public abstract class CallSiteBinder {
+ private static readonly LabelTarget _updateLabel = Expression.Label("CallSiteBinder.UpdateLabel");
+
+ /// <summary>
+ /// The Level 2 cache - all rules produced for the same binder.
+ /// </summary>
+ internal Dictionary<Type, object> Cache;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CallSiteBinder"/> class.
+ /// </summary>
+ protected CallSiteBinder() {
+ }
+
+ /// <summary>
+ /// Gets a label that can be used to cause the binding to be updated. It
+ /// indicates that the expression's binding is no longer valid.
+ /// This is typically used when the "version" of a dynamic object has
+ /// changed.
+ /// </summary>
+ public static LabelTarget UpdateLabel {
+ get { return _updateLabel; }
+ }
+
+ private sealed class LambdaSignature<T> where T : class {
+ internal static readonly LambdaSignature<T> Instance = new LambdaSignature<T>();
+
+ internal readonly ReadOnlyCollection<ParameterExpression> Parameters;
+ internal readonly LabelTarget ReturnLabel;
+
+ private LambdaSignature() {
+ Type target = typeof(T);
+ if (!typeof(Delegate).IsAssignableFrom(target)) {
+ throw Error.TypeParameterIsNotDelegate(target);
+ }
+
+ MethodInfo invoke = target.GetMethod("Invoke");
+ ParameterInfo[] pis = invoke.GetParametersCached();
+ if (pis[0].ParameterType != typeof(CallSite)) {
+ throw Error.FirstArgumentMustBeCallSite();
+ }
+
+ var @params = new ParameterExpression[pis.Length - 1];
+ for (int i = 0; i < @params.Length; i++) {
+ @params[i] = Expression.Parameter(pis[i + 1].ParameterType, "$arg" + i);
+ }
+
+ Parameters = new TrueReadOnlyCollection<ParameterExpression>(@params);
+ ReturnLabel = Expression.Label(invoke.GetReturnType());
+ }
+ }
+
+ /// <summary>
+ /// Performs the runtime binding of the dynamic operation on a set of arguments.
+ /// </summary>
+ /// <param name="args">An array of arguments to the dynamic operation.</param>
+ /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param>
+ /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
+ /// <returns>
+ /// An Expression that performs tests on the dynamic operation arguments, and
+ /// performs the dynamic operation if hte tests are valid. If the tests fail on
+ /// subsequent occurrences of the dynamic operation, Bind will be called again
+ /// to produce a new <see cref="Expression"/> for the new argument types.
+ /// </returns>
+ public abstract Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel);
+
+ /// <summary>
+ /// Provides low-level runtime binding support. Classes can override this and provide a direct
+ /// delegate for the implementation of rule. This can enable saving rules to disk, having
+ /// specialized rules available at runtime, or providing a different caching policy.
+ /// </summary>
+ /// <typeparam name="T">The target type of the CallSite.</typeparam>
+ /// <param name="site">The CallSite the bind is being performed for.</param>
+ /// <param name="args">The arguments for the binder.</param>
+ /// <returns>A new delegate which replaces the CallSite Target.</returns>
+ public virtual T BindDelegate<T>(CallSite<T> site, object[] args) where T : class {
+ return null;
+ }
+
+
+ internal T BindCore<T>(CallSite<T> site, object[] args) where T : class {
+ //
+ // Try to find a precompiled delegate, and return it if found.
+ //
+ T result = BindDelegate(site, args);
+ if (result != null) {
+ return result;
+ }
+
+ //
+ // Get the Expression for the binding
+ //
+ var signature = LambdaSignature<T>.Instance;
+ Expression binding = Bind(args, signature.Parameters, signature.ReturnLabel);
+
+ //
+ // Check the produced rule
+ //
+ if (binding == null) {
+ throw Error.NoOrInvalidRuleProduced();
+ }
+
+ //
+ // finally produce the new rule if we need to
+ //
+#if !MICROSOFT_SCRIPTING_CORE
+ // We cannot compile rules in the heterogeneous app domains since they
+ // may come from less trusted sources
+ if (!AppDomain.CurrentDomain.IsHomogenous) {
+ throw Error.HomogenousAppDomainRequired();
+ }
+#endif
+ Expression<T> e = Stitch(binding, signature);
+ T newRule = e.Compile();
+
+ CacheTarget(newRule);
+
+ return newRule;
+ }
+
+ /// <summary>
+ /// Adds a target to the cache of known targets. The cached targets will
+ /// be scanned before calling BindDelegate to produce the new rule.
+ /// </summary>
+ /// <typeparam name="T">The type of target being added.</typeparam>
+ /// <param name="target">The target delegate to be added to the cache.</param>
+ protected void CacheTarget<T>(T target) where T : class {
+ GetRuleCache<T>().AddRule(target);
+ }
+
+ private static Expression<T> Stitch<T>(Expression binding, LambdaSignature<T> signature) where T : class {
+ Type targetType = typeof(T);
+ Type siteType = typeof(CallSite<T>);
+
+ var body = new ReadOnlyCollectionBuilder<Expression>(3);
+ body.Add(binding);
+
+ var site = Expression.Parameter(typeof(CallSite), "$site");
+ var @params = signature.Parameters.AddFirst(site);
+
+ Expression updLabel = Expression.Label(CallSiteBinder.UpdateLabel);
+
+#if DEBUG
+ // put the AST into the constant pool for debugging purposes
+ updLabel = Expression.Block(
+ Expression.Constant(binding, typeof(Expression)),
+ updLabel
+ );
+#endif
+
+ body.Add(updLabel);
+ body.Add(
+ Expression.Label(
+ signature.ReturnLabel,
+ Expression.Condition(
+ Expression.Call(
+ typeof(CallSiteOps).GetMethod("SetNotMatched"),
+ @params.First()
+ ),
+ Expression.Default(signature.ReturnLabel.Type),
+ Expression.Invoke(
+ Expression.Property(
+ Expression.Convert(site, siteType),
+ typeof(CallSite<T>).GetProperty("Update")
+ ),
+ new TrueReadOnlyCollection<Expression>(@params)
+ )
+ )
+ )
+ );
+
+ return new Expression<T>(
+ Expression.Block(body),
+ "CallSite.Target",
+ true, // always compile the rules with tail call optimization
+ new TrueReadOnlyCollection<ParameterExpression>(@params)
+ );
+ }
+
+ internal RuleCache<T> GetRuleCache<T>() where T : class {
+ // make sure we have cache.
+ if (Cache == null) {
+ Interlocked.CompareExchange(ref Cache, new Dictionary<Type, object>(), null);
+ }
+
+ object ruleCache;
+ var cache = Cache;
+ lock (cache) {
+ if (!cache.TryGetValue(typeof(T), out ruleCache)) {
+ cache[typeof(T)] = ruleCache = new RuleCache<T>();
+ }
+ }
+
+ RuleCache<T> result = ruleCache as RuleCache<T>;
+ Debug.Assert(result != null);
+ return result;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteHelpers.cs
new file mode 100644
index 00000000000..0768092cb58
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteHelpers.cs
@@ -0,0 +1,62 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Reflection;
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// Class that contains helper methods for DLR CallSites.
+ /// </summary>
+ public static class CallSiteHelpers {
+ private static Type _knownNonDynamicMethodType = typeof(object).GetMethod("ToString").GetType();
+
+ /// <summary>
+ /// Checks if a <see cref="MethodBase"/> is internally used by DLR and should not
+ /// be displayed on the language code's stack.
+ /// </summary>
+ /// <param name="mb">The input <see cref="MethodBase"/></param>
+ /// <returns>
+ /// True if the input <see cref="MethodBase"/> is internally used by DLR and should not
+ /// be displayed on the language code's stack. Otherwise, false.
+ /// </returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
+ public static bool IsInternalFrame(MethodBase mb) {
+ //All the dynamic methods created for DLR rules have a special name.
+ //We also check if the method has a different type than the known
+ //non-static method. If it does, it is a dynamic method.
+ //This could be improved if the CLR provides a way to attach some information
+ //to the dynamic method we create, like CustomAttributes.
+ if (mb.Name == "CallSite.Target" && mb.GetType() != _knownNonDynamicMethodType) {
+ return true;
+ }
+
+ //Filter out the helper methods.
+#if CODEPLEX_40
+ if (mb.DeclaringType == typeof(System.Dynamic.UpdateDelegates)) {
+#else
+ if (mb.DeclaringType == typeof(Microsoft.Scripting.UpdateDelegates)) {
+#endif
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteOps.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteOps.cs
new file mode 100644
index 00000000000..1585a2e1517
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CallSiteOps.cs
@@ -0,0 +1,173 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.ComponentModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting;
+using Microsoft.Linq.Expressions;
+#endif
+using System.Collections.Generic;
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+
+ // Conceptually these are instance methods on CallSite<T> but
+ // we don't want users to see them
+
+ /// <summary>
+ /// This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never), DebuggerStepThrough]
+ public static class CallSiteOps {
+
+ /// <summary>
+ /// Creates an instance of a dynamic call site used for cache lookup.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <returns>The new call site.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static CallSite<T> CreateMatchmaker<T>(CallSite<T> site) where T : class {
+ var mm = site.CreateMatchMaker();
+ CallSiteOps.ClearMatch(mm);
+ return mm;
+ }
+
+ /// <summary>
+ /// Checks if a dynamic site requires an update.
+ /// </summary>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ /// <returns>true if rule does not need updating, false otherwise.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static bool SetNotMatched(CallSite site) {
+ var res = site._match;
+ site._match = false; //avoid branch here to make sure the method is inlined
+ return res;
+ }
+
+ /// <summary>
+ /// Checks whether the executed rule matched
+ /// </summary>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ /// <returns>true if rule matched, false otherwise.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static bool GetMatch(CallSite site) {
+ return site._match;
+ }
+
+ /// <summary>
+ /// Clears the match flag on the matchmaker call site.
+ /// </summary>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static void ClearMatch(CallSite site) {
+ site._match = true;
+ }
+
+ /// <summary>
+ /// Adds a rule to the cache maintained on the dynamic call site.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ /// <param name="rule">An instance of the call site rule.</param>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static void AddRule<T>(CallSite<T> site, T rule) where T : class {
+ site.AddRule(rule);
+ }
+
+ /// <summary>
+ /// Updates rules in the cache.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="this">An instance of the dynamic call site.</param>
+ /// <param name="matched">The matched rule index.</param>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static void UpdateRules<T>(CallSite<T> @this, int matched) where T : class {
+ if (matched > 1) {
+ @this.MoveRule(matched);
+ }
+ }
+
+ /// <summary>
+ /// Gets the dynamic binding rules from the call site.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ /// <returns>An array of dynamic binding rules.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static T[] GetRules<T>(CallSite<T> site) where T : class {
+ return site.Rules;
+ }
+
+
+ /// <summary>
+ /// Retrieves binding rule cache.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ /// <returns>The cache.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static RuleCache<T> GetRuleCache<T>(CallSite<T> site) where T : class {
+ return site.Binder.GetRuleCache<T>();
+ }
+
+
+ /// <summary>
+ /// Moves the binding rule within the cache.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="cache">The call site rule cache.</param>
+ /// <param name="rule">An instance of the call site rule.</param>
+ /// <param name="i">An index of the call site rule.</param>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static void MoveRule<T>(RuleCache<T> cache, T rule, int i) where T : class {
+ if (i > 1) {
+ cache.MoveRule(rule, i);
+ }
+ }
+
+ /// <summary>
+ /// Searches the dynamic rule cache for rules applicable to the dynamic operation.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="cache">The cache.</param>
+ /// <returns>The collection of applicable rules.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static T[] GetCachedRules<T>(RuleCache<T> cache) where T : class {
+ return cache.GetRules();
+ }
+
+ /// <summary>
+ /// Updates the call site target with a new rule based on the arguments.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate of the <see cref="CallSite"/>.</typeparam>
+ /// <param name="binder">The call site binder.</param>
+ /// <param name="site">An instance of the dynamic call site.</param>
+ /// <param name="args">Arguments to the call site.</param>
+ /// <returns>The new call site target.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static T Bind<T>(CallSiteBinder binder, CallSite<T> site, object[] args) where T : class {
+ return binder.BindCore(site, args);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ConvertBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ConvertBinder.cs
new file mode 100644
index 00000000000..82f40c35833
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ConvertBinder.cs
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the convert dynamic operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class ConvertBinder : DynamicMetaObjectBinder {
+ private readonly Type _type;
+ private readonly bool _explicit;
+
+ /// <summary>
+ /// Initializes a new intsance of the <see cref="ConvertBinder" />.
+ /// </summary>
+ /// <param name="type">The type to convert to.</param>
+ /// <param name="explicit">true if the conversion should consider explicit conversions; otherwise, false.</param>
+ protected ConvertBinder(Type type, bool @explicit) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ _type = type;
+ _explicit = @explicit;
+ }
+
+ /// <summary>
+ /// The type to convert to.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
+ public Type Type {
+ get {
+ return _type;
+ }
+ }
+
+ /// <summary>
+ /// Gets the value indicating if the conversion should consider explicit conversions.
+ /// </summary>
+ public bool Explicit {
+ get {
+ return _explicit;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic convert operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic convert operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackConvert(DynamicMetaObject target) {
+ return FallbackConvert(target, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic convert operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic convert operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic convert operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic convert operation.</param>
+ /// <param name="args">An array of arguments of the dynamic convert operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.Requires(args == null || args.Length == 0, "args");
+
+ return target.BindConvert(this);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return _type; }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CreateInstanceBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CreateInstanceBinder.cs
new file mode 100644
index 00000000000..15934960b66
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/CreateInstanceBinder.cs
@@ -0,0 +1,97 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the create dynamic operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class CreateInstanceBinder : DynamicMetaObjectBinder {
+ private readonly CallInfo _callInfo;
+
+ /// <summary>
+ /// Initializes a new intsance of the <see cref="CreateInstanceBinder" />.
+ /// </summary>
+ /// <param name="callInfo">The signature of the arguments at the call site.</param>
+ protected CreateInstanceBinder(CallInfo callInfo) {
+ ContractUtils.RequiresNotNull(callInfo, "callInfo");
+ _callInfo = callInfo;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the signature of the arguments at the call site.
+ /// </summary>
+ public CallInfo CallInfo {
+ get { return _callInfo; }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic create operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic create operation.</param>
+ /// <param name="args">The arguments of the dynamic create operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args) {
+ return FallbackCreateInstance(target, args, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic create operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic create operation.</param>
+ /// <param name="args">The arguments of the dynamic create operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackCreateInstance(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic create operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic create operation.</param>
+ /// <param name="args">An array of arguments of the dynamic create operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNullItems(args, "args");
+
+ return target.BindCreateInstance(this, args);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteIndexBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteIndexBinder.cs
new file mode 100644
index 00000000000..8437a5244b2
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteIndexBinder.cs
@@ -0,0 +1,97 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the dynamic delete index operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class DeleteIndexBinder : DynamicMetaObjectBinder {
+ private readonly CallInfo _callInfo;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DeleteIndexBinder" />.
+ /// </summary>
+ /// <param name="callInfo">The signature of the arguments at the call site.</param>
+ protected DeleteIndexBinder(CallInfo callInfo) {
+ ContractUtils.RequiresNotNull(callInfo, "callInfo");
+ _callInfo = callInfo;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(void); }
+ }
+
+ /// <summary>
+ /// Gets the signature of the arguments at the call site.
+ /// </summary>
+ public CallInfo CallInfo {
+ get { return _callInfo; }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic delete index operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic delete index operation.</param>
+ /// <param name="args">An array of arguments of the dynamic delete index operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNullItems(args, "args");
+
+ return target.BindDeleteIndex(this, args);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic delete index operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic delete index operation.</param>
+ /// <param name="indexes">The arguments of the dynamic delete index operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indexes) {
+ return FallbackDeleteIndex(target, indexes, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic delete index operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic delete index operation.</param>
+ /// <param name="indexes">The arguments of the dynamic delete index operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackDeleteIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteMemberBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteMemberBinder.cs
new file mode 100644
index 00000000000..20433264a79
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DeleteMemberBinder.cs
@@ -0,0 +1,112 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Represents the dynamic delete member operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class DeleteMemberBinder : DynamicMetaObjectBinder {
+ private readonly string _name;
+ private readonly bool _ignoreCase;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DeleteIndexBinder" />.
+ /// </summary>
+ /// <param name="name">The name of the member to delete.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ protected DeleteMemberBinder(string name, bool ignoreCase) {
+ ContractUtils.RequiresNotNull(name, "name");
+
+ _name = name;
+ _ignoreCase = ignoreCase;
+ }
+
+ /// <summary>
+ /// Gets the name of the member to delete.
+ /// </summary>
+ public string Name {
+ get {
+ return _name;
+ }
+ }
+
+ /// <summary>
+ /// Gets the value indicating if the string comparison should ignore the case of the member name.
+ /// </summary>
+ public bool IgnoreCase {
+ get {
+ return _ignoreCase;
+ }
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(void); }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic delete member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic delete member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackDeleteMember(DynamicMetaObject target) {
+ return FallbackDeleteMember(target, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic delete member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic delete member operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackDeleteMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic delete member operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic delete member operation.</param>
+ /// <param name="args">An array of arguments of the dynamic delete member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.Requires(args == null || args.Length == 0);
+
+ return target.BindDeleteMember(this);
+ }
+
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObject.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObject.cs
new file mode 100644
index 00000000000..9c5fc873d2e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObject.cs
@@ -0,0 +1,335 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+using System.Runtime.Remoting;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the dynamic binding and a binding logic of an object participating in the dynamic binding.
+ /// </summary>
+ public class DynamicMetaObject {
+ private readonly Expression _expression;
+ private readonly BindingRestrictions _restrictions;
+ private readonly object _value;
+ private readonly bool _hasValue;
+
+ /// <summary>
+ /// Represents an empty array of type <see cref="DynamicMetaObject"/>. This field is read only.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ public static readonly DynamicMetaObject[] EmptyMetaObjects = new DynamicMetaObject[0];
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DynamicMetaObject"/> class.
+ /// </summary>
+ /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
+ /// <param name="restrictions">The set of binding restrictions under which the binding is valid.</param>
+ public DynamicMetaObject(Expression expression, BindingRestrictions restrictions) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+ ContractUtils.RequiresNotNull(restrictions, "restrictions");
+
+ _expression = expression;
+ _restrictions = restrictions;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DynamicMetaObject"/> class.
+ /// </summary>
+ /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
+ /// <param name="restrictions">The set of binding restrictions under which the binding is valid.</param>
+ /// <param name="value">The runtime value represented by the <see cref="DynamicMetaObject"/>.</param>
+ public DynamicMetaObject(Expression expression, BindingRestrictions restrictions, object value)
+ : this(expression, restrictions) {
+ _value = value;
+ _hasValue = true;
+ }
+
+ /// <summary>
+ /// The expression representing the <see cref="DynamicMetaObject"/> during the dynamic binding process.
+ /// </summary>
+ public Expression Expression {
+ get {
+ return _expression;
+ }
+ }
+
+ /// <summary>
+ /// The set of binding restrictions under which the binding is valid.
+ /// </summary>
+ public BindingRestrictions Restrictions {
+ get {
+ return _restrictions;
+ }
+ }
+
+ /// <summary>
+ /// The runtime value represented by this <see cref="DynamicMetaObject"/>.
+ /// </summary>
+ public object Value {
+ get {
+ return _value;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the <see cref="DynamicMetaObject"/> has the runtime value.
+ /// </summary>
+ public bool HasValue {
+ get {
+ return _hasValue;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets the <see cref="Type"/> of the runtime value or null if the <see cref="DynamicMetaObject"/> has no value associated with it.
+ /// </summary>
+ public Type RuntimeType {
+ get {
+ if (_hasValue) {
+ Type ct = Expression.Type;
+ // valuetype at compile tyme, type cannot change.
+ if (ct.IsValueType) {
+ return ct;
+ }
+ if (_value != null) {
+ return _value.GetType();
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the limit type of the <see cref="DynamicMetaObject"/>.
+ /// </summary>
+ /// <remarks>Represents the most specific type known about the object represented by the <see cref="DynamicMetaObject"/>. <see cref="RuntimeType"/> if runtime value is available, a type of the <see cref="Expression"/> otherwise.</remarks>
+ public Type LimitType {
+ get {
+ return RuntimeType ?? Expression.Type;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic conversion operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="ConvertBinder"/> that represents the details of the dynamic operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindConvert(ConvertBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackConvert(this);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic get member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="GetMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindGetMember(GetMemberBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackGetMember(this);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="SetMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set member operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackSetMember(this, value);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic delete member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="DeleteMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackDeleteMember(this);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic get index operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="GetIndexBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the get index operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackGetIndex(this, indexes);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set index operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the set index operation.</param>
+ /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackSetIndex(this, indexes, value);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic delete index operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="DeleteIndexBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the delete index operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackDeleteIndex(this, indexes);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke member operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="InvokeMemberBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke member operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackInvokeMember(this, args);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="InvokeBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the invoke operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackInvoke(this, args);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic create instance operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="CreateInstanceBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="args">An array of <see cref="DynamicMetaObject"/> instances - arguments to the create instance operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackCreateInstance(this, args);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic unary operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="UnaryOperationBinder"/> that represents the details of the dynamic operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackUnaryOperation(this);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic binary operation.
+ /// </summary>
+ /// <param name="binder">An instance of the <see cref="BinaryOperationBinder"/> that represents the details of the dynamic operation.</param>
+ /// <param name="arg">An instance of the <see cref="DynamicMetaObject"/> representing the right hand side of the binary operation.</param>
+ /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public virtual DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ return binder.FallbackBinaryOperation(this, arg);
+ }
+
+ /// <summary>
+ /// Returns the enumeration of all dynamic member names.
+ /// </summary>
+ /// <returns>The list of dynamic member names.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ public virtual IEnumerable<string> GetDynamicMemberNames() {
+ return new string[0];
+ }
+
+ /// <summary>
+ /// Returns the list of expressions represented by the <see cref="DynamicMetaObject"/> instances.
+ /// </summary>
+ /// <param name="objects">An array of <see cref="DynamicMetaObject"/> instances to extract expressions from.</param>
+ /// <returns>The array of expressions.</returns>
+ internal static Expression[] GetExpressions(DynamicMetaObject[] objects) {
+ ContractUtils.RequiresNotNull(objects, "objects");
+
+ Expression[] res = new Expression[objects.Length];
+ for (int i = 0; i < objects.Length; i++) {
+ DynamicMetaObject mo = objects[i];
+ ContractUtils.RequiresNotNull(mo, "objects");
+ Expression expr = mo.Expression;
+ ContractUtils.RequiresNotNull(expr, "objects");
+ res[i] = expr;
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Creates a meta-object for the specified object.
+ /// </summary>
+ /// <param name="value">The object to get a meta-object for.</param>
+ /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
+ /// <returns>
+ /// If the given object implements <see cref="IDynamicMetaObjectProvider"/> and is not a remote object from outside the current AppDomain,
+ /// returns the object's specific meta-object returned by <see cref="IDynamicMetaObjectProvider.GetMetaObject"/>. Otherwise a plain new meta-object
+ /// with no restrictions is created and returned.
+ /// </returns>
+ public static DynamicMetaObject Create(object value, Expression expression) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+
+ IDynamicMetaObjectProvider ido = value as IDynamicMetaObjectProvider;
+#if !SILVERLIGHT
+ if (ido != null && !RemotingServices.IsObjectOutOfAppDomain(value)) {
+#else
+ if (ido != null) {
+#endif
+ var idoMetaObject = ido.GetMetaObject(expression);
+
+ if (idoMetaObject == null ||
+ !idoMetaObject.HasValue ||
+ idoMetaObject.Value == null ||
+ (object)idoMetaObject.Expression != (object)expression) {
+ throw Error.InvalidMetaObjectCreated(ido.GetType());
+ }
+
+ return idoMetaObject;
+ } else {
+ return new DynamicMetaObject(expression, BindingRestrictions.Empty, value);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObjectBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObjectBinder.cs
new file mode 100644
index 00000000000..ae59b973ac1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicMetaObjectBinder.cs
@@ -0,0 +1,305 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Runtime.Remoting;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// The dynamic call site binder that participates in the <see cref="DynamicMetaObject"/> binding protocol.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="CallSiteBinder"/> performs the binding of the dynamic operation using the runtime values
+ /// as input. On the other hand, the <see cref="DynamicMetaObjectBinder"/> participates in the <see cref="DynamicMetaObject"/>
+ /// binding protocol.
+ /// </remarks>
+ public abstract class DynamicMetaObjectBinder : CallSiteBinder {
+
+ #region Public APIs
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DynamicMetaObjectBinder"/> class.
+ /// </summary>
+ protected DynamicMetaObjectBinder() {
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public virtual Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the value indicating if we should validate the result of the binding.
+ /// </summary>
+ protected virtual bool ValidateBindingResult {
+ get { return true; }
+ }
+
+ /// <summary>
+ /// Performs the runtime binding of the dynamic operation on a set of arguments.
+ /// </summary>
+ /// <param name="args">An array of arguments to the dynamic operation.</param>
+ /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param>
+ /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
+ /// <returns>
+ /// An Expression that performs tests on the dynamic operation arguments, and
+ /// performs the dynamic operation if hte tests are valid. If the tests fail on
+ /// subsequent occurrences of the dynamic operation, Bind will be called again
+ /// to produce a new <see cref="Expression"/> for the new argument types.
+ /// </returns>
+ public sealed override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
+ ContractUtils.RequiresNotNull(args, "args");
+ ContractUtils.RequiresNotNull(parameters, "parameters");
+ ContractUtils.RequiresNotNull(returnLabel, "returnLabel");
+ if (args.Length == 0) {
+ throw Error.OutOfRange("args.Length", 1);
+ }
+ if (parameters.Count == 0) {
+ throw Error.OutOfRange("parameters.Count", 1);
+ }
+ if (args.Length != parameters.Count) {
+ throw new ArgumentOutOfRangeException("args");
+ }
+
+ // Ensure that the binder's ReturnType matches CallSite's return
+ // type. We do this so meta objects and language binders can
+ // compose trees together without needing to insert converts.
+ //
+ // For now, we need to allow binders to opt out of this check.
+ Type expectedResult;
+ if (ValidateBindingResult) {
+ expectedResult = ReturnType;
+
+ if (returnLabel.Type != typeof(void) &&
+ !TypeUtils.AreReferenceAssignable(returnLabel.Type, expectedResult)) {
+ throw Error.BinderNotCompatibleWithCallSite(expectedResult, this, returnLabel.Type);
+ }
+ } else {
+ // We have to at least make sure it works with the CallSite's
+ // type to build the return.
+ expectedResult = returnLabel.Type;
+ }
+
+ DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]);
+ DynamicMetaObject[] metaArgs = CreateArgumentMetaObjects(args, parameters);
+
+ DynamicMetaObject binding = Bind(target, metaArgs);
+
+ if (binding == null) {
+ throw Error.BindingCannotBeNull();
+ }
+
+ Expression body = binding.Expression;
+ BindingRestrictions restrictions = binding.Restrictions;
+
+ // Ensure the result matches the expected result type.
+ if (expectedResult != typeof(void) &&
+ !TypeUtils.AreReferenceAssignable(expectedResult, body.Type)) {
+
+ //
+ // Blame the last person that handled the result: assume it's
+ // the dynamic object (if any), otherwise blame the language.
+ //
+ if (target.Value is IDynamicMetaObjectProvider) {
+ throw Error.DynamicObjectResultNotAssignable(body.Type, target.Value.GetType(), this, expectedResult);
+ } else {
+ throw Error.DynamicBinderResultNotAssignable(body.Type, this, expectedResult);
+ }
+ }
+
+ // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding.
+ // it makes sense to restrict on the target's type in such cases.
+ // ideally IDO metaobjects should do this, but they often miss that type of "this" is significant.
+ if (IsStandardBinder && args[0] as IDynamicMetaObjectProvider != null) {
+ if (restrictions == BindingRestrictions.Empty) {
+ throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this);
+ }
+ }
+
+ restrictions = AddRemoteObjectRestrictions(restrictions, args, parameters);
+
+ // Add the return
+ if (body.NodeType != ExpressionType.Goto) {
+ body = Expression.Return(returnLabel, body);
+ }
+
+ // Finally, add restrictions
+ if (restrictions != BindingRestrictions.Empty) {
+ body = Expression.IfThen(restrictions.ToExpression(), body);
+ }
+
+ return body;
+ }
+
+ private static DynamicMetaObject[] CreateArgumentMetaObjects(object[] args, ReadOnlyCollection<ParameterExpression> parameters) {
+ DynamicMetaObject[] mos;
+ if (args.Length != 1) {
+ mos = new DynamicMetaObject[args.Length - 1];
+ for (int i = 1; i < args.Length; i++) {
+ mos[i - 1] = DynamicMetaObject.Create(args[i], parameters[i]);
+ }
+ } else {
+ mos = DynamicMetaObject.EmptyMetaObjects;
+ }
+ return mos;
+ }
+
+ private static BindingRestrictions AddRemoteObjectRestrictions(BindingRestrictions restrictions, object[] args, ReadOnlyCollection<ParameterExpression> parameters) {
+#if !SILVERLIGHT
+
+ for (int i = 0; i < parameters.Count; i++) {
+ var expr = parameters[i];
+ var value = args[i] as MarshalByRefObject;
+
+ // special case for MBR objects.
+ // when MBR objects are remoted they can have different conversion behavior
+ // so bindings created for local and remote objects should not be mixed.
+ if (value != null && !IsComObject(value)) {
+ BindingRestrictions remotedRestriction;
+ if (RemotingServices.IsObjectOutOfAppDomain(value)) {
+ remotedRestriction = BindingRestrictions.GetExpressionRestriction(
+ Expression.AndAlso(
+ Expression.NotEqual(expr, Expression.Constant(null)),
+ Expression.Call(
+ typeof(RemotingServices).GetMethod("IsObjectOutOfAppDomain"),
+ expr
+ )
+ )
+ );
+ } else {
+ remotedRestriction = BindingRestrictions.GetExpressionRestriction(
+ Expression.AndAlso(
+ Expression.NotEqual(expr, Expression.Constant(null)),
+ Expression.Not(
+ Expression.Call(
+ typeof(RemotingServices).GetMethod("IsObjectOutOfAppDomain"),
+ expr
+ )
+ )
+ )
+ );
+ }
+ restrictions = restrictions.Merge(remotedRestriction);
+ }
+ }
+
+#endif
+ return restrictions;
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic operation.</param>
+ /// <param name="args">An array of arguments of the dynamic operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args);
+
+ /// <summary>
+ /// Gets an expression that will cause the binding to be updated. It
+ /// indicates that the expression's binding is no longer valid.
+ /// This is typically used when the "version" of a dynamic object has
+ /// changed.
+ /// </summary>
+ /// <param name="type">The <see cref="Expression.Type">Type</see> property of the resulting expression; any type is allowed.</param>
+ /// <returns>The update expression.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ public Expression GetUpdateExpression(Type type) {
+ return Expression.Goto(CallSiteBinder.UpdateLabel, type);
+ }
+
+ /// <summary>
+ /// Defers the binding of the operation until later time when the runtime values of all dynamic operation arguments have been computed.
+ /// </summary>
+ /// <param name="target">The target of the dynamic operation.</param>
+ /// <param name="args">An array of arguments of the dynamic operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject Defer(DynamicMetaObject target, params DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+
+ if (args == null) {
+ return MakeDeferred(target.Restrictions, target);
+ } else {
+ return MakeDeferred(
+ target.Restrictions.Merge(BindingRestrictions.Combine(args)),
+ args.AddFirst(target)
+ );
+ }
+ }
+
+ /// <summary>
+ /// Defers the binding of the operation until later time when the runtime values of all dynamic operation arguments have been computed.
+ /// </summary>
+ /// <param name="args">An array of arguments of the dynamic operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject Defer(params DynamicMetaObject[] args) {
+ return MakeDeferred(BindingRestrictions.Combine(args), args);
+ }
+
+ private DynamicMetaObject MakeDeferred(BindingRestrictions rs, params DynamicMetaObject[] args) {
+ var exprs = DynamicMetaObject.GetExpressions(args);
+
+ Type delegateType = DelegateHelpers.MakeDeferredSiteDelegate(args, ReturnType);
+
+ // Because we know the arguments match the delegate type (we just created the argument types)
+ // we go directly to DynamicExpression.Make to avoid a bunch of unnecessary argument validation
+ return new DynamicMetaObject(
+ DynamicExpression.Make(ReturnType, delegateType, this, new TrueReadOnlyCollection<Expression>(exprs)),
+ rs
+ );
+ }
+
+ #endregion
+
+ // used to detect standard MetaObjectBinders.
+ internal virtual bool IsStandardBinder {
+ get {
+ return false;
+ }
+ }
+
+#if !SILVERLIGHT
+ private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
+ private static bool IsComObject(object obj) {
+ // we can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust
+ return obj != null && ComObjectType.IsAssignableFrom(obj.GetType());
+ }
+#endif
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs
new file mode 100644
index 00000000000..30931a0429b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/DynamicObject.cs
@@ -0,0 +1,634 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Provides a simple class that can be inherited from to create an object with dynamic behavior
+ /// at runtime. Subclasses can override the various binder methods (GetMember, SetMember, Call, etc...)
+ /// to provide custom behavior that will be invoked at runtime.
+ ///
+ /// If a method is not overridden then the DynamicObject does not directly support that behavior and
+ /// the call site will determine how the binding should be performed.
+ /// </summary>
+ public class DynamicObject : IDynamicMetaObjectProvider {
+
+ /// <summary>
+ /// Enables derived types to create a new instance of DynamicObject. DynamicObject instances cannot be
+ /// directly instantiated because they have no implementation of dynamic behavior.
+ /// </summary>
+ protected DynamicObject() {
+ }
+
+ #region Public Virtual APIs
+
+ /// <summary>
+ /// Provides the implementation of getting a member. Derived classes can override
+ /// this method to customize behavior. When not overridden the call site requesting the
+ /// binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="result">The result of the get operation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryGetMember(GetMemberBinder binder, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of setting a member. Derived classes can override
+ /// this method to customize behavior. When not overridden the call site requesting the
+ /// binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="value">The value to set.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ public virtual bool TrySetMember(SetMemberBinder binder, object value) {
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of deleting a member. Derived classes can override
+ /// this method to customize behavior. When not overridden the call site requesting the
+ /// binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ public virtual bool TryDeleteMember(DeleteMemberBinder binder) {
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of calling a member. Derived classes can override
+ /// this method to customize behavior. When not overridden the call site requesting the
+ /// binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="args">The arguments to be used for the invocation.</param>
+ /// <param name="result">The result of the invocation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of converting the DynamicObject to another type. Derived classes
+ /// can override this method to customize behavior. When not overridden the call site
+ /// requesting the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="result">The result of the conversion.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryConvert(ConvertBinder binder, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of creating an instance of the DynamicObject. Derived classes
+ /// can override this method to customize behavior. When not overridden the call site requesting
+ /// the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="args">The arguments used for creation.</param>
+ /// <param name="result">The created instance.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of invoking the DynamicObject. Derived classes can
+ /// override this method to customize behavior. When not overridden the call site requesting
+ /// the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="args">The arguments to be used for the invocation.</param>
+ /// <param name="result">The result of the invocation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryInvoke(InvokeBinder binder, object[] args, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of performing a binary operation. Derived classes can
+ /// override this method to customize behavior. When not overridden the call site requesting
+ /// the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="arg">The right operand for the operation.</param>
+ /// <param name="result">The result of the operation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of performing a unary operation. Derived classes can
+ /// override this method to customize behavior. When not overridden the call site requesting
+ /// the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="result">The result of the operation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryUnaryOperation(UnaryOperationBinder binder, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of performing a get index operation. Derived classes can
+ /// override this method to customize behavior. When not overridden the call site requesting
+ /// the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="indexes">The indexes to be used.</param>
+ /// <param name="result">The result of the operation.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
+ result = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of performing a set index operation. Derived classes can
+ /// override this method to custmize behavior. When not overridden the call site requesting
+ /// the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="indexes">The indexes to be used.</param>
+ /// <param name="value">The value to set.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate")]
+ public virtual bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) {
+ return false;
+ }
+
+ /// <summary>
+ /// Provides the implementation of performing a delete index operation. Derived classes
+ /// can override this method to custmize behavior. When not overridden the call site
+ /// requesting the binder determines the behavior.
+ /// </summary>
+ /// <param name="binder">The binder provided by the call site.</param>
+ /// <param name="indexes">The indexes to be deleted.</param>
+ /// <returns>true if the operation is complete, false if the call site should determine behavior.</returns>
+ public virtual bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes) {
+ return false;
+ }
+
+ /// <summary>
+ /// Returns the enumeration of all dynamic member names.
+ /// </summary>
+ /// <returns>The list of dynamic member names.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ public virtual System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames() {
+ return new string[0];
+ }
+ #endregion
+
+ #region MetaDynamic
+
+ private sealed class MetaDynamic : DynamicMetaObject {
+
+ internal MetaDynamic(Expression expression, DynamicObject value)
+ : base(expression, BindingRestrictions.Empty, value) {
+ }
+
+ public override System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
+ {
+ return Value.GetDynamicMemberNames();
+ }
+
+ public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
+ if (IsOverridden("TryGetMember")) {
+ return CallMethodWithResult("TryGetMember", binder, NoArgs, (e) => binder.FallbackGetMember(this, e));
+ }
+
+ return base.BindGetMember(binder);
+ }
+
+ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
+ if (IsOverridden("TrySetMember")) {
+ return CallMethodReturnLast("TrySetMember", binder, GetArgs(value), (e) => binder.FallbackSetMember(this, value, e));
+ }
+
+ return base.BindSetMember(binder, value);
+ }
+
+ public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) {
+ if (IsOverridden("TryDeleteMember")) {
+ return CallMethodNoResult("TryDeleteMember", binder, NoArgs, (e) => binder.FallbackDeleteMember(this, e));
+ }
+
+ return base.BindDeleteMember(binder);
+ }
+
+ public override DynamicMetaObject BindConvert(ConvertBinder binder) {
+ if (IsOverridden("TryConvert")) {
+ return CallMethodWithResult("TryConvert", binder, NoArgs, (e) => binder.FallbackConvert(this, e));
+ }
+
+ return base.BindConvert(binder);
+ }
+
+ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
+ if (IsOverridden("TryInvokeMember")) {
+ return CallMethodWithResult("TryInvokeMember", binder, GetArgArray(args), (e) => binder.FallbackInvokeMember(this, args, e));
+ } else if (IsOverridden("TryGetMember")) {
+ // Generate a tree like:
+ //
+ // {
+ // object result;
+ // TryGetMember(payload, out result) ? FallbackInvoke(result) : fallbackResult
+ // }
+ //
+ // Then it calls FallbackInvokeMember with this tree as the
+ // "error", giving the language the option of using this
+ // tree or doing .NET binding.
+ //
+ return CallMethodWithResult(
+ "TryGetMember", new GetBinderAdapter(binder), NoArgs,
+ (e) => binder.FallbackInvokeMember(this, args, e),
+ (e) => binder.FallbackInvoke(e, args, null)
+ );
+ }
+
+ return base.BindInvokeMember(binder, args);
+ }
+
+
+ public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) {
+ if (IsOverridden("TryCreateInstance")) {
+ return CallMethodWithResult("TryCreateInstance", binder, GetArgArray(args), (e) => binder.FallbackCreateInstance(this, args, e));
+ }
+
+ return base.BindCreateInstance(binder, args);
+ }
+
+ public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) {
+ if (IsOverridden("TryInvoke")) {
+ return CallMethodWithResult("TryInvoke", binder, GetArgArray(args), (e) => binder.FallbackInvoke(this, args, e));
+ }
+
+ return base.BindInvoke(binder, args);
+ }
+
+ public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) {
+ if (IsOverridden("TryBinaryOperation")) {
+ return CallMethodWithResult("TryBinaryOperation", binder, GetArgs(arg), (e) => binder.FallbackBinaryOperation(this, arg, e));
+ }
+
+ return base.BindBinaryOperation(binder, arg);
+ }
+
+ public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) {
+ if (IsOverridden("TryUnaryOperation")) {
+ return CallMethodWithResult("TryUnaryOperation", binder, NoArgs, (e) => binder.FallbackUnaryOperation(this, e));
+ }
+
+ return base.BindUnaryOperation(binder);
+ }
+
+ public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) {
+ if (IsOverridden("TryGetIndex")) {
+ return CallMethodWithResult("TryGetIndex", binder, GetArgArray(indexes), (e) => binder.FallbackGetIndex(this, indexes, e));
+ }
+
+ return base.BindGetIndex(binder, indexes);
+ }
+
+ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ if (IsOverridden("TrySetIndex")) {
+ return CallMethodReturnLast("TrySetIndex", binder, GetArgArray(indexes, value), (e) => binder.FallbackSetIndex(this, indexes, value, e));
+ }
+
+ return base.BindSetIndex(binder, indexes, value);
+ }
+
+ public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) {
+ if (IsOverridden("TryDeleteIndex")) {
+ return CallMethodNoResult("TryDeleteIndex", binder, GetArgArray(indexes), (e) => binder.FallbackDeleteIndex(this, indexes, e));
+ }
+
+ return base.BindDeleteIndex(binder, indexes);
+ }
+
+ private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
+
+ private readonly static Expression[] NoArgs = new Expression[0];
+
+ private static Expression[] GetArgs(params DynamicMetaObject[] args) {
+ Expression[] paramArgs = DynamicMetaObject.GetExpressions(args);
+
+ for (int i = 0; i < paramArgs.Length; i++) {
+ paramArgs[i] = Expression.Convert(args[i].Expression, typeof(object));
+ }
+
+ return paramArgs;
+ }
+
+ private static Expression[] GetArgArray(DynamicMetaObject[] args) {
+ return new[] { Expression.NewArrayInit(typeof(object), GetArgs(args)) };
+ }
+
+ private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value) {
+ return new Expression[] {
+ Expression.NewArrayInit(typeof(object), GetArgs(args)),
+ Expression.Convert(value.Expression, typeof(object))
+ };
+ }
+
+ private static ConstantExpression Constant(DynamicMetaObjectBinder binder) {
+ Type t = binder.GetType();
+ while (!t.IsVisible) {
+ t = t.BaseType;
+ }
+ return Expression.Constant(binder, t);
+ }
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic that returns a result
+ /// </summary>
+ private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) {
+ return CallMethodWithResult(methodName, binder, args, fallback, null);
+ }
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic that returns a result
+ /// </summary>
+ private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke) {
+ //
+ // First, call fallback to do default binding
+ // This produces either an error or a call to a .NET member
+ //
+ DynamicMetaObject fallbackResult = fallback(null);
+
+ //
+ // Build a new expression like:
+ // {
+ // object result;
+ // TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
+ // }
+ //
+ var result = Expression.Parameter(typeof(object), null);
+
+ var callArgs = new Expression[args.Length + 2];
+ Array.Copy(args, 0, callArgs, 1, args.Length);
+ callArgs[0] = Constant(binder);
+ callArgs[callArgs.Length - 1] = result;
+
+ var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);
+
+ // Need to add a conversion if calling TryConvert
+ if (binder.ReturnType != typeof(object)) {
+ Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);
+
+ var convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
+ // will always be a cast or unbox
+ Debug.Assert(convert.Method == null);
+
+ resultMO = new DynamicMetaObject(convert, resultMO.Restrictions);
+ }
+
+ if (fallbackInvoke != null) {
+ resultMO = fallbackInvoke(resultMO);
+ }
+
+ var callDynamic = new DynamicMetaObject(
+ Expression.Block(
+ new[] { result },
+ Expression.Condition(
+ Expression.Call(
+ GetLimitedSelf(),
+ typeof(DynamicObject).GetMethod(methodName),
+ callArgs
+ ),
+ resultMO.Expression,
+ fallbackResult.Expression,
+ binder.ReturnType
+ )
+ ),
+ GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
+ );
+
+ //
+ // Now, call fallback again using our new MO as the error
+ // When we do this, one of two things can happen:
+ // 1. Binding will succeed, and it will ignore our call to
+ // the dynamic method, OR
+ // 2. Binding will fail, and it will use the MO we created
+ // above.
+ //
+ return fallback(callDynamic);
+ }
+
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic, but uses one of the arguments for
+ /// the result.
+ /// </summary>
+ private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) {
+ //
+ // First, call fallback to do default binding
+ // This produces either an error or a call to a .NET member
+ //
+ DynamicMetaObject fallbackResult = fallback(null);
+
+ //
+ // Build a new expression like:
+ // {
+ // object result;
+ // TrySetMember(payload, result = value) ? result : fallbackResult
+ // }
+ //
+
+ var result = Expression.Parameter(typeof(object), null);
+ var callArgs = args.AddFirst(Constant(binder));
+ callArgs[args.Length] = Expression.Assign(result, callArgs[args.Length]);
+
+ var callDynamic = new DynamicMetaObject(
+ Expression.Block(
+ new[] { result },
+ Expression.Condition(
+ Expression.Call(
+ GetLimitedSelf(),
+ typeof(DynamicObject).GetMethod(methodName),
+ callArgs
+ ),
+ result,
+ fallbackResult.Expression,
+ typeof(object)
+ )
+ ),
+ GetRestrictions().Merge(fallbackResult.Restrictions)
+ );
+
+ //
+ // Now, call fallback again using our new MO as the error
+ // When we do this, one of two things can happen:
+ // 1. Binding will succeed, and it will ignore our call to
+ // the dynamic method, OR
+ // 2. Binding will fail, and it will use the MO we created
+ // above.
+ //
+ return fallback(callDynamic);
+ }
+
+
+ /// <summary>
+ /// Helper method for generating a MetaObject which calls a
+ /// specific method on Dynamic, but uses one of the arguments for
+ /// the result.
+ /// </summary>
+ private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) {
+ //
+ // First, call fallback to do default binding
+ // This produces either an error or a call to a .NET member
+ //
+ DynamicMetaObject fallbackResult = fallback(null);
+
+ //
+ // Build a new expression like:
+ // if (TryDeleteMember(payload)) { } else { fallbackResult }
+ //
+ var callDynamic = new DynamicMetaObject(
+ Expression.Condition(
+ Expression.Call(
+ GetLimitedSelf(),
+ typeof(DynamicObject).GetMethod(methodName),
+ args.AddFirst(Constant(binder))
+ ),
+ Expression.Empty(),
+ fallbackResult.Expression,
+ typeof(void)
+ ),
+ GetRestrictions().Merge(fallbackResult.Restrictions)
+ );
+
+ //
+ // Now, call fallback again using our new MO as the error
+ // When we do this, one of two things can happen:
+ // 1. Binding will succeed, and it will ignore our call to
+ // the dynamic method, OR
+ // 2. Binding will fail, and it will use the MO we created
+ // above.
+ //
+ return fallback(callDynamic);
+ }
+
+ /// <summary>
+ /// Checks if the derived type has overridden the specified method. If there is no
+ /// implementation for the method provided then Dynamic falls back to the base class
+ /// behavior which lets the call site determine how the binder is performed.
+ /// </summary>
+ private bool IsOverridden(string method) {
+ var methods = Value.GetType().GetMember(method, MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance);
+
+ foreach (MethodInfo mi in methods) {
+ if (mi.DeclaringType != typeof(DynamicObject) && mi.GetBaseDefinition().DeclaringType == typeof(DynamicObject)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns a Restrictions object which includes our current restrictions merged
+ /// with a restriction limiting our type
+ /// </summary>
+ private BindingRestrictions GetRestrictions() {
+ Debug.Assert(Restrictions == BindingRestrictions.Empty, "We don't merge, restrictions are always empty");
+
+ return BindingRestrictions.GetTypeRestriction(this);
+ }
+
+ /// <summary>
+ /// Returns our Expression converted to our known LimitType
+ /// </summary>
+ private Expression GetLimitedSelf() {
+ if (TypeUtils.AreEquivalent(Expression.Type, LimitType)) {
+ return Expression;
+ }
+ return Expression.Convert(Expression, LimitType);
+ }
+
+ private new DynamicObject Value {
+ get {
+ return (DynamicObject)base.Value;
+ }
+ }
+
+ // It is okay to throw NotSupported from this binder. This object
+ // is only used by DynamicObject.GetMember--it is not expected to
+ // (and cannot) implement binding semantics. It is just so the DO
+ // can use the Name and IgnoreCase properties.
+ private sealed class GetBinderAdapter : GetMemberBinder {
+ internal GetBinderAdapter(InvokeMemberBinder binder)
+ : base(binder.Name, binder.IgnoreCase) {
+ }
+
+ public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) {
+ throw new NotSupportedException();
+ }
+ }
+ }
+
+ #endregion
+
+ #region IDynamicMetaObjectProvider Members
+
+ /// <summary>
+ /// The provided MetaObject will dispatch to the Dynamic virtual methods.
+ /// The object can be encapsulated inside of another MetaObject to
+ /// provide custom behavior for individual actions.
+ /// </summary>
+ public virtual DynamicMetaObject GetMetaObject(Expression parameter) {
+ return new MetaDynamic(parameter, this);
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoClass.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoClass.cs
new file mode 100644
index 00000000000..db41d72827b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoClass.cs
@@ -0,0 +1,197 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Scripting.Utils;
+#endif
+using System.Text;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents a dynamically assigned class. Expando objects which share the same
+ /// members will share the same class. Classes are dynamically assigned as the
+ /// expando object gains members.
+ /// </summary>
+ internal class ExpandoClass {
+ private readonly string[] _keys; // list of names associated with each element in the data array, sorted
+ private readonly int _hashCode; // pre-calculated hash code of all the keys the class contains
+ private Dictionary<int, List<WeakReference>> _transitions; // cached transitions
+
+ private const int EmptyHashCode = 6551; // hash code of the empty ExpandoClass.
+
+ internal static ExpandoClass Empty = new ExpandoClass(); // The empty Expando class - all Expando objects start off w/ this class.
+
+ /// <summary>
+ /// Constructs the empty ExpandoClass. This is the class used when an
+ /// empty Expando object is initially constructed.
+ /// </summary>
+ internal ExpandoClass() {
+ _hashCode = EmptyHashCode;
+ _keys = new string[0];
+ }
+
+ /// <summary>
+ /// Constructs a new ExpandoClass that can hold onto the specified keys. The
+ /// keys must be sorted ordinally. The hash code must be precalculated for
+ /// the keys.
+ /// </summary>
+ internal ExpandoClass(string[] keys, int hashCode) {
+ _hashCode = hashCode;
+ _keys = keys;
+ }
+
+ /// <summary>
+ /// Finds or creates a new ExpandoClass given the existing set of keys
+ /// in this ExpandoClass plus the new key to be added. Members in an
+ /// ExpandoClass are always stored case sensitively.
+ /// </summary>
+ internal ExpandoClass FindNewClass(string newKey) {
+ // just XOR the newKey hash code
+ int hashCode = _hashCode ^ newKey.GetHashCode();
+
+ lock (this) {
+ List<WeakReference> infos = GetTransitionList(hashCode);
+
+ for (int i = 0; i < infos.Count; i++) {
+ ExpandoClass klass = infos[i].Target as ExpandoClass;
+ if (klass == null) {
+ infos.RemoveAt(i);
+ i--;
+ continue;
+ }
+
+ if (string.Equals(klass._keys[klass._keys.Length - 1], newKey, StringComparison.Ordinal)) {
+ // the new key is the key we added in this transition
+ return klass;
+ }
+ }
+
+ // no applicable transition, create a new one
+ string[] keys = new string[_keys.Length + 1];
+ Array.Copy(_keys, keys, _keys.Length);
+ keys[_keys.Length] = newKey;
+ ExpandoClass ec = new ExpandoClass(keys, hashCode);
+
+ infos.Add(new WeakReference(ec));
+ return ec;
+ }
+ }
+
+ /// <summary>
+ /// Gets the lists of transitions that are valid from this ExpandoClass
+ /// to an ExpandoClass whos keys hash to the apporopriate hash code.
+ /// </summary>
+ private List<WeakReference> GetTransitionList(int hashCode) {
+ if (_transitions == null) {
+ _transitions = new Dictionary<int, List<WeakReference>>();
+ }
+
+ List<WeakReference> infos;
+ if (!_transitions.TryGetValue(hashCode, out infos)) {
+ _transitions[hashCode] = infos = new List<WeakReference>();
+ }
+
+ return infos;
+ }
+
+ /// <summary>
+ /// Gets the index at which the value should be stored for the specified name.
+ /// </summary>
+ internal int GetValueIndex(string name, bool caseInsensitive, ExpandoObject obj) {
+ if (caseInsensitive) {
+ return GetValueIndexCaseInsensitive(name, obj);
+ } else {
+ return GetValueIndexCaseSensitive(name);
+ }
+ }
+
+ /// <summary>
+ /// Gets the index at which the value should be stored for the specified name
+ /// case sensitively. Returns the index even if the member is marked as deleted.
+ /// </summary>
+ internal int GetValueIndexCaseSensitive(string name) {
+ for (int i = 0; i < _keys.Length; i++) {
+ if (string.Equals(
+ _keys[i],
+ name,
+ StringComparison.Ordinal)) {
+ return i;
+ }
+ }
+ return ExpandoObject.NoMatch;
+ }
+
+ /// <summary>
+ /// Gets the index at which the value should be stored for the specified name,
+ /// the method is only used in the case-insensitive case.
+ /// </summary>
+ /// <param name="name">the name of the member</param>
+ /// <param name="obj">The ExpandoObject associated with the class
+ /// that is used to check if a member has been deleted.</param>
+ /// <returns>
+ /// the exact match if there is one
+ /// if there is exactly one member with case insensitive match, return it
+ /// otherwise we throw AmbiguousMatchException.
+ /// </returns>
+ private int GetValueIndexCaseInsensitive(string name, ExpandoObject obj) {
+ int caseInsensitiveMatch = ExpandoObject.NoMatch; //the location of the case-insensitive matching member
+ lock (obj.LockObject) {
+ for (int i = _keys.Length - 1; i >= 0; i--) {
+ if (string.Equals(
+ _keys[i],
+ name,
+ StringComparison.OrdinalIgnoreCase)) {
+ //if the matching member is deleted, continue searching
+ if (!obj.IsDeletedMember(i)) {
+ if (caseInsensitiveMatch == ExpandoObject.NoMatch) {
+ caseInsensitiveMatch = i;
+ } else {
+ //Ambigous match, stop searching
+ return ExpandoObject.AmbiguousMatchFound;
+ }
+ }
+ }
+ }
+ }
+ //There is exactly one member with case insensitive match.
+ return caseInsensitiveMatch;
+ }
+
+ /// <summary>
+ /// Gets the names of the keys that can be stored in the Expando class. The
+ /// list is sorted ordinally.
+ /// </summary>
+ internal string[] Keys {
+ get {
+ return _keys;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoObject.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoObject.cs
new file mode 100644
index 00000000000..8222ed322d1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/ExpandoObject.cs
@@ -0,0 +1,1108 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents an object with members that can be dynamically added and removed at runtime.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
+ public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary<string, object>, INotifyPropertyChanged {
+ internal readonly object LockObject; // the readonly field is used for locking the Expando object
+ private ExpandoData _data; // the data currently being held by the Expando object
+ private int _count; // the count of available members
+
+ internal readonly static object Uninitialized = new object(); // A marker object used to identify that a value is uninitialized.
+
+ internal const int AmbiguousMatchFound = -2; // The value is used to indicate there exists ambiguous match in the Expando object
+ internal const int NoMatch = -1; // The value is used to indicate there is no matching member
+
+ private PropertyChangedEventHandler _propertyChanged;
+
+ /// <summary>
+ /// Creates a new ExpandoObject with no members.
+ /// </summary>
+ public ExpandoObject() {
+ _data = ExpandoData.Empty;
+ LockObject = new object();
+ }
+
+ #region Get/Set/Delete Helpers
+
+ /// <summary>
+ /// Try to get the data stored for the specified class at the specified index. If the
+ /// class has changed a full lookup for the slot will be performed and the correct
+ /// value will be retrieved.
+ /// </summary>
+ internal bool TryGetValue(object indexClass, int index, string name, bool ignoreCase, out object value) {
+ // read the data now. The data is immutable so we get a consistent view.
+ // If there's a concurrent writer they will replace data and it just appears
+ // that we won the race
+ ExpandoData data = _data;
+ if (data.Class != indexClass || ignoreCase) {
+ /* Re-search for the index matching the name here if
+ * 1) the class has changed, we need to get the correct index and return
+ * the value there.
+ * 2) the search is case insensitive:
+ * a. the member specified by index may be deleted, but there might be other
+ * members matching the name if the binder is case insensitive.
+ * b. the member that exactly matches the name didn't exist before and exists now,
+ * need to find the exact match.
+ */
+ index = data.Class.GetValueIndex(name, ignoreCase, this);
+ if (index == ExpandoObject.AmbiguousMatchFound) {
+ throw Error.AmbiguousMatchInExpandoObject(name);
+ }
+ }
+
+ if (index == ExpandoObject.NoMatch) {
+ value = null;
+ return false;
+ }
+
+ // Capture the value into a temp, so it doesn't get mutated after we check
+ // for Uninitialized.
+ object temp = data[index];
+ if (temp == Uninitialized) {
+ value = null;
+ return false;
+ }
+
+ // index is now known to be correct
+ value = temp;
+ return true;
+ }
+
+ /// <summary>
+ /// Sets the data for the specified class at the specified index. If the class has
+ /// changed then a full look for the slot will be performed. If the new class does
+ /// not have the provided slot then the Expando's class will change. Only case sensitive
+ /// setter is supported in ExpandoObject.
+ /// </summary>
+ internal void TrySetValue(object indexClass, int index, object value, string name, bool ignoreCase, bool add) {
+ ExpandoData data;
+ object oldValue;
+
+ lock (LockObject) {
+ data = _data;
+
+ if (data.Class != indexClass || ignoreCase) {
+ // The class has changed or we are doing a case-insensitive search,
+ // we need to get the correct index and set the value there. If we
+ // don't have the value then we need to promote the class - that
+ // should only happen when we have multiple concurrent writers.
+ index = data.Class.GetValueIndex(name, ignoreCase, this);
+ if (index == ExpandoObject.AmbiguousMatchFound) {
+ throw Error.AmbiguousMatchInExpandoObject(name);
+ }
+ if (index == ExpandoObject.NoMatch) {
+ // Before creating a new class with the new member, need to check
+ // if there is the exact same member but is deleted. We should reuse
+ // the class if there is such a member.
+ int exactMatch = ignoreCase ?
+ data.Class.GetValueIndexCaseSensitive(name) :
+ index;
+ if (exactMatch != ExpandoObject.NoMatch) {
+ Debug.Assert(data[exactMatch] == Uninitialized);
+ index = exactMatch;
+ } else {
+ ExpandoClass newClass = data.Class.FindNewClass(name);
+ data = PromoteClassCore(data.Class, newClass);
+ // After the class promotion, there must be an exact match,
+ // so we can do case-sensitive search here.
+ index = data.Class.GetValueIndexCaseSensitive(name);
+ Debug.Assert(index != ExpandoObject.NoMatch);
+ }
+ }
+ }
+
+ // Setting an uninitialized member increases the count of available members
+ oldValue = data[index];
+ if (oldValue == Uninitialized) {
+ _count++;
+ } else if (add) {
+ throw Error.SameKeyExistsInExpando(name);
+ }
+
+ data[index] = value;
+ }
+
+ // Notify property changed, outside of the lock.
+ var propertyChanged = _propertyChanged;
+ if (propertyChanged != null && value != oldValue) {
+ // Use the canonical case for the key.
+ propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[index]));
+ }
+ }
+
+ /// <summary>
+ /// Deletes the data stored for the specified class at the specified index.
+ /// </summary>
+ internal bool TryDeleteValue(object indexClass, int index, string name, bool ignoreCase, object deleteValue) {
+ ExpandoData data;
+ lock (LockObject) {
+ data = _data;
+
+ if (data.Class != indexClass || ignoreCase) {
+ // the class has changed or we are doing a case-insensitive search,
+ // we need to get the correct index. If there is no associated index
+ // we simply can't have the value and we return false.
+ index = data.Class.GetValueIndex(name, ignoreCase, this);
+ if (index == ExpandoObject.AmbiguousMatchFound) {
+ throw Error.AmbiguousMatchInExpandoObject(name);
+ }
+ }
+ if (index == ExpandoObject.NoMatch) {
+ return false;
+ }
+
+ object oldValue = data[index];
+ if (oldValue == Uninitialized) {
+ return false;
+ }
+
+ // Make sure the value matches, if requested.
+ //
+ // It's a shame we have to call Equals with the lock held but
+ // there doesn't seem to be a good way around that, and
+ // ConcurrentDictionary in mscorlib does the same thing.
+ if (deleteValue != Uninitialized && !object.Equals(oldValue, deleteValue)) {
+ return false;
+ }
+
+ data[index] = Uninitialized;
+
+ // Deleting an available member decreases the count of available members
+ _count--;
+ }
+
+ // Notify property changed, outside of the lock.
+ var propertyChanged = _propertyChanged;
+ if (propertyChanged != null) {
+ // Use the canonical case for the key.
+ propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[index]));
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true if the member at the specified index has been deleted,
+ /// otherwise false. Call this function holding the lock.
+ /// </summary>
+ internal bool IsDeletedMember(int index) {
+ Debug.Assert(index >= 0 && index <= _data.Length);
+
+ if (index == _data.Length) {
+ // The member is a newly added by SetMemberBinder and not in data yet
+ return false;
+ }
+
+ return _data[index] == ExpandoObject.Uninitialized;
+ }
+
+ /// <summary>
+ /// Exposes the ExpandoClass which we've associated with this
+ /// Expando object. Used for type checks in rules.
+ /// </summary>
+ internal ExpandoClass Class {
+ get {
+ return _data.Class;
+ }
+ }
+
+ /// <summary>
+ /// Promotes the class from the old type to the new type and returns the new
+ /// ExpandoData object.
+ /// </summary>
+ private ExpandoData PromoteClassCore(ExpandoClass oldClass, ExpandoClass newClass) {
+ Debug.Assert(oldClass != newClass);
+
+ lock (LockObject) {
+ if (_data.Class == oldClass) {
+ _data = _data.UpdateClass(newClass);
+ }
+ return _data;
+ }
+ }
+
+ /// <summary>
+ /// Internal helper to promote a class. Called from our RuntimeOps helper. This
+ /// version simply doesn't expose the ExpandoData object which is a private
+ /// data structure.
+ /// </summary>
+ internal void PromoteClass(object oldClass, object newClass) {
+ PromoteClassCore((ExpandoClass)oldClass, (ExpandoClass)newClass);
+ }
+
+ #endregion
+
+ #region IDynamicMetaObjectProvider Members
+
+ DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
+ return new MetaExpando(parameter, this);
+ }
+ #endregion
+
+ #region Helper methods
+ private void TryAddMember(string key, object value) {
+ ContractUtils.RequiresNotNull(key, "key");
+ // Pass null to the class, which forces lookup.
+ TrySetValue(null, -1, value, key, false, true);
+ }
+
+ private bool TryGetValueForKey(string key, out object value) {
+ // Pass null to the class, which forces lookup.
+ return TryGetValue(null, -1, key, false, out value);
+ }
+
+ private bool ExpandoContainsKey(string key) {
+ return _data.Class.GetValueIndexCaseSensitive(key) >= 0;
+ }
+
+ // We create a non-generic type for the debug view for each different collection type
+ // that uses DebuggerTypeProxy, instead of defining a generic debug view type and
+ // using different instantiations. The reason for this is that support for generics
+ // with using DebuggerTypeProxy is limited. For C#, DebuggerTypeProxy supports only
+ // open types (from MSDN http://msdn.microsoft.com/en-us/library/d8eyd8zc.aspx).
+ private sealed class KeyCollectionDebugView {
+ private ICollection<string> collection;
+ public KeyCollectionDebugView(ICollection<string> collection) {
+ Debug.Assert(collection != null);
+ this.collection = collection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public string[] Items {
+ get {
+ string[] items = new string[collection.Count];
+ collection.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+
+ [DebuggerTypeProxy(typeof(KeyCollectionDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+ private class KeyCollection : ICollection<string> {
+ private readonly ExpandoObject _expando;
+ private readonly int _expandoVersion;
+ private readonly int _expandoCount;
+ private readonly ExpandoData _expandoData;
+
+ internal KeyCollection(ExpandoObject expando) {
+ lock (expando.LockObject) {
+ _expando = expando;
+ _expandoVersion = expando._data.Version;
+ _expandoCount = expando._count;
+ _expandoData = expando._data;
+ }
+ }
+
+ private void CheckVersion() {
+ if (_expando._data.Version != _expandoVersion || _expandoData != _expando._data) {
+ //the underlying expando object has changed
+ throw Error.CollectionModifiedWhileEnumerating();
+ }
+ }
+
+ #region ICollection<string> Members
+
+ public void Add(string item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ public void Clear() {
+ throw Error.CollectionReadOnly();
+ }
+
+ public bool Contains(string item) {
+ lock (_expando.LockObject) {
+ CheckVersion();
+ return _expando.ExpandoContainsKey(item);
+ }
+ }
+
+ public void CopyTo(string[] array, int arrayIndex) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count");
+ lock (_expando.LockObject) {
+ CheckVersion();
+ ExpandoData data = _expando._data;
+ for (int i = 0; i < data.Class.Keys.Length; i++) {
+ if (data[i] != Uninitialized) {
+ array[arrayIndex++] = data.Class.Keys[i];
+ }
+ }
+ }
+ }
+
+ public int Count {
+ get {
+ CheckVersion();
+ return _expandoCount;
+ }
+ }
+
+ public bool IsReadOnly {
+ get { return true; }
+ }
+
+ public bool Remove(string item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ #endregion
+
+ #region IEnumerable<string> Members
+
+ public IEnumerator<string> GetEnumerator() {
+ for (int i = 0, n = _expandoData.Class.Keys.Length; i < n; i++) {
+ CheckVersion();
+ if (_expandoData[i] != Uninitialized) {
+ yield return _expandoData.Class.Keys[i];
+ }
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ // We create a non-generic type for the debug view for each different collection type
+ // that uses DebuggerTypeProxy, instead of defining a generic debug view type and
+ // using different instantiations. The reason for this is that support for generics
+ // with using DebuggerTypeProxy is limited. For C#, DebuggerTypeProxy supports only
+ // open types (from MSDN http://msdn.microsoft.com/en-us/library/d8eyd8zc.aspx).
+ private sealed class ValueCollectionDebugView {
+ private ICollection<object> collection;
+ public ValueCollectionDebugView(ICollection<object> collection) {
+ Debug.Assert(collection != null);
+ this.collection = collection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public object[] Items {
+ get {
+ object[] items = new object[collection.Count];
+ collection.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+
+ [DebuggerTypeProxy(typeof(ValueCollectionDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+ private class ValueCollection : ICollection<object> {
+ private readonly ExpandoObject _expando;
+ private readonly int _expandoVersion;
+ private readonly int _expandoCount;
+ private readonly ExpandoData _expandoData;
+
+ internal ValueCollection(ExpandoObject expando) {
+ lock (expando.LockObject) {
+ _expando = expando;
+ _expandoVersion = expando._data.Version;
+ _expandoCount = expando._count;
+ _expandoData = expando._data;
+ }
+ }
+
+ private void CheckVersion() {
+ if (_expando._data.Version != _expandoVersion || _expandoData != _expando._data) {
+ //the underlying expando object has changed
+ throw Error.CollectionModifiedWhileEnumerating();
+ }
+ }
+
+ #region ICollection<string> Members
+
+ public void Add(object item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ public void Clear() {
+ throw Error.CollectionReadOnly();
+ }
+
+ public bool Contains(object item) {
+ lock (_expando.LockObject) {
+ CheckVersion();
+
+ ExpandoData data = _expando._data;
+ for (int i = 0; i < data.Class.Keys.Length; i++) {
+
+ // See comment in TryDeleteValue; it's okay to call
+ // object.Equals with the lock held.
+ if (object.Equals(data[i], item)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public void CopyTo(object[] array, int arrayIndex) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.RequiresArrayRange(array, arrayIndex, _expandoCount, "arrayIndex", "Count");
+ lock (_expando.LockObject) {
+ CheckVersion();
+ ExpandoData data = _expando._data;
+ for (int i = 0; i < data.Class.Keys.Length; i++) {
+ if (data[i] != Uninitialized) {
+ array[arrayIndex++] = data[i];
+ }
+ }
+ }
+ }
+
+ public int Count {
+ get {
+ CheckVersion();
+ return _expandoCount;
+ }
+ }
+
+ public bool IsReadOnly {
+ get { return true; }
+ }
+
+ public bool Remove(object item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ #endregion
+
+ #region IEnumerable<string> Members
+
+ public IEnumerator<object> GetEnumerator() {
+ ExpandoData data = _expando._data;
+ for (int i = 0; i < data.Class.Keys.Length; i++) {
+ CheckVersion();
+ // Capture the value into a temp so we don't inadvertently
+ // return Uninitialized.
+ object temp = data[i];
+ if (temp != Uninitialized) {
+ yield return temp;
+ }
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ #region IDictionary<string, object> Members
+ ICollection<string> IDictionary<string, object>.Keys {
+ get {
+ return new KeyCollection(this);
+ }
+ }
+
+ ICollection<object> IDictionary<string, object>.Values {
+ get {
+ return new ValueCollection(this);
+ }
+ }
+
+ object IDictionary<string, object>.this[string key] {
+ get {
+ object value;
+ if (!TryGetValueForKey(key, out value)) {
+ throw Error.KeyDoesNotExistInExpando(key);
+ }
+ return value;
+ }
+ set {
+ ContractUtils.RequiresNotNull(key, "key");
+ // Pass null to the class, which forces lookup.
+ TrySetValue(null, -1, value, key, false, false);
+ }
+ }
+
+ void IDictionary<string, object>.Add(string key, object value) {
+ this.TryAddMember(key, value);
+ }
+
+ bool IDictionary<string, object>.ContainsKey(string key) {
+ ContractUtils.RequiresNotNull(key, "key");
+
+ ExpandoData data = _data;
+ int index = data.Class.GetValueIndexCaseSensitive(key);
+ return index >= 0 && data[index] != Uninitialized;
+ }
+
+ bool IDictionary<string, object>.Remove(string key) {
+ ContractUtils.RequiresNotNull(key, "key");
+ // Pass null to the class, which forces lookup.
+ return TryDeleteValue(null, -1, key, false, Uninitialized);
+ }
+
+ bool IDictionary<string, object>.TryGetValue(string key, out object value) {
+ return TryGetValueForKey(key, out value);
+ }
+
+ #endregion
+
+ #region ICollection<KeyValuePair<string, object>> Members
+ int ICollection<KeyValuePair<string, object>>.Count {
+ get {
+ return _count;
+ }
+ }
+
+ bool ICollection<KeyValuePair<string, object>>.IsReadOnly {
+ get { return false; }
+ }
+
+ void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) {
+ TryAddMember(item.Key, item.Value);
+ }
+
+ void ICollection<KeyValuePair<string, object>>.Clear() {
+ // We remove both class and data!
+ ExpandoData data;
+ lock (LockObject) {
+ data = _data;
+ _data = ExpandoData.Empty;
+ _count = 0;
+ }
+
+ // Notify property changed for all properties.
+ var propertyChanged = _propertyChanged;
+ if (propertyChanged != null) {
+ for (int i = 0, n = data.Class.Keys.Length; i < n; i++) {
+ if (data[i] != Uninitialized) {
+ propertyChanged(this, new PropertyChangedEventArgs(data.Class.Keys[i]));
+ }
+ }
+ }
+ }
+
+ bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) {
+ object value;
+ if (!TryGetValueForKey(item.Key, out value)) {
+ return false;
+ }
+
+ return object.Equals(value, item.Value);
+ }
+
+ void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.RequiresArrayRange(array, arrayIndex, _count, "arrayIndex", "Count");
+
+ // We want this to be atomic and not throw
+ lock (LockObject) {
+ foreach (KeyValuePair<string, object> item in this) {
+ array[arrayIndex++] = item;
+ }
+ }
+ }
+
+ bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item) {
+ return TryDeleteValue(null, -1, item.Key, false, item.Value);
+ }
+ #endregion
+
+ #region IEnumerable<KeyValuePair<string, object>> Member
+
+ IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() {
+ ExpandoData data = _data;
+ return GetExpandoEnumerator(data, data.Version);
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ ExpandoData data = _data;
+ return GetExpandoEnumerator(data, data.Version);
+ }
+
+ // Note: takes the data and version as parameters so they will be
+ // captured before the first call to MoveNext().
+ private IEnumerator<KeyValuePair<string, object>> GetExpandoEnumerator(ExpandoData data, int version) {
+ for (int i = 0; i < data.Class.Keys.Length; i++) {
+ if (_data.Version != version || data != _data) {
+ // The underlying expando object has changed:
+ // 1) the version of the expando data changed
+ // 2) the data object is changed
+ throw Error.CollectionModifiedWhileEnumerating();
+ }
+ // Capture the value into a temp so we don't inadvertently
+ // return Uninitialized.
+ object temp = data[i];
+ if (temp != Uninitialized) {
+ yield return new KeyValuePair<string,object>(data.Class.Keys[i], temp);
+ }
+ }
+ }
+ #endregion
+
+ #region MetaExpando
+
+ private class MetaExpando : DynamicMetaObject {
+ public MetaExpando(Expression expression, ExpandoObject value)
+ : base(expression, BindingRestrictions.Empty, value) {
+ }
+
+ private DynamicMetaObject GetDynamicMetaObjectForMember(string name, bool ignoreCase, DynamicMetaObject fallback) {
+ ExpandoClass klass = Value.Class;
+
+ //try to find the member, including the deleted members
+ int index = klass.GetValueIndex(name, ignoreCase, Value);
+
+ ParameterExpression value = Expression.Parameter(typeof(object), "value");
+
+ Expression tryGetValue = Expression.Call(
+ typeof(RuntimeOps).GetMethod("ExpandoTryGetValue"),
+ GetLimitedSelf(),
+ Expression.Constant(klass, typeof(object)),
+ Expression.Constant(index),
+ Expression.Constant(name),
+ Expression.Constant(ignoreCase),
+ value
+ );
+
+ Expression memberValue = Expression.Block(
+ new[] { value },
+ Expression.Condition(
+ tryGetValue,
+ value,
+ fallback.Expression,
+ typeof(object)
+ )
+ );
+
+ return new DynamicMetaObject(memberValue, fallback.Restrictions);
+ }
+
+ public override DynamicMetaObject BindGetMember(GetMemberBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ DynamicMetaObject memberValue = GetDynamicMetaObjectForMember(
+ binder.Name,
+ binder.IgnoreCase,
+ binder.FallbackGetMember(this)
+ );
+
+ return AddDynamicTestAndDefer(binder, Value.Class, null, memberValue);
+ }
+
+ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ DynamicMetaObject memberValue = GetDynamicMetaObjectForMember(
+ binder.Name,
+ binder.IgnoreCase,
+ binder.FallbackInvokeMember(this, args)
+ );
+ //invoke the member value using the language's binder
+ return AddDynamicTestAndDefer(
+ binder,
+ Value.Class,
+ null,
+ binder.FallbackInvoke(memberValue, args, null)
+ );
+ }
+
+ public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(value, "value");
+
+ ExpandoClass klass;
+ int index;
+
+ ExpandoClass originalClass = GetClassEnsureIndex(binder.Name, binder.IgnoreCase, Value, out klass, out index);
+
+ return AddDynamicTestAndDefer(
+ binder,
+ klass,
+ originalClass,
+ new DynamicMetaObject(
+ Expression.Call(
+ typeof(RuntimeOps).GetMethod("ExpandoTrySetValue"),
+ GetLimitedSelf(),
+ Expression.Constant(klass, typeof(object)),
+ Expression.Constant(index),
+ Expression.Convert(value.Expression, typeof(object)),
+ Expression.Constant(binder.Name),
+ Expression.Constant(binder.IgnoreCase)
+ ),
+ BindingRestrictions.Empty
+ )
+ );
+ }
+
+ public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ int index = Value.Class.GetValueIndex(binder.Name, binder.IgnoreCase, Value);
+
+ Expression tryDelete = Expression.Call(
+ typeof(RuntimeOps).GetMethod("ExpandoTryDeleteValue"),
+ GetLimitedSelf(),
+ Expression.Constant(Value.Class, typeof(object)),
+ Expression.Constant(index),
+ Expression.Constant(binder.Name),
+ Expression.Constant(binder.IgnoreCase)
+ );
+ DynamicMetaObject fallback = binder.FallbackDeleteMember(this);
+
+ DynamicMetaObject target = new DynamicMetaObject(
+ Expression.IfThen(Expression.Not(tryDelete), fallback.Expression),
+ fallback.Restrictions
+ );
+
+ return AddDynamicTestAndDefer(binder, Value.Class, null, target);
+ }
+
+ public override IEnumerable<string> GetDynamicMemberNames() {
+ var expandoData = Value._data;
+ var klass = expandoData.Class;
+ for (int i = 0; i < klass.Keys.Length; i++) {
+ object val = expandoData[i];
+ if (val != ExpandoObject.Uninitialized) {
+ yield return klass.Keys[i];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds a dynamic test which checks if the version has changed. The test is only necessary for
+ /// performance as the methods will do the correct thing if called with an incorrect version.
+ /// </summary>
+ private DynamicMetaObject AddDynamicTestAndDefer(DynamicMetaObjectBinder binder, ExpandoClass klass, ExpandoClass originalClass, DynamicMetaObject succeeds) {
+
+ Expression ifTestSucceeds = succeeds.Expression;
+ if (originalClass != null) {
+ // we are accessing a member which has not yet been defined on this class.
+ // We force a class promotion after the type check. If the class changes the
+ // promotion will fail and the set/delete will do a full lookup using the new
+ // class to discover the name.
+ Debug.Assert(originalClass != klass);
+
+ ifTestSucceeds = Expression.Block(
+ Expression.Call(
+ null,
+ typeof(RuntimeOps).GetMethod("ExpandoPromoteClass"),
+ GetLimitedSelf(),
+ Expression.Constant(originalClass, typeof(object)),
+ Expression.Constant(klass, typeof(object))
+ ),
+ succeeds.Expression
+ );
+ }
+
+ return new DynamicMetaObject(
+ Expression.Condition(
+ Expression.Call(
+ null,
+ typeof(RuntimeOps).GetMethod("ExpandoCheckVersion"),
+ GetLimitedSelf(),
+ Expression.Constant(originalClass ?? klass, typeof(object))
+ ),
+ ifTestSucceeds,
+ binder.GetUpdateExpression(ifTestSucceeds.Type)
+ ),
+ GetRestrictions().Merge(succeeds.Restrictions)
+ );
+ }
+
+ /// <summary>
+ /// Gets the class and the index associated with the given name. Does not update the expando object. Instead
+ /// this returns both the original and desired new class. A rule is created which includes the test for the
+ /// original class, the promotion to the new class, and the set/delete based on the class post-promotion.
+ /// </summary>
+ private ExpandoClass GetClassEnsureIndex(string name, bool caseInsensitive, ExpandoObject obj, out ExpandoClass klass, out int index) {
+ ExpandoClass originalClass = Value.Class;
+
+ index = originalClass.GetValueIndex(name, caseInsensitive, obj) ;
+ if (index == ExpandoObject.AmbiguousMatchFound) {
+ klass = originalClass;
+ return null;
+ }
+ if (index == ExpandoObject.NoMatch) {
+ // go ahead and find a new class now...
+ ExpandoClass newClass = originalClass.FindNewClass(name);
+
+ klass = newClass;
+ index = newClass.GetValueIndexCaseSensitive(name);
+
+ Debug.Assert(index != ExpandoObject.NoMatch);
+ return originalClass;
+ } else {
+ klass = originalClass;
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Returns our Expression converted to our known LimitType
+ /// </summary>
+ private Expression GetLimitedSelf() {
+ if (TypeUtils.AreEquivalent(Expression.Type, LimitType)) {
+ return Expression;
+ }
+ return Expression.Convert(Expression, LimitType);
+ }
+
+ /// <summary>
+ /// Returns a Restrictions object which includes our current restrictions merged
+ /// with a restriction limiting our type
+ /// </summary>
+ private BindingRestrictions GetRestrictions() {
+ Debug.Assert(Restrictions == BindingRestrictions.Empty, "We don't merge, restrictions are always empty");
+
+ return BindingRestrictions.GetTypeRestriction(this);
+ }
+
+ public new ExpandoObject Value {
+ get {
+ return (ExpandoObject)base.Value;
+ }
+ }
+ }
+
+ #endregion
+
+ #region ExpandoData
+
+ /// <summary>
+ /// Stores the class and the data associated with the class as one atomic
+ /// pair. This enables us to do a class check in a thread safe manner w/o
+ /// requiring locks.
+ /// </summary>
+ private class ExpandoData {
+ internal static ExpandoData Empty = new ExpandoData();
+
+ /// <summary>
+ /// the dynamically assigned class associated with the Expando object
+ /// </summary>
+ internal readonly ExpandoClass Class;
+
+ /// <summary>
+ /// data stored in the expando object, key names are stored in the class.
+ ///
+ /// Expando._data must be locked when mutating the value. Otherwise a copy of it
+ /// could be made and lose values.
+ /// </summary>
+ private readonly object[] _dataArray;
+
+ /// <summary>
+ /// Indexer for getting/setting the data
+ /// </summary>
+ internal object this[int index] {
+ get {
+ return _dataArray[index];
+ }
+ set {
+ //when the array is updated, version increases, even the new value is the same
+ //as previous. Dictionary type has the same behavior.
+ _version++;
+ _dataArray[index] = value;
+ }
+ }
+
+ internal int Version {
+ get { return _version; }
+ }
+
+ internal int Length {
+ get { return _dataArray.Length; }
+ }
+
+ /// <summary>
+ /// Constructs an empty ExpandoData object with the empty class and no data.
+ /// </summary>
+ private ExpandoData() {
+ Class = ExpandoClass.Empty;
+ _dataArray = new object[0];
+ }
+
+ /// <summary>
+ /// the version of the ExpandoObject that tracks set and delete operations
+ /// </summary>
+ private int _version;
+
+ /// <summary>
+ /// Constructs a new ExpandoData object with the specified class and data.
+ /// </summary>
+ internal ExpandoData(ExpandoClass klass, object[] data, int version) {
+ Class = klass;
+ _dataArray = data;
+ _version = version;
+ }
+
+ /// <summary>
+ /// Update the associated class and increases the storage for the data array if needed.
+ /// </summary>
+ /// <returns></returns>
+ internal ExpandoData UpdateClass(ExpandoClass newClass) {
+ if (_dataArray.Length >= newClass.Keys.Length) {
+ // we have extra space in our buffer, just initialize it to Uninitialized.
+ this[newClass.Keys.Length - 1] = ExpandoObject.Uninitialized;
+ return new ExpandoData(newClass, this._dataArray, this._version);
+ } else {
+ // we've grown too much - we need a new object array
+ int oldLength = _dataArray.Length;
+ object[] arr = new object[GetAlignedSize(newClass.Keys.Length)];
+ Array.Copy(_dataArray, arr, _dataArray.Length);
+ ExpandoData newData = new ExpandoData(newClass, arr, this._version);
+ newData[oldLength] = ExpandoObject.Uninitialized;
+ return newData;
+ }
+ }
+
+ private static int GetAlignedSize(int len) {
+ // the alignment of the array for storage of values (must be a power of two)
+ const int DataArrayAlignment = 8;
+
+ // round up and then mask off lower bits
+ return (len + (DataArrayAlignment - 1)) & (~(DataArrayAlignment - 1));
+ }
+ }
+
+ #endregion
+
+ #region INotifyPropertyChanged Members
+
+ event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
+ add { _propertyChanged += value; }
+ remove { _propertyChanged -= value; }
+ }
+
+ #endregion
+ }
+}
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+
+ //
+ // Note: these helpers are kept as simple wrappers so they have a better
+ // chance of being inlined.
+ //
+ public static partial class RuntimeOps {
+
+ /// <summary>
+ /// Gets the value of an item in an expando object.
+ /// </summary>
+ /// <param name="expando">The expando object.</param>
+ /// <param name="indexClass">The class of the expando object.</param>
+ /// <param name="index">The index of the member.</param>
+ /// <param name="name">The name of the member.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ /// <param name="value">The out parameter containing the value of the member.</param>
+ /// <returns>True if the member exists in the expando object, otherwise false.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static bool ExpandoTryGetValue(ExpandoObject expando, object indexClass, int index, string name, bool ignoreCase, out object value) {
+ return expando.TryGetValue(indexClass, index, name, ignoreCase, out value);
+ }
+
+ /// <summary>
+ /// Sets the value of an item in an expando object.
+ /// </summary>
+ /// <param name="expando">The expando object.</param>
+ /// <param name="indexClass">The class of the expando object.</param>
+ /// <param name="index">The index of the member.</param>
+ /// <param name="value">The value of the member.</param>
+ /// <param name="name">The name of the member.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ /// <returns>
+ /// Returns the index for the set member.
+ /// </returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static object ExpandoTrySetValue(ExpandoObject expando, object indexClass, int index, object value, string name, bool ignoreCase) {
+ expando.TrySetValue(indexClass, index, value, name, ignoreCase, false);
+ return value;
+ }
+
+ /// <summary>
+ /// Deletes the value of an item in an expando object.
+ /// </summary>
+ /// <param name="expando">The expando object.</param>
+ /// <param name="indexClass">The class of the expando object.</param>
+ /// <param name="index">The index of the member.</param>
+ /// <param name="name">The name of the member.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ /// <returns>true if the item was successfully removed; otherwise, false.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static bool ExpandoTryDeleteValue(ExpandoObject expando, object indexClass, int index, string name, bool ignoreCase) {
+ return expando.TryDeleteValue(indexClass, index, name, ignoreCase, ExpandoObject.Uninitialized);
+ }
+
+ /// <summary>
+ /// Checks the version of the expando object.
+ /// </summary>
+ /// <param name="expando">The expando object.</param>
+ /// <param name="version">The version to check.</param>
+ /// <returns>true if the version is equal; otherwise, false.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static bool ExpandoCheckVersion(ExpandoObject expando, object version) {
+ return expando.Class == version;
+ }
+
+ /// <summary>
+ /// Promotes an expando object from one class to a new class.
+ /// </summary>
+ /// <param name="expando">The expando object.</param>
+ /// <param name="oldClass">The old class of the expando object.</param>
+ /// <param name="newClass">The new class of the expando object.</param>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static void ExpandoPromoteClass(ExpandoObject expando, object oldClass, object newClass) {
+ expando.PromoteClass(oldClass, newClass);
+ }
+ }
+}
+
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetIndexBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetIndexBinder.cs
new file mode 100644
index 00000000000..6676913d2fd
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetIndexBinder.cs
@@ -0,0 +1,98 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Represents the dynamic get index operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class GetIndexBinder : DynamicMetaObjectBinder {
+ private readonly CallInfo _callInfo;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GetIndexBinder" />.
+ /// </summary>
+ /// <param name="callInfo">The signature of the arguments at the call site.</param>
+ protected GetIndexBinder(CallInfo callInfo) {
+ ContractUtils.RequiresNotNull(callInfo, "callInfo");
+ _callInfo = callInfo;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the signature of the arguments at the call site.
+ /// </summary>
+ public CallInfo CallInfo {
+ get { return _callInfo; }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic get index operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic get index operation.</param>
+ /// <param name="args">An array of arguments of the dynamic get index operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNullItems(args, "args");
+
+ return target.BindGetIndex(this, args);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic get index operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic get index operation.</param>
+ /// <param name="indexes">The arguments of the dynamic get index operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes) {
+ return FallbackGetIndex(target, indexes, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic get index operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic get index operation.</param>
+ /// <param name="indexes">The arguments of the dynamic get index operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetMemberBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetMemberBinder.cs
new file mode 100644
index 00000000000..6fb6520c4dc
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/GetMemberBinder.cs
@@ -0,0 +1,110 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the dynamic get member operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class GetMemberBinder : DynamicMetaObjectBinder {
+ private readonly string _name;
+ private readonly bool _ignoreCase;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GetMemberBinder" />.
+ /// </summary>
+ /// <param name="name">The name of the member to get.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ protected GetMemberBinder(string name, bool ignoreCase) {
+ ContractUtils.RequiresNotNull(name, "name");
+
+ _name = name;
+ _ignoreCase = ignoreCase;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the name of the member to get.
+ /// </summary>
+ public string Name {
+ get {
+ return _name;
+ }
+ }
+
+ /// <summary>
+ /// Gets the value indicating if the string comparison should ignore the case of the member name.
+ /// </summary>
+ public bool IgnoreCase {
+ get {
+ return _ignoreCase;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic get member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic get member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackGetMember(DynamicMetaObject target) {
+ return FallbackGetMember(target, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic get member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic get member operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic get member operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic get member operation.</param>
+ /// <param name="args">An array of arguments of the dynamic get member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, params DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.Requires(args == null || args.Length == 0, "args");
+
+ return target.BindGetMember(this);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/IDynamicMetaObjectProvider.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/IDynamicMetaObjectProvider.cs
new file mode 100644
index 00000000000..276a2aedb61
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/IDynamicMetaObjectProvider.cs
@@ -0,0 +1,44 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents a dynamic object, that can have its operations bound at runtime.
+ /// </summary>
+ /// <remarks>
+ /// Objects that want to participate in the binding process should implement an IDynamicMetaObjectProvider interface,
+ /// and implement <see cref="IDynamicMetaObjectProvider.GetMetaObject" /> to return a <see cref="DynamicMetaObject" />.
+ /// </remarks>
+ public interface IDynamicMetaObjectProvider {
+ /// <summary>
+ /// Returns the <see cref="DynamicMetaObject" /> responsible for binding operations performed on this object.
+ /// </summary>
+ /// <param name="parameter">The expression tree representation of the runtime value.</param>
+ /// <returns>The <see cref="DynamicMetaObject" /> to bind this object.</returns>
+ DynamicMetaObject GetMetaObject(Expression parameter);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeBinder.cs
new file mode 100644
index 00000000000..c446ba0e1cf
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeBinder.cs
@@ -0,0 +1,98 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Represents the invoke dynamic operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class InvokeBinder : DynamicMetaObjectBinder {
+ private readonly CallInfo _callInfo;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InvokeBinder" />.
+ /// </summary>
+ /// <param name="callInfo">The signature of the arguments at the call site.</param>
+ protected InvokeBinder(CallInfo callInfo) {
+ ContractUtils.RequiresNotNull(callInfo, "callInfo");
+ _callInfo = callInfo;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the signature of the arguments at the call site.
+ /// </summary>
+ public CallInfo CallInfo {
+ get { return _callInfo; }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke operation.</param>
+ /// <param name="args">The arguments of the dynamic invoke operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args) {
+ return FallbackInvoke(target, args, null);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke operation.</param>
+ /// <param name="args">The arguments of the dynamic invoke operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke operation.</param>
+ /// <param name="args">An array of arguments of the dynamic invoke operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNullItems(args, "args");
+
+ return target.BindInvoke(this, args);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeMemberBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeMemberBinder.cs
new file mode 100644
index 00000000000..240b77a860a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/InvokeMemberBinder.cs
@@ -0,0 +1,139 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Represents the invoke member dynamic operation at the call site,
+ /// providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class InvokeMemberBinder : DynamicMetaObjectBinder {
+ private readonly string _name;
+ private readonly bool _ignoreCase;
+ private readonly CallInfo _callInfo;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InvokeMemberBinder" />.
+ /// </summary>
+ /// <param name="name">The name of the member to invoke.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ /// <param name="callInfo">The signature of the arguments at the call site.</param>
+ protected InvokeMemberBinder(string name, bool ignoreCase, CallInfo callInfo) {
+ ContractUtils.RequiresNotNull(name, "name");
+ ContractUtils.RequiresNotNull(callInfo, "callInfo");
+
+ _name = name;
+ _ignoreCase = ignoreCase;
+ _callInfo = callInfo;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the name of the member to invoke.
+ /// </summary>
+ public string Name {
+ get {
+ return _name;
+ }
+ }
+
+ /// <summary>
+ /// Gets the value indicating if the string comparison should ignore the case of the member name.
+ /// </summary>
+ public bool IgnoreCase {
+ get {
+ return _ignoreCase;
+ }
+ }
+
+ /// <summary>
+ /// Gets the signature of the arguments at the call site.
+ /// </summary>
+ public CallInfo CallInfo {
+ get { return _callInfo; }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke member operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke member operation.</param>
+ /// <param name="args">An array of arguments of the dynamic invoke member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNullItems(args, "args");
+
+ return target.BindInvokeMember(this, args);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic invoke member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke member operation.</param>
+ /// <param name="args">The arguments of the dynamic invoke member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args) {
+ return FallbackInvokeMember(target, args, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic invoke member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke member operation.</param>
+ /// <param name="args">The arguments of the dynamic invoke member operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic invoke operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic invoke operation.</param>
+ /// <param name="args">The arguments of the dynamic invoke operation.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ /// <remarks>
+ /// This method is called by the target when the target implements the invoke member operation
+ /// as a sequence of get member, and invoke, to let the <see cref="DynamicMetaObject"/>
+ /// request the binding of the invoke operation only.
+ /// </remarks>
+ public abstract DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/RuleCache.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/RuleCache.cs
new file mode 100644
index 00000000000..3e2323a85b1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/RuleCache.cs
@@ -0,0 +1,126 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.ComponentModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+ /// Represents a cache of runtime binding rules.
+ /// </summary>
+ /// <typeparam name="T">The delegate type.</typeparam>
+ [EditorBrowsable(EditorBrowsableState.Never), DebuggerStepThrough]
+ public class RuleCache<T> where T : class {
+ private T[] _rules = new T[0];
+ private readonly Object cacheLock = new Object();
+
+ private const int MaxRules = 128;
+
+ internal RuleCache() { }
+
+ internal T[] GetRules() {
+ return _rules;
+ }
+
+ // move the rule +2 up.
+ // this is called on every successful rule.
+ internal void MoveRule(T rule, int i) {
+ // limit search to MaxSearch elements.
+ // Rule should not get too far unless it has been already moved up.
+ // need a lock to make sure we are moving the right rule and not loosing any.
+ lock (cacheLock) {
+ const int MaxSearch = 8;
+ int count = _rules.Length - i;
+ if (count > MaxSearch) {
+ count = MaxSearch;
+ }
+
+ int oldIndex = -1;
+ int max = Math.Min(_rules.Length, i + count);
+ for (int index = i; index < max; index++) {
+ if (_rules[index] == rule) {
+ oldIndex = index;
+ break;
+ }
+ }
+ if (oldIndex < 0) {
+ return;
+ }
+ T oldRule = _rules[oldIndex];
+ _rules[oldIndex] = _rules[oldIndex - 1];
+ _rules[oldIndex - 1] = _rules[oldIndex - 2];
+ _rules[oldIndex - 2] = oldRule;
+ }
+ }
+
+ internal void AddRule(T newRule) {
+ // need a lock to make sure we are not loosing rules.
+ lock (cacheLock) {
+ _rules = AddOrInsert(_rules, newRule);
+ }
+ }
+
+ internal void ReplaceRule(T oldRule, T newRule) {
+ // need a lock to make sure we are replacing the right rule
+ lock (cacheLock) {
+ int i = Array.IndexOf(_rules, oldRule);
+ if (i >= 0) {
+ _rules[i] = newRule;
+ return; // DONE
+ }
+
+ // could not find it.
+ _rules = AddOrInsert(_rules, newRule);
+ }
+ }
+
+
+ // Adds to end or or inserts items at InsertPosition
+ private const int InsertPosition = MaxRules / 2;
+
+ private static T[] AddOrInsert(T[] rules, T item) {
+ if (rules.Length < InsertPosition) {
+ return rules.AddLast(item);
+ }
+
+ T[] newRules;
+
+ int newLength = rules.Length + 1;
+ if (newLength > MaxRules) {
+ newLength = MaxRules;
+ newRules = rules;
+ } else {
+ newRules = new T[newLength];
+ }
+
+ Array.Copy(rules, 0, newRules, 0, InsertPosition);
+ newRules[InsertPosition] = item;
+ Array.Copy(rules, InsertPosition, newRules, InsertPosition + 1, newLength - InsertPosition - 1);
+ return newRules;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetIndexBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetIndexBinder.cs
new file mode 100644
index 00000000000..38f15ca7b24
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetIndexBinder.cs
@@ -0,0 +1,107 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+
+ /// <summary>
+ /// Represents the dynamic set index operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class SetIndexBinder : DynamicMetaObjectBinder {
+ private readonly CallInfo _callInfo;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SetIndexBinder" />.
+ /// </summary>
+ /// <param name="callInfo">The signature of the arguments at the call site.</param>
+ protected SetIndexBinder(CallInfo callInfo) {
+ ContractUtils.RequiresNotNull(callInfo, "callInfo");
+ _callInfo = callInfo;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the signature of the arguments at the call site.
+ /// </summary>
+ public CallInfo CallInfo {
+ get { return _callInfo; }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set index operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic set index operation.</param>
+ /// <param name="args">An array of arguments of the dynamic set index operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNull(args, "args");
+ ContractUtils.Requires(args.Length >= 2, "args");
+
+ DynamicMetaObject value = args[args.Length - 1];
+ DynamicMetaObject[] indexes = args.RemoveLast();
+
+ ContractUtils.RequiresNotNull(value, "args");
+ ContractUtils.RequiresNotNullItems(indexes, "args");
+
+ return target.BindSetIndex(this, indexes, value);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set index operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic set index operation.</param>
+ /// <param name="indexes">The arguments of the dynamic set index operation.</param>
+ /// <param name="value">The value to set to the collection.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value) {
+ return FallbackSetIndex(target, indexes, value, null);
+ }
+
+ /// <summary>
+ /// When overridden in the derived class, performs the binding of the dynamic set index operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic set index operation.</param>
+ /// <param name="indexes">The arguments of the dynamic set index operation.</param>
+ /// <param name="value">The value to set to the collection.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetMemberBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetMemberBinder.cs
new file mode 100644
index 00000000000..8e6386ff552
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/SetMemberBinder.cs
@@ -0,0 +1,116 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the dynamic set member operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class SetMemberBinder : DynamicMetaObjectBinder {
+ private readonly string _name;
+ private readonly bool _ignoreCase;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SetMemberBinder" />.
+ /// </summary>
+ /// <param name="name">The name of the member to get.</param>
+ /// <param name="ignoreCase">true if the name should be matched ignoring case; false otherwise.</param>
+ protected SetMemberBinder(string name, bool ignoreCase) {
+ ContractUtils.RequiresNotNull(name, "name");
+
+ _name = name;
+ _ignoreCase = ignoreCase;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Gets the name of the member to get.
+ /// </summary>
+ public string Name {
+ get {
+ return _name;
+ }
+ }
+
+ /// <summary>
+ /// Gets the value indicating if the string comparison should ignore the case of the member name.
+ /// </summary>
+ public bool IgnoreCase {
+ get {
+ return _ignoreCase;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set member operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic set member operation.</param>
+ /// <param name="args">An array of arguments of the dynamic set member operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.RequiresNotNull(args, "args");
+ ContractUtils.Requires(args.Length == 1, "args");
+
+ var arg0 = args[0];
+ ContractUtils.RequiresNotNull(arg0, "args");
+
+ return target.BindSetMember(this, arg0);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic set member operation.</param>
+ /// <param name="value">The value to set to the member.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value) {
+ return FallbackSetMember(target, value, null);
+ }
+
+ /// <summary>
+ /// Performs the binding of the dynamic set member operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic set member operation.</param>
+ /// <param name="value">The value to set to the member.</param>
+ /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UnaryOperationBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UnaryOperationBinder.cs
new file mode 100644
index 00000000000..f5a33f6f616
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UnaryOperationBinder.cs
@@ -0,0 +1,135 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ /// <summary>
+ /// Represents the unary dynamic operation at the call site, providing the binding semantic and the details about the operation.
+ /// </summary>
+ public abstract class UnaryOperationBinder : DynamicMetaObjectBinder {
+ private ExpressionType _operation;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BinaryOperationBinder"/> class.
+ /// </summary>
+ /// <param name="operation">The unary operation kind.</param>
+ protected UnaryOperationBinder(ExpressionType operation) {
+ ContractUtils.Requires(OperationIsValid(operation), "operation");
+ _operation = operation;
+ }
+
+ /// <summary>
+ /// The result type of the operation.
+ /// </summary>
+ public override sealed Type ReturnType {
+ get {
+ switch(_operation) {
+ case ExpressionType.IsFalse:
+ case ExpressionType.IsTrue:
+ return typeof(bool);
+ default:
+ return typeof(object);
+ }
+ }
+ }
+
+ /// <summary>
+ /// The unary operation kind.
+ /// </summary>
+ public ExpressionType Operation {
+ get {
+ return _operation;
+ }
+ }
+
+ /// <summary>
+ /// Performs the binding of the unary dynamic operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic unary operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target) {
+ return FallbackUnaryOperation(target, null);
+ }
+
+ /// <summary>
+ /// Performs the binding of the unary dynamic operation if the target dynamic object cannot bind.
+ /// </summary>
+ /// <param name="target">The target of the dynamic unary operation.</param>
+ /// <param name="errorSuggestion">The binding result in case the binding fails, or null.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public abstract DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion);
+
+ /// <summary>
+ /// Performs the binding of the dynamic unary operation.
+ /// </summary>
+ /// <param name="target">The target of the dynamic operation.</param>
+ /// <param name="args">An array of arguments of the dynamic operation.</param>
+ /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
+ public sealed override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
+ ContractUtils.RequiresNotNull(target, "target");
+ ContractUtils.Requires(args == null || args.Length == 0, "args");
+
+ return target.BindUnaryOperation(this);
+ }
+
+ // this is a standard DynamicMetaObjectBinder
+ internal override sealed bool IsStandardBinder {
+ get {
+ return true;
+ }
+ }
+
+ internal static bool OperationIsValid(ExpressionType operation) {
+ switch (operation) {
+ #region Generated Unary Operation Binder Validator
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_unop_validator from: generate_tree.py
+
+ case ExpressionType.Negate:
+ case ExpressionType.UnaryPlus:
+ case ExpressionType.Not:
+ case ExpressionType.Decrement:
+ case ExpressionType.Increment:
+ case ExpressionType.OnesComplement:
+ case ExpressionType.IsTrue:
+ case ExpressionType.IsFalse:
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ case ExpressionType.Extension:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UpdateDelegates.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UpdateDelegates.Generated.cs
new file mode 100644
index 00000000000..28ec2d4f351
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Actions/UpdateDelegates.Generated.cs
@@ -0,0 +1,2665 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Threading;
+
+#if CODEPLEX_40
+namespace System.Dynamic {
+#else
+namespace Microsoft.Scripting {
+#endif
+ internal static partial class UpdateDelegates {
+
+ //
+ // WARNING: do not edit these methods here. The real source code lives
+ // in two places: generate_dynsites.py, which generates the methods in
+ // this file, and UpdateDelegates.cs, which dynamically generates
+ // methods like these at run time. If you want to make a change, edit
+ // *both* of those files instead
+ //
+
+ #region Generated UpdateAndExecute Methods
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_update_targets from: generate_dynsites.py
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute0<TRet>(CallSite site) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, TRet>>)site;
+ Func<CallSite, TRet>[] applicable;
+ Func<CallSite, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch0<TRet>(CallSite site) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute1<T0, TRet>(CallSite site, T0 arg0) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, TRet>>)site;
+ Func<CallSite, T0, TRet>[] applicable;
+ Func<CallSite, T0, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch1<T0, TRet>(CallSite site, T0 arg0) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute2<T0, T1, TRet>(CallSite site, T0 arg0, T1 arg1) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, TRet>>)site;
+ Func<CallSite, T0, T1, TRet>[] applicable;
+ Func<CallSite, T0, T1, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch2<T0, T1, TRet>(CallSite site, T0 arg0, T1 arg1) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute3<T0, T1, T2, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, TRet>>)site;
+ Func<CallSite, T0, T1, T2, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch3<T0, T1, T2, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute4<T0, T1, T2, T3, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch4<T0, T1, T2, T3, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute5<T0, T1, T2, T3, T4, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, T4, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, T4, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, T4, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3, arg4);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch5<T0, T1, T2, T3, T4, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute6<T0, T1, T2, T3, T4, T5, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, T4, T5, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch6<T0, T1, T2, T3, T4, T5, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute7<T0, T1, T2, T3, T4, T5, T6, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, T4, T5, T6, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch7<T0, T1, T2, T3, T4, T5, T6, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute8<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch8<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch9<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static TRet UpdateAndExecute10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>>)site;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>[] applicable;
+ Func<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet> rule, originalRule = @this.Target;
+ TRet result;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return result;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ result = rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ if (CallSiteOps.GetMatch(site)) {
+ return result;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static TRet NoMatch10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
+ site._match = false;
+ return default(TRet);
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid1<T0>(CallSite site, T0 arg0) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0>>)site;
+ Action<CallSite, T0>[] applicable;
+ Action<CallSite, T0> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid1<T0>(CallSite site, T0 arg0) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid2<T0, T1>(CallSite site, T0 arg0, T1 arg1) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1>>)site;
+ Action<CallSite, T0, T1>[] applicable;
+ Action<CallSite, T0, T1> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid2<T0, T1>(CallSite site, T0 arg0, T1 arg1) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid3<T0, T1, T2>(CallSite site, T0 arg0, T1 arg1, T2 arg2) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2>>)site;
+ Action<CallSite, T0, T1, T2>[] applicable;
+ Action<CallSite, T0, T1, T2> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid3<T0, T1, T2>(CallSite site, T0 arg0, T1 arg1, T2 arg2) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid4<T0, T1, T2, T3>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3>>)site;
+ Action<CallSite, T0, T1, T2, T3>[] applicable;
+ Action<CallSite, T0, T1, T2, T3> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid4<T0, T1, T2, T3>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid5<T0, T1, T2, T3, T4>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3, T4>>)site;
+ Action<CallSite, T0, T1, T2, T3, T4>[] applicable;
+ Action<CallSite, T0, T1, T2, T3, T4> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3, arg4);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid5<T0, T1, T2, T3, T4>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid6<T0, T1, T2, T3, T4, T5>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3, T4, T5>>)site;
+ Action<CallSite, T0, T1, T2, T3, T4, T5>[] applicable;
+ Action<CallSite, T0, T1, T2, T3, T4, T5> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid6<T0, T1, T2, T3, T4, T5>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid7<T0, T1, T2, T3, T4, T5, T6>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3, T4, T5, T6>>)site;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6>[] applicable;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid7<T0, T1, T2, T3, T4, T5, T6>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid8<T0, T1, T2, T3, T4, T5, T6, T7>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7>>)site;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7>[] applicable;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid8<T0, T1, T2, T3, T4, T5, T6, T7>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid9<T0, T1, T2, T3, T4, T5, T6, T7, T8>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8>>)site;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8>[] applicable;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid9<T0, T1, T2, T3, T4, T5, T6, T7, T8>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
+ site._match = false;
+ return;
+ }
+
+
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ internal static void UpdateAndExecuteVoid10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
+ //
+ // Declare the locals here upfront. It actually saves JIT stack space.
+ //
+ var @this = (CallSite<Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>>)site;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>[] applicable;
+ Action<CallSite, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> rule, originalRule = @this.Target;
+
+
+ //
+ // Create matchmaker and its site. We'll need them regardless.
+ //
+ site = CallSiteOps.CreateMatchmaker(@this);
+
+ //
+ // Level 1 cache lookup
+ //
+ if ((applicable = CallSiteOps.GetRules(@this)) != null) {
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+
+ // if we've already tried it skip it...
+ if ((object)rule != (object)originalRule) {
+ @this.Target = rule;
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+
+ if (CallSiteOps.GetMatch(site)) {
+ CallSiteOps.UpdateRules(@this, i);
+ return;
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+ }
+
+ //
+ // Level 2 cache lookup
+ //
+
+ //
+ // Any applicable rules in level 2 cache?
+ //
+
+ var cache = CallSiteOps.GetRuleCache(@this);
+
+ applicable = cache.GetRules();
+ for (int i = 0; i < applicable.Length; i++) {
+ rule = applicable[i];
+
+ //
+ // Execute the rule
+ //
+ @this.Target = rule;
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // Rule worked. Add it to level 1 cache
+ //
+ CallSiteOps.AddRule(@this, rule);
+ // and then move it to the front of the L2 cache
+ CallSiteOps.MoveRule(cache, rule, i);
+ }
+ }
+
+ // Rule didn't match, try the next one
+ CallSiteOps.ClearMatch(site);
+ }
+
+ //
+ // Miss on Level 0, 1 and 2 caches. Create new rule
+ //
+
+ rule = null;
+ var args = new object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 };
+
+ for (; ; ) {
+ @this.Target = originalRule;
+ rule = @this.Target = @this.Binder.BindCore(@this, args);
+
+ //
+ // Execute the rule on the matchmaker site
+ //
+
+ try {
+ rule(site, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ if (CallSiteOps.GetMatch(site)) {
+ return;
+ }
+ } finally {
+ if (CallSiteOps.GetMatch(site)) {
+ //
+ // The rule worked. Add it to level 1 cache.
+ //
+ CallSiteOps.AddRule(@this, rule);
+ }
+ }
+
+ // Rule we got back didn't work, try another one
+ CallSiteOps.ClearMatch(site);
+ }
+ }
+
+ [Obsolete("pregenerated CallSite<T>.Update delegate", true)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ internal static void NoMatchVoid10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
+ site._match = false;
+ return;
+ }
+
+
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs
new file mode 100644
index 00000000000..df231bf8a44
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BinaryExpression.cs
@@ -0,0 +1,2624 @@
+
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents an expression that has a binary operator.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.BinaryExpressionProxy))]
+#endif
+ public class BinaryExpression : Expression {
+ private readonly Expression _left;
+ private readonly Expression _right;
+
+ internal BinaryExpression(Expression left, Expression right) {
+ _left = left;
+ _right = right;
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node can be reduced.
+ /// </summary>
+ public override bool CanReduce {
+ get {
+ // Only OpAssignments are reducible.
+ return IsOpAssignment(NodeType);
+ }
+ }
+
+ private static bool IsOpAssignment(ExpressionType op) {
+ switch (op) {
+ case ExpressionType.AddAssign:
+ case ExpressionType.SubtractAssign:
+ case ExpressionType.MultiplyAssign:
+ case ExpressionType.AddAssignChecked:
+ case ExpressionType.SubtractAssignChecked:
+ case ExpressionType.MultiplyAssignChecked:
+ case ExpressionType.DivideAssign:
+ case ExpressionType.ModuloAssign:
+ case ExpressionType.PowerAssign:
+ case ExpressionType.AndAssign:
+ case ExpressionType.OrAssign:
+ case ExpressionType.RightShiftAssign:
+ case ExpressionType.LeftShiftAssign:
+ case ExpressionType.ExclusiveOrAssign:
+ return true;
+ }
+ return false;
+ }
+ /// <summary>
+ /// Gets the right operand of the binary operation.
+ /// </summary>
+ public Expression Right {
+ get { return _right; }
+ }
+ /// <summary>
+ /// Gets the left operand of the binary operation.
+ /// </summary>
+ public Expression Left {
+ get { return _left; }
+ }
+ /// <summary>
+ /// Gets the implementing method for the binary operation.
+ /// </summary>
+ public MethodInfo Method {
+ get { return GetMethod(); }
+ }
+
+ internal virtual MethodInfo GetMethod() {
+ return null;
+ }
+
+ /// <summary>
+ /// Reduces the binary expression node to a simpler expression.
+ /// If CanReduce returns true, this should return a valid expression.
+ /// This method is allowed to return another node which itself
+ /// must be reduced.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ public override Expression Reduce() {
+ // Only reduce OpAssignment expressions.
+ if (IsOpAssignment(NodeType)) {
+ switch (_left.NodeType) {
+ case ExpressionType.MemberAccess:
+ return ReduceMember();
+
+ case ExpressionType.Index:
+ return ReduceIndex();
+
+ default:
+ return ReduceVariable();
+ }
+ }
+ return this;
+ }
+
+ // Return the corresponding Op of an assignment op.
+ private static ExpressionType GetBinaryOpFromAssignmentOp(ExpressionType op) {
+ Debug.Assert(IsOpAssignment(op));
+ switch (op) {
+ case ExpressionType.AddAssign:
+ return ExpressionType.Add;
+ case ExpressionType.AddAssignChecked:
+ return ExpressionType.AddChecked;
+ case ExpressionType.SubtractAssign:
+ return ExpressionType.Subtract;
+ case ExpressionType.SubtractAssignChecked:
+ return ExpressionType.SubtractChecked;
+ case ExpressionType.MultiplyAssign:
+ return ExpressionType.Multiply;
+ case ExpressionType.MultiplyAssignChecked:
+ return ExpressionType.MultiplyChecked;
+ case ExpressionType.DivideAssign:
+ return ExpressionType.Divide;
+ case ExpressionType.ModuloAssign:
+ return ExpressionType.Modulo;
+ case ExpressionType.PowerAssign:
+ return ExpressionType.Power;
+ case ExpressionType.AndAssign:
+ return ExpressionType.And;
+ case ExpressionType.OrAssign:
+ return ExpressionType.Or;
+ case ExpressionType.RightShiftAssign:
+ return ExpressionType.RightShift;
+ case ExpressionType.LeftShiftAssign:
+ return ExpressionType.LeftShift;
+ case ExpressionType.ExclusiveOrAssign:
+ return ExpressionType.ExclusiveOr;
+ default:
+ // must be an error
+ throw Error.InvalidOperation("op");
+ }
+
+ }
+
+ private Expression ReduceVariable() {
+ // v (op)= r
+ // ... is reduced into ...
+ // v = v (op) r
+ ExpressionType op = GetBinaryOpFromAssignmentOp(NodeType);
+ Expression r = Expression.MakeBinary(op, _left, _right, false, Method);
+ LambdaExpression conversion = GetConversion();
+ if (conversion != null) {
+ r = Expression.Invoke(conversion, r);
+ }
+ return Expression.Assign(_left, r);
+ }
+
+ private Expression ReduceMember() {
+ MemberExpression member = (MemberExpression)_left;
+
+ if (member.Expression == null) {
+ // static member, reduce the same as variable
+ return ReduceVariable();
+ } else {
+ // left.b (op)= r
+ // ... is reduced into ...
+ // temp1 = left
+ // temp2 = temp1.b (op) r
+ // temp1.b = temp2
+ // temp2
+ ParameterExpression temp1 = Variable(member.Expression.Type, "temp1");
+
+ // 1. temp1 = left
+ Expression e1 = Expression.Assign(temp1, member.Expression);
+
+ // 2. temp2 = temp1.b (op) r
+ ExpressionType op = GetBinaryOpFromAssignmentOp(NodeType);
+ Expression e2 = Expression.MakeBinary(op, Expression.MakeMemberAccess(temp1, member.Member), _right, false, Method);
+ LambdaExpression conversion = GetConversion();
+ if (conversion != null) {
+ e2 = Expression.Invoke(conversion, e2);
+ }
+ ParameterExpression temp2 = Variable(e2.Type, "temp2");
+ e2 = Expression.Assign(temp2, e2);
+
+ // 3. temp1.b = temp2
+ Expression e3 = Expression.Assign(Expression.MakeMemberAccess(temp1, member.Member), temp2);
+
+ // 3. temp2
+ Expression e4 = temp2;
+
+ return Expression.Block(
+ new ParameterExpression[] { temp1, temp2 },
+ e1, e2, e3, e4
+ );
+ }
+ }
+
+ private Expression ReduceIndex() {
+ // left[a0, a1, ... aN] (op)= r
+ //
+ // ... is reduced into ...
+ //
+ // tempObj = left
+ // tempArg0 = a0
+ // ...
+ // tempArgN = aN
+ // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
+ // tempObj[tempArg0, ... tempArgN] = tempValue
+
+ var index = (IndexExpression)_left;
+
+ var vars = new List<ParameterExpression>(index.Arguments.Count + 2);
+ var exprs = new List<Expression>(index.Arguments.Count + 3);
+
+ var tempObj = Expression.Variable(index.Object.Type, "tempObj");
+ vars.Add(tempObj);
+ exprs.Add(Expression.Assign(tempObj, index.Object));
+
+ var tempArgs = new List<Expression>(index.Arguments.Count);
+ foreach (var arg in index.Arguments) {
+ var tempArg = Expression.Variable(arg.Type, "tempArg" + tempArgs.Count);
+ vars.Add(tempArg);
+ tempArgs.Add(tempArg);
+ exprs.Add(Expression.Assign(tempArg, arg));
+ }
+
+ var tempIndex = Expression.MakeIndex(tempObj, index.Indexer, tempArgs);
+
+ // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
+ ExpressionType binaryOp = GetBinaryOpFromAssignmentOp(NodeType);
+ Expression op = Expression.MakeBinary(binaryOp, tempIndex, _right, false, Method);
+ LambdaExpression conversion = GetConversion();
+ if (conversion != null) {
+ op = Expression.Invoke(conversion, op);
+ }
+ var tempValue = Expression.Variable(op.Type, "tempValue");
+ vars.Add(tempValue);
+ exprs.Add(Expression.Assign(tempValue, op));
+
+ // tempObj[tempArg0, ... tempArgN] = tempValue
+ exprs.Add(Expression.Assign(tempIndex, tempValue));
+
+ return Expression.Block(vars, exprs);
+ }
+
+ /// <summary>
+ /// Gets the type conversion function that is used by a coalescing or compound assignment operation.
+ /// </summary>
+ public LambdaExpression Conversion {
+ get { return GetConversion(); }
+ }
+
+ internal virtual LambdaExpression GetConversion() {
+ return null;
+ }
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
+ /// </summary>
+ public bool IsLifted {
+ get {
+ if (NodeType == ExpressionType.Coalesce || NodeType == ExpressionType.Assign) {
+ return false;
+ }
+ if (TypeUtils.IsNullableType(_left.Type)) {
+ MethodInfo method = GetMethod();
+ return method == null ||
+ !TypeUtils.AreEquivalent(method.GetParametersCached()[0].ParameterType.GetNonRefType(), _left.Type);
+ }
+ return false;
+ }
+ }
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator whose return type is lifted to a nullable type.
+ /// </summary>
+ public bool IsLiftedToNull {
+ get {
+ return IsLifted && TypeUtils.IsNullableType(Type);
+ }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitBinary(this);
+ }
+
+ internal static Expression Create(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method, LambdaExpression conversion) {
+ if (nodeType == ExpressionType.Assign) {
+ Debug.Assert(method == null && TypeUtils.AreEquivalent(type, left.Type));
+ return new AssignBinaryExpression(left, right);
+ }
+ if (conversion != null) {
+ Debug.Assert(method == null && TypeUtils.AreEquivalent(type, right.Type) && nodeType == ExpressionType.Coalesce);
+ return new CoalesceConversionBinaryExpression(left, right, conversion);
+ }
+ if (method != null) {
+ return new MethodBinaryExpression(nodeType, left, right, type, method);
+ }
+ if (type == typeof(bool)) {
+ return new LogicalBinaryExpression(nodeType, left, right);
+ }
+ return new SimpleBinaryExpression(nodeType, left, right, type);
+ }
+
+ internal bool IsLiftedLogical {
+ get {
+ Type left = _left.Type;
+ Type right = _right.Type;
+ MethodInfo method = GetMethod();
+ ExpressionType kind = NodeType;
+
+ return
+ (kind == ExpressionType.AndAlso || kind == ExpressionType.OrElse) &&
+ TypeUtils.AreEquivalent(right, left) &&
+ TypeUtils.IsNullableType(left) &&
+ method != null &&
+ TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left));
+ }
+ }
+
+ internal bool IsReferenceComparison {
+ get {
+ Type left = _left.Type;
+ Type right = _right.Type;
+ MethodInfo method = GetMethod();
+ ExpressionType kind = NodeType;
+
+ return (kind == ExpressionType.Equal || kind == ExpressionType.NotEqual) &&
+ method == null && !left.IsValueType && !right.IsValueType;
+ }
+ }
+
+ //
+ // For a userdefined type T which has op_False defined and L, R are
+ // nullable, (L AndAlso R) is computed as:
+ //
+ // L.HasValue
+ // ? T.op_False(L.GetValueOrDefault())
+ // ? L
+ // : R.HasValue
+ // ? (T?)(T.op_BitwiseAnd(L.GetValueOrDefault(), R.GetValueOrDefault()))
+ // : null
+ // : null
+ //
+ // For a userdefined type T which has op_True defined and L, R are
+ // nullable, (L OrElse R) is computed as:
+ //
+ // L.HasValue
+ // ? T.op_True(L.GetValueOrDefault())
+ // ? L
+ // : R.HasValue
+ // ? (T?)(T.op_BitwiseOr(L.GetValueOrDefault(), R.GetValueOrDefault()))
+ // : null
+ // : null
+ //
+ //
+ // This is the same behavior as VB. If you think about it, it makes
+ // sense: it's combining the normal pattern for short-circuiting
+ // operators, with the normal pattern for lifted operations: if either
+ // of the operands is null, the result is also null.
+ //
+ internal Expression ReduceUserdefinedLifted() {
+ Debug.Assert(IsLiftedLogical);
+
+ var left = Parameter(_left.Type, "left");
+ var right = Parameter(Right.Type, "right");
+ string opName = NodeType == ExpressionType.AndAlso ? "op_False" : "op_True";
+ MethodInfo opTrueFalse = TypeUtils.GetBooleanOperator(Method.DeclaringType, opName);
+ Debug.Assert(opTrueFalse != null);
+
+ return Block(
+ new[] { left },
+ Assign(left, _left),
+ Condition(
+ Property(left, "HasValue"),
+ Condition(
+ Call(opTrueFalse, Call(left, "GetValueOrDefault", null)),
+ left,
+ Block(
+ new[] { right },
+ Assign(right, _right),
+ Condition(
+ Property(right, "HasValue"),
+ Convert(
+ Call(
+ Method,
+ Call(left, "GetValueOrDefault", null),
+ Call(right, "GetValueOrDefault", null)
+ ),
+ Type
+ ),
+ Constant(null, Type)
+ )
+ )
+ ),
+ Constant(null, Type)
+ )
+ );
+ }
+ }
+
+ // Optimized representation of simple logical expressions:
+ // && || == != > < >= <=
+ internal sealed class LogicalBinaryExpression : BinaryExpression {
+ private readonly ExpressionType _nodeType;
+
+ internal LogicalBinaryExpression(ExpressionType nodeType, Expression left, Expression right)
+ : base(left, right) {
+ _nodeType = nodeType;
+ }
+
+ public sealed override Type Type {
+ get { return typeof(bool); }
+ }
+
+ public sealed override ExpressionType NodeType {
+ get { return _nodeType; }
+ }
+ }
+
+ // Optimized assignment node, only holds onto children
+ internal sealed class AssignBinaryExpression : BinaryExpression {
+ internal AssignBinaryExpression(Expression left, Expression right)
+ : base(left, right) {
+ }
+
+ public sealed override Type Type {
+ get { return Left.Type; }
+ }
+
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Assign; }
+ }
+ }
+
+ // Coalesce with conversion
+ // This is not a frequently used node, but rather we want to save every
+ // other BinaryExpression from holding onto the null conversion lambda
+ internal sealed class CoalesceConversionBinaryExpression : BinaryExpression {
+ private readonly LambdaExpression _conversion;
+
+ internal CoalesceConversionBinaryExpression(Expression left, Expression right, LambdaExpression conversion)
+ : base(left, right) {
+ _conversion = conversion;
+ }
+
+ internal override LambdaExpression GetConversion() {
+ return _conversion;
+ }
+
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Coalesce; }
+ }
+
+ public sealed override Type Type {
+ get { return Right.Type; }
+ }
+ }
+
+ // OpAssign with conversion
+ // This is not a frequently used node, but rather we want to save every
+ // other BinaryExpression from holding onto the null conversion lambda
+ internal sealed class OpAssignMethodConversionBinaryExpression : MethodBinaryExpression {
+ private readonly LambdaExpression _conversion;
+
+ internal OpAssignMethodConversionBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method, LambdaExpression conversion)
+ : base(nodeType, left, right, type, method) {
+ _conversion = conversion;
+ }
+
+ internal override LambdaExpression GetConversion() {
+ return _conversion;
+ }
+ }
+
+ // Class that handles most binary expressions
+ // If needed, it can be optimized even more (often Type == left.Type)
+ internal class SimpleBinaryExpression : BinaryExpression {
+ private readonly ExpressionType _nodeType;
+ private readonly Type _type;
+
+ internal SimpleBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type)
+ : base(left, right) {
+ _nodeType = nodeType;
+ _type = type;
+ }
+
+ public sealed override ExpressionType NodeType {
+ get { return _nodeType; }
+ }
+
+ public sealed override Type Type {
+ get { return _type; }
+ }
+ }
+
+ // Class that handles binary expressions with a method
+ // If needed, it can be optimized even more (often Type == method.ReturnType)
+ internal class MethodBinaryExpression : SimpleBinaryExpression {
+ private readonly MethodInfo _method;
+
+ internal MethodBinaryExpression(ExpressionType nodeType, Expression left, Expression right, Type type, MethodInfo method)
+ : base(nodeType, left, right, type) {
+ _method = method;
+ }
+
+ internal override MethodInfo GetMethod() {
+ return _method;
+ }
+ }
+
+ public partial class Expression {
+
+ #region Assign
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see ref="F:ExpressionType.Assign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Assign(Expression left, Expression right) {
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ TypeUtils.ValidateType(left.Type);
+ TypeUtils.ValidateType(right.Type);
+ if (!TypeUtils.AreReferenceAssignable(left.Type, right.Type)) {
+ throw Error.ExpressionTypeDoesNotMatchAssignment(right.Type, left.Type);
+ }
+ return new AssignBinaryExpression(left, right);
+ }
+
+ #endregion
+
+
+ private static BinaryExpression GetUserDefinedBinaryOperator(ExpressionType binaryType, string name, Expression left, Expression right, bool liftToNull) {
+ // try exact match first
+ MethodInfo method = GetUserDefinedBinaryOperator(binaryType, left.Type, right.Type, name);
+ if (method != null) {
+ return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
+ }
+ // try lifted call
+ if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type)) {
+ Type nnLeftType = TypeUtils.GetNonNullableType(left.Type);
+ Type nnRightType = TypeUtils.GetNonNullableType(right.Type);
+ method = GetUserDefinedBinaryOperator(binaryType, nnLeftType, nnRightType, name);
+ if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
+ if (method.ReturnType != typeof(bool) || liftToNull) {
+ return new MethodBinaryExpression(binaryType, left, right, TypeUtils.GetNullableType(method.ReturnType), method);
+ } else {
+ return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
+ }
+ }
+ }
+ return null;
+ }
+
+
+ private static BinaryExpression GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, bool liftToNull) {
+ System.Diagnostics.Debug.Assert(method != null);
+ ValidateOperator(method);
+ ParameterInfo[] pms = method.GetParametersCached();
+ if (pms.Length != 2)
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ if (ParameterIsAssignable(pms[0], left.Type) && ParameterIsAssignable(pms[1], right.Type)) {
+ ValidateParamswithOperandsOrThrow(pms[0].ParameterType, left.Type, binaryType, method.Name);
+ ValidateParamswithOperandsOrThrow(pms[1].ParameterType, right.Type, binaryType, method.Name);
+ return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
+
+ }
+ // check for lifted call
+ if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type) &&
+ ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
+ ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right.Type)) &&
+ method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
+ if (method.ReturnType != typeof(bool) || liftToNull) {
+ return new MethodBinaryExpression(binaryType, left, right, TypeUtils.GetNullableType(method.ReturnType), method);
+ } else {
+ return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
+ }
+ }
+ throw Error.OperandTypesDoNotMatchParameters(binaryType, method.Name);
+ }
+
+ private static BinaryExpression GetMethodBasedAssignOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression conversion, bool liftToNull) {
+ BinaryExpression b = GetMethodBasedBinaryOperator(binaryType, left, right, method, liftToNull);
+ if (conversion == null) {
+ // return type must be assignable back to the left type
+ if (!TypeUtils.AreReferenceAssignable(left.Type, b.Type)) {
+ throw Error.UserDefinedOpMustHaveValidReturnType(binaryType, b.Method.Name);
+ }
+ } else {
+ // add the conversion to the result
+ ValidateOpAssignConversionLambda(conversion, b.Left, b.Method, b.NodeType);
+ b = new OpAssignMethodConversionBinaryExpression(b.NodeType, b.Left, b.Right, b.Left.Type, b.Method, conversion);
+ }
+ return b;
+ }
+
+
+ private static BinaryExpression GetUserDefinedBinaryOperatorOrThrow(ExpressionType binaryType, string name, Expression left, Expression right, bool liftToNull) {
+ BinaryExpression b = GetUserDefinedBinaryOperator(binaryType, name, left, right, liftToNull);
+ if (b != null) {
+ ParameterInfo[] pis = b.Method.GetParametersCached();
+ ValidateParamswithOperandsOrThrow(pis[0].ParameterType, left.Type, binaryType, name);
+ ValidateParamswithOperandsOrThrow(pis[1].ParameterType, right.Type, binaryType, name);
+ return b;
+ }
+ throw Error.BinaryOperatorNotDefined(binaryType, left.Type, right.Type);
+ }
+
+ private static BinaryExpression GetUserDefinedAssignOperatorOrThrow(ExpressionType binaryType, string name, Expression left, Expression right, LambdaExpression conversion, bool liftToNull) {
+ BinaryExpression b = GetUserDefinedBinaryOperatorOrThrow(binaryType, name, left, right, liftToNull);
+ if (conversion == null) {
+ // return type must be assignable back to the left type
+ if (!TypeUtils.AreReferenceAssignable(left.Type, b.Type)) {
+ throw Error.UserDefinedOpMustHaveValidReturnType(binaryType, b.Method.Name);
+ }
+ } else {
+ // add the conversion to the result
+ ValidateOpAssignConversionLambda(conversion, b.Left, b.Method, b.NodeType);
+ b = new OpAssignMethodConversionBinaryExpression(b.NodeType, b.Left, b.Right, b.Left.Type, b.Method, conversion);
+ }
+ return b;
+ }
+
+
+ private static MethodInfo GetUserDefinedBinaryOperator(ExpressionType binaryType, Type leftType, Type rightType, string name) {
+ // UNDONE: This algorithm is wrong, we should be checking for uniqueness and erroring if
+ // UNDONE: it is defined on both types.
+ Type[] types = new Type[] { leftType, rightType };
+ Type nnLeftType = TypeUtils.GetNonNullableType(leftType);
+ Type nnRightType = TypeUtils.GetNonNullableType(rightType);
+ BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+ MethodInfo method = nnLeftType.GetMethodValidated(name, flags, null, types, null);
+ if (method == null && !TypeUtils.AreEquivalent(leftType, rightType)) {
+ method = nnRightType.GetMethodValidated(name, flags, null, types, null);
+ }
+
+ if (IsLiftingConditionalLogicalOperator(leftType, rightType, method, binaryType)) {
+ method = GetUserDefinedBinaryOperator(binaryType, nnLeftType, nnRightType, name);
+ }
+ return method;
+ }
+
+
+ private static bool IsLiftingConditionalLogicalOperator(Type left, Type right, MethodInfo method, ExpressionType binaryType) {
+ return TypeUtils.IsNullableType(right) &&
+ TypeUtils.IsNullableType(left) &&
+ method == null &&
+ (binaryType == ExpressionType.AndAlso || binaryType == ExpressionType.OrElse);
+ }
+
+
+ internal static bool ParameterIsAssignable(ParameterInfo pi, Type argType) {
+ Type pType = pi.ParameterType;
+ if (pType.IsByRef)
+ pType = pType.GetElementType();
+ return TypeUtils.AreReferenceAssignable(pType, argType);
+ }
+
+
+ private static void ValidateParamswithOperandsOrThrow(Type paramType, Type operandType, ExpressionType exprType, string name) {
+ if (TypeUtils.IsNullableType(paramType) && !TypeUtils.IsNullableType(operandType)) {
+ throw Error.OperandTypesDoNotMatchParameters(exprType, name);
+ }
+ }
+
+
+ private static void ValidateOperator(MethodInfo method) {
+ System.Diagnostics.Debug.Assert(method != null);
+ ValidateMethodInfo(method);
+ if (!method.IsStatic)
+ throw Error.UserDefinedOperatorMustBeStatic(method);
+ if (method.ReturnType == typeof(void))
+ throw Error.UserDefinedOperatorMustNotBeVoid(method);
+ }
+
+
+ private static void ValidateMethodInfo(MethodInfo method) {
+ if (method.IsGenericMethodDefinition)
+ throw Error.MethodIsGeneric(method);
+ if (method.ContainsGenericParameters)
+ throw Error.MethodContainsGenericParameters(method);
+ }
+
+
+ private static bool IsNullComparison(Expression left, Expression right) {
+ // If we have x==null, x!=null, null==x or null!=x where x is
+ // nullable but not null, then this is treated as a call to x.HasValue
+ // and is legal even if there is no equality operator defined on the
+ // type of x.
+ if (IsNullConstant(left) && !IsNullConstant(right) && TypeUtils.IsNullableType(right.Type)) {
+ return true;
+ }
+ if (IsNullConstant(right) && !IsNullConstant(left) && TypeUtils.IsNullableType(left.Type)) {
+ return true;
+ }
+ return false;
+ }
+
+
+ // Note: this has different meaning than ConstantCheck.IsNull
+ // That function attempts to determine if the result of a tree will be
+ // null at runtime. This function is used at tree construction time and
+ // only looks for a ConstantExpression with a null Value. It can't
+ // become "smarter" or that would break tree construction.
+ private static bool IsNullConstant(Expression e) {
+ var c = e as ConstantExpression;
+ return c != null && c.Value == null;
+ }
+
+
+ private static void ValidateUserDefinedConditionalLogicOperator(ExpressionType nodeType, Type left, Type right, MethodInfo method) {
+ ValidateOperator(method);
+ ParameterInfo[] pms = method.GetParametersCached();
+ if (pms.Length != 2)
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ if (!ParameterIsAssignable(pms[0], left)) {
+ if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left))))
+ throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
+ }
+ if (!ParameterIsAssignable(pms[1], right)) {
+ if (!(TypeUtils.IsNullableType(right) && ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right))))
+ throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
+ }
+ if (pms[0].ParameterType != pms[1].ParameterType) {
+ throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
+ }
+ if (method.ReturnType != pms[0].ParameterType) {
+ throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
+ }
+ if (IsValidLiftedConditionalLogicalOperator(left, right, pms)) {
+ left = TypeUtils.GetNonNullableType(left);
+ right = TypeUtils.GetNonNullableType(left);
+ }
+ MethodInfo opTrue = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_True");
+ MethodInfo opFalse = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_False");
+ if (opTrue == null || opTrue.ReturnType != typeof(bool) ||
+ opFalse == null || opFalse.ReturnType != typeof(bool)) {
+ throw Error.LogicalOperatorMustHaveBooleanOperators(nodeType, method.Name);
+ }
+ VerifyOpTrueFalse(nodeType, left, opFalse);
+ VerifyOpTrueFalse(nodeType, left, opTrue);
+ }
+
+ private static void VerifyOpTrueFalse(ExpressionType nodeType, Type left, MethodInfo opTrue) {
+ ParameterInfo[] pmsOpTrue = opTrue.GetParametersCached();
+ if (pmsOpTrue.Length != 1)
+ throw Error.IncorrectNumberOfMethodCallArguments(opTrue);
+
+ if (!ParameterIsAssignable(pmsOpTrue[0], left)) {
+ if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pmsOpTrue[0], TypeUtils.GetNonNullableType(left))))
+ throw Error.OperandTypesDoNotMatchParameters(nodeType, opTrue.Name);
+ }
+ }
+
+ private static bool IsValidLiftedConditionalLogicalOperator(Type left, Type right, ParameterInfo[] pms) {
+ return TypeUtils.AreEquivalent(left, right) &&
+ TypeUtils.IsNullableType(right) &&
+ TypeUtils.AreEquivalent(pms[1].ParameterType, TypeUtils.GetNonNullableType(right));
+ }
+
+
+ /// <summary>
+ /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
+ /// </summary>
+ /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
+ /// <param name="left">An Expression that represents the left operand.</param>
+ /// <param name="right">An Expression that represents the right operand.</param>
+ /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
+ public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right) {
+ return MakeBinary(binaryType, left, right, false, null, null);
+ }
+
+ /// <summary>
+ /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
+ /// </summary>
+ /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
+ /// <param name="left">An Expression that represents the left operand.</param>
+ /// <param name="right">An Expression that represents the right operand.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <param name="method">A MethodInfo that specifies the implementing method.</param>
+ /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
+ public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ return MakeBinary(binaryType, left, right, liftToNull, method, null);
+ }
+
+ ///
+ /// <summary>
+ /// Creates a BinaryExpression, given the left and right operands, by calling an appropriate factory method.
+ /// </summary>
+ /// <param name="binaryType">The ExpressionType that specifies the type of binary operation.</param>
+ /// <param name="left">An Expression that represents the left operand.</param>
+ /// <param name="right">An Expression that represents the right operand.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <param name="method">A MethodInfo that specifies the implementing method.</param>
+ /// <param name="conversion">A LambdaExpression that represents a type conversion function. This parameter is used if binaryType is Coalesce or compound assignment.</param>
+ /// <returns>The BinaryExpression that results from calling the appropriate factory method.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ public static BinaryExpression MakeBinary(ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method, LambdaExpression conversion) {
+ switch (binaryType) {
+ case ExpressionType.Add:
+ return Add(left, right, method);
+ case ExpressionType.AddChecked:
+ return AddChecked(left, right, method);
+ case ExpressionType.Subtract:
+ return Subtract(left, right, method);
+ case ExpressionType.SubtractChecked:
+ return SubtractChecked(left, right, method);
+ case ExpressionType.Multiply:
+ return Multiply(left, right, method);
+ case ExpressionType.MultiplyChecked:
+ return MultiplyChecked(left, right, method);
+ case ExpressionType.Divide:
+ return Divide(left, right, method);
+ case ExpressionType.Modulo:
+ return Modulo(left, right, method);
+ case ExpressionType.Power:
+ return Power(left, right, method);
+ case ExpressionType.And:
+ return And(left, right, method);
+ case ExpressionType.AndAlso:
+ return AndAlso(left, right, method);
+ case ExpressionType.Or:
+ return Or(left, right, method);
+ case ExpressionType.OrElse:
+ return OrElse(left, right, method);
+ case ExpressionType.LessThan:
+ return LessThan(left, right, liftToNull, method);
+ case ExpressionType.LessThanOrEqual:
+ return LessThanOrEqual(left, right, liftToNull, method);
+ case ExpressionType.GreaterThan:
+ return GreaterThan(left, right, liftToNull, method);
+ case ExpressionType.GreaterThanOrEqual:
+ return GreaterThanOrEqual(left, right, liftToNull, method);
+ case ExpressionType.Equal:
+ return Equal(left, right, liftToNull, method);
+ case ExpressionType.NotEqual:
+ return NotEqual(left, right, liftToNull, method);
+ case ExpressionType.ExclusiveOr:
+ return ExclusiveOr(left, right, method);
+ case ExpressionType.Coalesce:
+ return Coalesce(left, right, conversion);
+ case ExpressionType.ArrayIndex:
+ return ArrayIndex(left, right);
+ case ExpressionType.RightShift:
+ return RightShift(left, right, method);
+ case ExpressionType.LeftShift:
+ return LeftShift(left, right, method);
+ case ExpressionType.Assign:
+ return Assign(left, right);
+ case ExpressionType.AddAssign:
+ return AddAssign(left, right, method, conversion);
+ case ExpressionType.AndAssign:
+ return AndAssign(left, right, method, conversion);
+ case ExpressionType.DivideAssign:
+ return DivideAssign(left, right, method, conversion);
+ case ExpressionType.ExclusiveOrAssign:
+ return ExclusiveOrAssign(left, right, method, conversion);
+ case ExpressionType.LeftShiftAssign:
+ return LeftShiftAssign(left, right, method, conversion);
+ case ExpressionType.ModuloAssign:
+ return ModuloAssign(left, right, method, conversion);
+ case ExpressionType.MultiplyAssign:
+ return MultiplyAssign(left, right, method, conversion);
+ case ExpressionType.OrAssign:
+ return OrAssign(left, right, method, conversion);
+ case ExpressionType.PowerAssign:
+ return PowerAssign(left, right, method, conversion);
+ case ExpressionType.RightShiftAssign:
+ return RightShiftAssign(left, right, method, conversion);
+ case ExpressionType.SubtractAssign:
+ return SubtractAssign(left, right, method, conversion);
+ case ExpressionType.AddAssignChecked:
+ return AddAssignChecked(left, right, method, conversion);
+ case ExpressionType.SubtractAssignChecked:
+ return SubtractAssignChecked(left, right, method, conversion);
+ case ExpressionType.MultiplyAssignChecked:
+ return MultiplyAssignChecked(left, right, method, conversion);
+ default:
+ throw Error.UnhandledBinary(binaryType);
+ }
+ }
+
+ #region Equality Operators
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an equality comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Equal(Expression left, Expression right) {
+ return Equal(left, right, false, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an equality comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Equal(Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ return GetEqualityComparisonOperator(ExpressionType.Equal, "op_Equality", left, right, liftToNull);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Equal, left, right, method, liftToNull);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a reference equality comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Equal"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ReferenceEqual(Expression left, Expression right) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (TypeUtils.HasReferenceEquality(left.Type, right.Type)) {
+ return new LogicalBinaryExpression(ExpressionType.Equal, left, right);
+ }
+ throw Error.ReferenceEqualityNotDefined(left.Type, right.Type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an inequality comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression NotEqual(Expression left, Expression right) {
+ return NotEqual(left, right, false, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an inequality comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression NotEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ return GetEqualityComparisonOperator(ExpressionType.NotEqual, "op_Inequality", left, right, liftToNull);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.NotEqual, left, right, method, liftToNull);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a reference inequality comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.NotEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ReferenceNotEqual(Expression left, Expression right) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (TypeUtils.HasReferenceEquality(left.Type, right.Type)) {
+ return new LogicalBinaryExpression(ExpressionType.NotEqual, left, right);
+ }
+ throw Error.ReferenceEqualityNotDefined(left.Type, right.Type);
+ }
+
+ private static BinaryExpression GetEqualityComparisonOperator(ExpressionType binaryType, string opName, Expression left, Expression right, bool liftToNull) {
+ // known comparison - numeric types, bools, object, enums
+ if (left.Type == right.Type && (TypeUtils.IsNumeric(left.Type) ||
+ left.Type == typeof(object) ||
+ TypeUtils.IsBool(left.Type) ||
+ TypeUtils.GetNonNullableType(left.Type).IsEnum)) {
+ if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
+ return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
+ } else {
+ return new LogicalBinaryExpression(binaryType, left, right);
+ }
+ }
+ // look for user defined operator
+ BinaryExpression b = GetUserDefinedBinaryOperator(binaryType, opName, left, right, liftToNull);
+ if (b != null) {
+ return b;
+ }
+ if (TypeUtils.HasBuiltInEqualityOperator(left.Type, right.Type) || IsNullComparison(left, right)) {
+ if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
+ return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
+ } else {
+ return new LogicalBinaryExpression(binaryType, left, right);
+ }
+ }
+ throw Error.BinaryOperatorNotDefined(binaryType, left.Type, right.Type);
+ }
+
+ #endregion
+
+ #region Comparison Expressions
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "greater than" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThan"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression GreaterThan(Expression left, Expression right) {
+ return GreaterThan(left, right, false, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "greater than" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThan"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression GreaterThan(Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ return GetComparisonOperator(ExpressionType.GreaterThan, "op_GreaterThan", left, right, liftToNull);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.GreaterThan, left, right, method, liftToNull);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "less than" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThan"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+
+ public static BinaryExpression LessThan(Expression left, Expression right) {
+ return LessThan(left, right, false, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "less than" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThan"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression LessThan(Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ return GetComparisonOperator(ExpressionType.LessThan, "op_LessThan", left, right, liftToNull);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.LessThan, left, right, method, liftToNull);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "greater than or equal" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThanOrEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression GreaterThanOrEqual(Expression left, Expression right) {
+ return GreaterThanOrEqual(left, right, false, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "greater than or equal" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.GreaterThanOrEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression GreaterThanOrEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ return GetComparisonOperator(ExpressionType.GreaterThanOrEqual, "op_GreaterThanOrEqual", left, right, liftToNull);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.GreaterThanOrEqual, left, right, method, liftToNull);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "less than or equal" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThanOrEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression LessThanOrEqual(Expression left, Expression right) {
+ return LessThanOrEqual(left, right, false, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a "less than or equal" numeric comparison.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="liftToNull">true to set IsLiftedToNull to true; false to set IsLiftedToNull to false.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LessThanOrEqual"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.IsLiftedToNull"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression LessThanOrEqual(Expression left, Expression right, bool liftToNull, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ return GetComparisonOperator(ExpressionType.LessThanOrEqual, "op_LessThanOrEqual", left, right, liftToNull);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.LessThanOrEqual, left, right, method, liftToNull);
+ }
+
+
+ private static BinaryExpression GetComparisonOperator(ExpressionType binaryType, string opName, Expression left, Expression right, bool liftToNull) {
+ if (left.Type == right.Type && TypeUtils.IsNumeric(left.Type)) {
+ if (TypeUtils.IsNullableType(left.Type) && liftToNull) {
+ return new SimpleBinaryExpression(binaryType, left, right, typeof(bool?));
+ } else {
+ return new LogicalBinaryExpression(binaryType, left, right);
+ }
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(binaryType, opName, left, right, liftToNull);
+ }
+
+ #endregion
+
+ #region Boolean Expressions
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a conditional AND operation that evaluates the second operand only if it has to.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAlso"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression AndAlso(Expression left, Expression right) {
+ return AndAlso(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a conditional AND operation that evaluates the second operand only if it has to.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAlso"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AndAlso(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ Type returnType;
+ if (method == null) {
+ if (left.Type == right.Type) {
+ if (left.Type == typeof(bool)) {
+ return new LogicalBinaryExpression(ExpressionType.AndAlso, left, right);
+ } else if (left.Type == typeof(bool?)) {
+ return new SimpleBinaryExpression(ExpressionType.AndAlso, left, right, left.Type);
+ }
+ }
+ method = GetUserDefinedBinaryOperator(ExpressionType.AndAlso, left.Type, right.Type, "op_BitwiseAnd");
+ if (method != null) {
+ ValidateUserDefinedConditionalLogicOperator(ExpressionType.AndAlso, left.Type, right.Type, method);
+ returnType = (TypeUtils.IsNullableType(left.Type) && TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left.Type))) ? left.Type : method.ReturnType;
+ return new MethodBinaryExpression(ExpressionType.AndAlso, left, right, returnType, method);
+ }
+ throw Error.BinaryOperatorNotDefined(ExpressionType.AndAlso, left.Type, right.Type);
+ }
+ ValidateUserDefinedConditionalLogicOperator(ExpressionType.AndAlso, left.Type, right.Type, method);
+ returnType = (TypeUtils.IsNullableType(left.Type) && TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(left.Type))) ? left.Type : method.ReturnType;
+ return new MethodBinaryExpression(ExpressionType.AndAlso, left, right, returnType, method);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a conditional OR operation that evaluates the second operand only if it has to.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrElse"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression OrElse(Expression left, Expression right) {
+ return OrElse(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a conditional OR operation that evaluates the second operand only if it has to.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrElse"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression OrElse(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ Type returnType;
+ if (method == null) {
+ if (left.Type == right.Type) {
+ if (left.Type == typeof(bool)) {
+ return new LogicalBinaryExpression(ExpressionType.OrElse, left, right);
+ } else if (left.Type == typeof(bool?)) {
+ return new SimpleBinaryExpression(ExpressionType.OrElse, left, right, left.Type);
+ }
+ }
+ method = GetUserDefinedBinaryOperator(ExpressionType.OrElse, left.Type, right.Type, "op_BitwiseOr");
+ if (method != null) {
+ ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.Type, right.Type, method);
+ returnType = (TypeUtils.IsNullableType(left.Type) && method.ReturnType == TypeUtils.GetNonNullableType(left.Type)) ? left.Type : method.ReturnType;
+ return new MethodBinaryExpression(ExpressionType.OrElse, left, right, returnType, method);
+ }
+ throw Error.BinaryOperatorNotDefined(ExpressionType.OrElse, left.Type, right.Type);
+ }
+ ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.Type, right.Type, method);
+ returnType = (TypeUtils.IsNullableType(left.Type) && method.ReturnType == TypeUtils.GetNonNullableType(left.Type)) ? left.Type : method.ReturnType;
+ return new MethodBinaryExpression(ExpressionType.OrElse, left, right, returnType, method);
+ }
+
+ #endregion
+
+ #region Coalescing Expressions
+
+
+ /// <summary>
+ /// Creates a BinaryExpression that represents a coalescing operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A BinaryExpression that has the NodeType property equal to Coalesce and the Left and Right properties set to the specified values.</returns>
+ public static BinaryExpression Coalesce(Expression left, Expression right) {
+ return Coalesce(left, right, null);
+ }
+
+
+ /// <summary>
+ /// Creates a BinaryExpression that represents a coalescing operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="conversion">A LambdaExpression to set the Conversion property equal to.</param>
+ /// <returns>A BinaryExpression that has the NodeType property equal to Coalesce and the Left, Right and Conversion properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Coalesce(Expression left, Expression right, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+
+ if (conversion == null) {
+ Type resultType = ValidateCoalesceArgTypes(left.Type, right.Type);
+ return new SimpleBinaryExpression(ExpressionType.Coalesce, left, right, resultType);
+ }
+
+ if (left.Type.IsValueType && !TypeUtils.IsNullableType(left.Type)) {
+ throw Error.CoalesceUsedOnNonNullType();
+ }
+
+ Type delegateType = conversion.Type;
+ Debug.Assert(typeof(System.Delegate).IsAssignableFrom(delegateType) && delegateType != typeof(System.Delegate));
+ MethodInfo method = delegateType.GetMethod("Invoke");
+ if (method.ReturnType == typeof(void)) {
+ throw Error.UserDefinedOperatorMustNotBeVoid(conversion);
+ }
+ ParameterInfo[] pms = method.GetParametersCached();
+ Debug.Assert(pms.Length == conversion.Parameters.Count);
+ if (pms.Length != 1) {
+ throw Error.IncorrectNumberOfMethodCallArguments(conversion);
+ }
+ // The return type must match exactly.
+ // CONSIDER: We could weaken this restriction and
+ // CONSIDER: say that the return type must be assignable to from
+ // CONSIDER: the return type of the lambda.
+ if (!TypeUtils.AreEquivalent(method.ReturnType, right.Type)) {
+ throw Error.OperandTypesDoNotMatchParameters(ExpressionType.Coalesce, conversion.ToString());
+ }
+ // The parameter of the conversion lambda must either be assignable
+ // from the erased or unerased type of the left hand side.
+ if (!ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
+ !ParameterIsAssignable(pms[0], left.Type)) {
+ throw Error.OperandTypesDoNotMatchParameters(ExpressionType.Coalesce, conversion.ToString());
+ }
+ return new CoalesceConversionBinaryExpression(left, right, conversion);
+ }
+
+
+ private static Type ValidateCoalesceArgTypes(Type left, Type right) {
+ Type leftStripped = TypeUtils.GetNonNullableType(left);
+ if (left.IsValueType && !TypeUtils.IsNullableType(left)) {
+ throw Error.CoalesceUsedOnNonNullType();
+ } else if (TypeUtils.IsNullableType(left) && TypeUtils.IsImplicitlyConvertible(right, leftStripped)) {
+ return leftStripped;
+ } else if (TypeUtils.IsImplicitlyConvertible(right, left)) {
+ return left;
+ } else if (TypeUtils.IsImplicitlyConvertible(leftStripped, right)) {
+ return right;
+ } else {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ }
+
+
+
+ #endregion
+
+ #region Arithmetic Expressions
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Add"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Add(Expression left, Expression right) {
+ return Add(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Add"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Add(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.Add, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Add, "op_Addition", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Add, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression AddAssign(Expression left, Expression right) {
+ return AddAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AddAssign(Expression left, Expression right, MethodInfo method) {
+ return AddAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+
+ public static BinaryExpression AddAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.AddAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AddAssign, "op_Addition", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.AddAssign, left, right, method, conversion, true);
+ }
+
+ private static void ValidateOpAssignConversionLambda(LambdaExpression conversion, Expression left, MethodInfo method, ExpressionType nodeType) {
+ Type delegateType = conversion.Type;
+ Debug.Assert(typeof(System.Delegate).IsAssignableFrom(delegateType) && delegateType != typeof(System.Delegate));
+ MethodInfo mi = delegateType.GetMethod("Invoke");
+ ParameterInfo[] pms = mi.GetParametersCached();
+ Debug.Assert(pms.Length == conversion.Parameters.Count);
+ if (pms.Length != 1) {
+ throw Error.IncorrectNumberOfMethodCallArguments(conversion);
+ }
+ if (!TypeUtils.AreEquivalent(mi.ReturnType, left.Type)) {
+ throw Error.OperandTypesDoNotMatchParameters(nodeType, conversion.ToString());
+ }
+ if (method != null) {
+ // The parameter type of conversion lambda must be the same as the return type of the overload method
+ if (!TypeUtils.AreEquivalent(pms[0].ParameterType, method.ReturnType)) {
+ throw Error.OverloadOperatorTypeDoesNotMatchConversionType(nodeType, conversion.ToString());
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.AddAssignChecked"/> and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/>
+ /// properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AddAssignChecked(Expression left, Expression right) {
+ return AddAssignChecked(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AddAssignChecked(Expression left, Expression right, MethodInfo method) {
+ return AddAssignChecked(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an addition assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AddAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.AddAssignChecked, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AddAssignChecked, "op_Addition", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.AddAssignChecked, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression AddChecked(Expression left, Expression right) {
+ return AddChecked(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic addition operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AddChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AddChecked(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.AddChecked, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.AddChecked, "op_Addition", left, right, false);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.AddChecked, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Subtract"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Subtract(Expression left, Expression right) {
+ return Subtract(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Subtract"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Subtract(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.Subtract, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Subtract, "op_Subtraction", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Subtract, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression SubtractAssign(Expression left, Expression right) {
+ return SubtractAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression SubtractAssign(Expression left, Expression right, MethodInfo method) {
+ return SubtractAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression SubtractAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.SubtractAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.SubtractAssign, "op_Subtraction", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.SubtractAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression SubtractAssignChecked(Expression left, Expression right) {
+ return SubtractAssignChecked(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression SubtractAssignChecked(Expression left, Expression right, MethodInfo method) {
+ return SubtractAssignChecked(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a subtraction assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression SubtractAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.SubtractAssignChecked, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.SubtractAssignChecked, "op_Subtraction", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.SubtractAssignChecked, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression SubtractChecked(Expression left, Expression right) {
+ return SubtractChecked(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic subtraction operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.SubtractChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression SubtractChecked(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.SubtractChecked, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.SubtractChecked, "op_Subtraction", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.SubtractChecked, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic division operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Divide"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Divide(Expression left, Expression right) {
+ return Divide(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic division operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Divide"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Divide(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.Divide, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Divide, "op_Division", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Divide, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression DivideAssign(Expression left, Expression right) {
+ return DivideAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression DivideAssign(Expression left, Expression right, MethodInfo method) {
+ return DivideAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a division assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.DivideAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression DivideAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.DivideAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.DivideAssign, "op_Division", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.DivideAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic remainder operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Modulo"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Modulo(Expression left, Expression right) {
+ return Modulo(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic remainder operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Modulo"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Modulo(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.Modulo, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Modulo, "op_Modulus", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Modulo, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression ModuloAssign(Expression left, Expression right) {
+ return ModuloAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ModuloAssign(Expression left, Expression right, MethodInfo method) {
+ return ModuloAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a remainder assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ModuloAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ModuloAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.ModuloAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.ModuloAssign, "op_Modulus", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.ModuloAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Multiply"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Multiply(Expression left, Expression right) {
+ return Multiply(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Multiply"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Multiply(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.Multiply, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Multiply, "op_Multiply", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Multiply, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression MultiplyAssign(Expression left, Expression right) {
+ return MultiplyAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression MultiplyAssign(Expression left, Expression right, MethodInfo method) {
+ return MultiplyAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that does not have overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression MultiplyAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.MultiplyAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.MultiplyAssign, "op_Multiply", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.MultiplyAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right) {
+ return MultiplyAssignChecked(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right, MethodInfo method) {
+ return MultiplyAssignChecked(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a multiplication assignment operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyAssignChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression MultiplyAssignChecked(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.MultiplyAssignChecked, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.MultiplyAssignChecked, "op_Multiply", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.MultiplyAssignChecked, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression MultiplyChecked(Expression left, Expression right) {
+ return MultiplyChecked(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an arithmetic multiplication operation that has overflow checking.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.MultiplyChecked"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression MultiplyChecked(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsArithmetic(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.MultiplyChecked, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.MultiplyChecked, "op_Multiply", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.MultiplyChecked, left, right, method, true);
+ }
+
+ private static bool IsSimpleShift(Type left, Type right) {
+ return TypeUtils.IsInteger(left)
+ && TypeUtils.GetNonNullableType(right) == typeof(int);
+ }
+
+ private static Type GetResultTypeOfShift(Type left, Type right) {
+ if (!left.IsNullableType() && right.IsNullableType()) {
+ // lift the result type to Nullable<T>
+ return typeof(Nullable<>).MakeGenericType(left);
+ }
+ return left;
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise left-shift operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShift"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression LeftShift(Expression left, Expression right) {
+ return LeftShift(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise left-shift operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShift"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression LeftShift(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (IsSimpleShift(left.Type, right.Type)) {
+ Type resultType = GetResultTypeOfShift(left.Type, right.Type);
+ return new SimpleBinaryExpression(ExpressionType.LeftShift, left, right, resultType);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.LeftShift, "op_LeftShift", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.LeftShift, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression LeftShiftAssign(Expression left, Expression right) {
+ return LeftShiftAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression LeftShiftAssign(Expression left, Expression right, MethodInfo method) {
+ return LeftShiftAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise left-shift assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.LeftShiftAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression LeftShiftAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (IsSimpleShift(left.Type, right.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ Type resultType = GetResultTypeOfShift(left.Type, right.Type);
+ return new SimpleBinaryExpression(ExpressionType.LeftShiftAssign, left, right, resultType);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.LeftShiftAssign, "op_LeftShift", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.LeftShiftAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise right-shift operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShift"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression RightShift(Expression left, Expression right) {
+ return RightShift(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise right-shift operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShift"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression RightShift(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (IsSimpleShift(left.Type, right.Type)) {
+ Type resultType = GetResultTypeOfShift(left.Type, right.Type);
+ return new SimpleBinaryExpression(ExpressionType.RightShift, left, right, resultType);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.RightShift, "op_RightShift", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.RightShift, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression RightShiftAssign(Expression left, Expression right) {
+ return RightShiftAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression RightShiftAssign(Expression left, Expression right, MethodInfo method) {
+ return RightShiftAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise right-shift assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.RightShiftAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression RightShiftAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (IsSimpleShift(left.Type, right.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ Type resultType = GetResultTypeOfShift(left.Type, right.Type);
+ return new SimpleBinaryExpression(ExpressionType.RightShiftAssign, left, right, resultType);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.RightShiftAssign, "op_RightShift", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.RightShiftAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise AND operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.And"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression And(Expression left, Expression right) {
+ return And(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise AND operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.And"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression And(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.And, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.And, "op_BitwiseAnd", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.And, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression AndAssign(Expression left, Expression right) {
+ return AndAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AndAssign(Expression left, Expression right, MethodInfo method) {
+ return AndAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise AND assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.AndAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression AndAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.AndAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.AndAssign, "op_BitwiseAnd", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.AndAssign, left, right, method, conversion, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise OR operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Or"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Or(Expression left, Expression right) {
+ return Or(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents an bitwise OR operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Or"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Or(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.Or, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.Or, "op_BitwiseOr", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Or, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression OrAssign(Expression left, Expression right) {
+ return OrAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression OrAssign(Expression left, Expression right, MethodInfo method) {
+ return OrAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise OR assignment operation.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.OrAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression OrAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.OrAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.OrAssign, "op_BitwiseOr", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.OrAssign, left, right, method, conversion, true);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR operation, using op_ExclusiveOr for user-defined types.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOr"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression ExclusiveOr(Expression left, Expression right) {
+ return ExclusiveOr(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR operation, using op_ExclusiveOr for user-defined types.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOr"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ExclusiveOr(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
+ return new SimpleBinaryExpression(ExpressionType.ExclusiveOr, left, right, left.Type);
+ }
+ return GetUserDefinedBinaryOperatorOrThrow(ExpressionType.ExclusiveOr, "op_ExclusiveOr", left, right, true);
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.ExclusiveOr, left, right, method, true);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right) {
+ return ExclusiveOrAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right, MethodInfo method) {
+ return ExclusiveOrAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents a bitwise or logical XOR assignment operation, using op_ExclusiveOr for user-defined types.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.ExclusiveOrAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression ExclusiveOrAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ if (left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)) {
+ // conversion is not supported for binary ops on arithmetic types without operator overloading
+ if (conversion != null) {
+ throw Error.ConversionIsNotSupportedForArithmeticTypes();
+ }
+ return new SimpleBinaryExpression(ExpressionType.ExclusiveOrAssign, left, right, left.Type);
+ }
+ return GetUserDefinedAssignOperatorOrThrow(ExpressionType.ExclusiveOrAssign, "op_ExclusiveOr", left, right, conversion, true);
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.ExclusiveOrAssign, left, right, method, conversion, true);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents raising a number to a power.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Power"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression Power(Expression left, Expression right) {
+ return Power(left, right, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents raising a number to a power.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.Power"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression Power(Expression left, Expression right, MethodInfo method) {
+ RequiresCanRead(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ Type mathType = typeof(System.Math);
+ method = mathType.GetMethod("Pow", BindingFlags.Static | BindingFlags.Public);
+ if (method == null) {
+ throw Error.BinaryOperatorNotDefined(ExpressionType.Power, left.Type, right.Type);
+ }
+ }
+ return GetMethodBasedBinaryOperator(ExpressionType.Power, left, right, method, true);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/> and <see cref="P:BinaryExpression.Right"/> properties set to the specified values.</returns>
+ public static BinaryExpression PowerAssign(Expression left, Expression right) {
+ return PowerAssign(left, right, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, and <see cref="P:BinaryExpression.Method"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression PowerAssign(Expression left, Expression right, MethodInfo method) {
+ return PowerAssign(left, right, method, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BinaryExpression"/> that represents raising an expression to a power and assigning the result back to the expression.
+ /// </summary>
+ /// <param name="left">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Left"/> property equal to.</param>
+ /// <param name="right">An <see cref="Expression"/> to set the <see cref="P:BinaryExpression.Right"/> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"/> to set the <see cref="P:BinaryExpression.Method"/> property equal to.</param>
+ /// <param name="conversion">A <see cref="LambdaExpression"/> to set the <see cref="P:BinaryExpression.Conversion"/> property equal to.</param>
+ /// <returns>A <see cref="BinaryExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to <see cref="F:ExpressionType.PowerAssign"/>
+ /// and the <see cref="P:BinaryExpression.Left"/>, <see cref="P:BinaryExpression.Right"/>, <see cref="P:BinaryExpression.Method"/>,
+ /// and <see cref="P:BinaryExpression.Conversion"/> properties set to the specified values.
+ /// </returns>
+ public static BinaryExpression PowerAssign(Expression left, Expression right, MethodInfo method, LambdaExpression conversion) {
+ RequiresCanRead(left, "left");
+ RequiresCanWrite(left, "left");
+ RequiresCanRead(right, "right");
+ if (method == null) {
+ Type mathType = typeof(System.Math);
+ method = mathType.GetMethod("Pow", BindingFlags.Static | BindingFlags.Public);
+ if (method == null) {
+ throw Error.BinaryOperatorNotDefined(ExpressionType.PowerAssign, left.Type, right.Type);
+ }
+ }
+ return GetMethodBasedAssignOperator(ExpressionType.PowerAssign, left, right, method, conversion, true);
+ }
+
+ #endregion
+
+ #region ArrayIndex Expression
+
+
+ /// <summary>
+ /// Creates a BinaryExpression that represents applying an array index operator to an array of rank one.
+ /// </summary>
+ /// <param name="array">An Expression to set the Left property equal to.</param>
+ /// <param name="index">An Expression to set the Right property equal to.</param>
+ /// <returns>A BinaryExpression that has the NodeType property equal to ArrayIndex and the Left and Right properties set to the specified values.</returns>
+ public static BinaryExpression ArrayIndex(Expression array, Expression index) {
+ RequiresCanRead(array, "array");
+ RequiresCanRead(index, "index");
+ if (index.Type != typeof(int)) {
+ throw Error.ArgumentMustBeArrayIndexType();
+ }
+
+ Type arrayType = array.Type;
+ if (!arrayType.IsArray) {
+ throw Error.ArgumentMustBeArray();
+ }
+ if (arrayType.GetArrayRank() != 1) {
+ throw Error.IncorrectNumberOfIndexes();
+ }
+
+ return new SimpleBinaryExpression(ExpressionType.ArrayIndex, array, index, arrayType.GetElementType());
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BlockExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BlockExpression.cs
new file mode 100644
index 00000000000..430eda70891
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/BlockExpression.cs
@@ -0,0 +1,801 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Threading;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a block that contains a sequence of expressions where variables can be defined.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.BlockExpressionProxy))]
+#endif
+ public class BlockExpression : Expression {
+ /// <summary>
+ /// Gets the expressions in this block.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Expressions {
+ get { return GetOrMakeExpressions(); }
+ }
+
+ /// <summary>
+ /// Gets the variables defined in this block.
+ /// </summary>
+ public ReadOnlyCollection<ParameterExpression> Variables {
+ get {
+ return GetOrMakeVariables();
+ }
+ }
+
+ /// <summary>
+ /// Gets the last expression in this block.
+ /// </summary>
+ public Expression Result {
+ get {
+ Debug.Assert(ExpressionCount > 0);
+ return GetExpression(ExpressionCount - 1);
+ }
+ }
+
+ internal BlockExpression() {
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitBlock(this);
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Block; }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public override Type Type {
+ get { return GetExpression(ExpressionCount - 1).Type; }
+ }
+
+ internal virtual Expression GetExpression(int index) {
+ throw ContractUtils.Unreachable;
+ }
+
+ internal virtual int ExpressionCount {
+ get {
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ internal virtual ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ throw ContractUtils.Unreachable;
+ }
+
+ internal virtual ParameterExpression GetVariable(int index) {
+ throw ContractUtils.Unreachable;
+ }
+
+ internal virtual int VariableCount {
+ get {
+ return 0;
+ }
+ }
+
+ internal virtual ReadOnlyCollection<ParameterExpression> GetOrMakeVariables() {
+ return EmptyReadOnlyCollection<ParameterExpression>.Instance;
+ }
+
+ /// <summary>
+ /// Makes a copy of this node replacing the parameters/args with the provided values. The
+ /// shape of the parameters/args needs to match the shape of the current block - in other
+ /// words there should be the same # of parameters and args.
+ ///
+ /// parameters can be null in which case the existing parameters are used.
+ ///
+ /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
+ /// subclass of BlockExpression which is being used.
+ /// </summary>
+ internal virtual BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ throw ContractUtils.Unreachable;
+ }
+
+ /// <summary>
+ /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
+ ///
+ /// This is similar to the ReturnReadOnly which only takes a single argument. This version
+ /// supports nodes which hold onto 5 Expressions and puts all of the arguments into the
+ /// ReadOnlyCollection.
+ ///
+ /// Ultimately this means if we create the readonly collection we will be slightly more wasteful as we'll
+ /// have a readonly collection + some fields in the type. The DLR internally avoids accessing anything
+ /// which would force the readonly collection to be created.
+ ///
+ /// This is used by BlockExpression5 and MethodCallExpression5.
+ /// </summary>
+ internal static ReadOnlyCollection<Expression> ReturnReadOnlyExpressions(BlockExpression provider, ref object collection) {
+ Expression tObj = collection as Expression;
+ if (tObj != null) {
+ // otherwise make sure only one readonly collection ever gets exposed
+ Interlocked.CompareExchange(
+ ref collection,
+ new ReadOnlyCollection<Expression>(new BlockExpressionList(provider, tObj)),
+ tObj
+ );
+ }
+
+ // and return what is not guaranteed to be a readonly collection
+ return (ReadOnlyCollection<Expression>)collection;
+ }
+ }
+
+ #region Specialized Subclasses
+
+ internal sealed class Block2 : BlockExpression {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1; // storage for the 2nd argument.
+
+ internal Block2(Expression arg0, Expression arg1) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ }
+
+ internal override Expression GetExpression(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return 2;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnlyExpressions(this, ref _arg0);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == 2);
+ Debug.Assert(variables == null || variables.Count == 0);
+
+ return new Block2(args[0], args[1]);
+ }
+ }
+
+ internal sealed class Block3 : BlockExpression {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2; // storage for the 2nd and 3rd arguments.
+
+ internal Block3(Expression arg0, Expression arg1, Expression arg2) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ }
+
+ internal override Expression GetExpression(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return 3;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnlyExpressions(this, ref _arg0);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == 3);
+ Debug.Assert(variables == null || variables.Count == 0);
+
+ return new Block3(args[0], args[1], args[2]);
+ }
+ }
+
+ internal sealed class Block4 : BlockExpression {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2, _arg3; // storarg for the 2nd, 3rd, and 4th arguments.
+
+ internal Block4(Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ _arg3 = arg3;
+ }
+
+ internal override Expression GetExpression(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ case 3: return _arg3;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return 4;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnlyExpressions(this, ref _arg0);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == 4);
+ Debug.Assert(variables == null || variables.Count == 0);
+
+ return new Block4(args[0], args[1], args[2], args[3]);
+ }
+ }
+
+ internal sealed class Block5 : BlockExpression {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2, _arg3, _arg4; // storage for the 2nd - 5th args.
+
+ internal Block5(Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ _arg3 = arg3;
+ _arg4 = arg4;
+ }
+
+ internal override Expression GetExpression(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ case 3: return _arg3;
+ case 4: return _arg4;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return 5;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnlyExpressions(this, ref _arg0);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == 5);
+ Debug.Assert(variables == null || variables.Count == 0);
+
+ return new Block5(args[0], args[1], args[2], args[3], args[4]);
+ }
+ }
+
+ internal class BlockN : BlockExpression {
+ private IList<Expression> _expressions; // either the original IList<Expression> or a ReadOnlyCollection if the user has accessed it.
+
+ internal BlockN(IList<Expression> expressions) {
+ Debug.Assert(expressions.Count != 0);
+
+ _expressions = expressions;
+ }
+
+ internal override Expression GetExpression(int index) {
+ Debug.Assert(index >= 0 && index < _expressions.Count);
+
+ return _expressions[index];
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return _expressions.Count;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnly(ref _expressions);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(variables == null || variables.Count == 0);
+
+ return new BlockN(args);
+ }
+ }
+
+ internal class ScopeExpression : BlockExpression {
+ private IList<ParameterExpression> _variables; // list of variables or ReadOnlyCollection if the user has accessed the readonly collection
+
+ internal ScopeExpression(IList<ParameterExpression> variables) {
+ _variables = variables;
+ }
+
+ internal override int VariableCount {
+ get {
+ return _variables.Count;
+ }
+ }
+
+ internal override ParameterExpression GetVariable(int index) {
+ return _variables[index];
+ }
+
+ internal override ReadOnlyCollection<ParameterExpression> GetOrMakeVariables() {
+ return ReturnReadOnly(ref _variables);
+ }
+
+ protected IList<ParameterExpression> VariablesList {
+ get {
+ return _variables;
+ }
+ }
+
+ // Used for rewrite of the nodes to either reuse existing set of variables if not rewritten.
+ internal IList<ParameterExpression> ReuseOrValidateVariables(ReadOnlyCollection<ParameterExpression> variables) {
+ if (variables != null && variables != VariablesList) {
+ // Need to validate the new variables (uniqueness, not byref)
+ ValidateVariables(variables, "variables");
+ return variables;
+ } else {
+ return VariablesList;
+ }
+ }
+ }
+
+ internal sealed class Scope1 : ScopeExpression {
+ private object _body;
+
+ internal Scope1(IList<ParameterExpression> variables, Expression body)
+ : base(variables) {
+ _body = body;
+ }
+
+ internal override Expression GetExpression(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_body);
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return 1;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnlyExpressions(this, ref _body);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == 1);
+ Debug.Assert(variables == null || variables.Count == VariableCount);
+
+ return new Scope1(ReuseOrValidateVariables(variables), args[0]);
+ }
+ }
+
+ internal class ScopeN : ScopeExpression {
+ private IList<Expression> _body;
+
+ internal ScopeN(IList<ParameterExpression> variables, IList<Expression> body)
+ : base(variables) {
+ _body = body;
+ }
+
+ internal override Expression GetExpression(int index) {
+ return _body[index];
+ }
+
+ internal override int ExpressionCount {
+ get {
+ return _body.Count;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeExpressions() {
+ return ReturnReadOnly(ref _body);
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == ExpressionCount);
+ Debug.Assert(variables == null || variables.Count == VariableCount);
+
+ return new ScopeN(ReuseOrValidateVariables(variables), args);
+ }
+ }
+
+ internal class ScopeWithType : ScopeN {
+ private readonly Type _type;
+
+ internal ScopeWithType(IList<ParameterExpression> variables, IList<Expression> expressions, Type type)
+ : base(variables, expressions) {
+ _type = type;
+ }
+
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ Debug.Assert(args.Length == ExpressionCount);
+ Debug.Assert(variables == null || variables.Count == VariableCount);
+
+ return new ScopeWithType(ReuseOrValidateVariables(variables), args, _type);
+ }
+ }
+
+ #endregion
+
+ #region Block List Classes
+
+ /// <summary>
+ /// Provides a wrapper around an IArgumentProvider which exposes the argument providers
+ /// members out as an IList of Expression. This is used to avoid allocating an array
+ /// which needs to be stored inside of a ReadOnlyCollection. Instead this type has
+ /// the same amount of overhead as an array without duplicating the storage of the
+ /// elements. This ensures that internally we can avoid creating and copying arrays
+ /// while users of the Expression trees also don't pay a size penalty for this internal
+ /// optimization. See IArgumentProvider for more general information on the Expression
+ /// tree optimizations being used here.
+ /// </summary>
+ internal class BlockExpressionList : IList<Expression> {
+ private readonly BlockExpression _block;
+ private readonly Expression _arg0;
+
+ internal BlockExpressionList(BlockExpression provider, Expression arg0) {
+ _block = provider;
+ _arg0 = arg0;
+ }
+
+ #region IList<Expression> Members
+
+ public int IndexOf(Expression item) {
+ if (_arg0 == item) {
+ return 0;
+ }
+
+ for (int i = 1; i < _block.ExpressionCount; i++) {
+ if (_block.GetExpression(i) == item) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public void Insert(int index, Expression item) {
+ throw ContractUtils.Unreachable;
+ }
+
+ public void RemoveAt(int index) {
+ throw ContractUtils.Unreachable;
+ }
+
+ public Expression this[int index] {
+ get {
+ if (index == 0) {
+ return _arg0;
+ }
+
+ return _block.GetExpression(index);
+ }
+ set {
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ #endregion
+
+ #region ICollection<Expression> Members
+
+ public void Add(Expression item) {
+ throw ContractUtils.Unreachable;
+ }
+
+ public void Clear() {
+ throw ContractUtils.Unreachable;
+ }
+
+ public bool Contains(Expression item) {
+ return IndexOf(item) != -1;
+ }
+
+ public void CopyTo(Expression[] array, int arrayIndex) {
+ array[arrayIndex++] = _arg0;
+ for (int i = 1; i < _block.ExpressionCount; i++) {
+ array[arrayIndex++] = _block.GetExpression(i);
+ }
+ }
+
+ public int Count {
+ get { return _block.ExpressionCount; }
+ }
+
+ public bool IsReadOnly {
+ get { return true; }
+ }
+
+ public bool Remove(Expression item) {
+ throw ContractUtils.Unreachable;
+ }
+
+ #endregion
+
+ #region IEnumerable<Expression> Members
+
+ public IEnumerator<Expression> GetEnumerator() {
+ yield return _arg0;
+
+ for (int i = 1; i < _block.ExpressionCount; i++) {
+ yield return _block.GetExpression(i);
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ yield return _arg0;
+
+ for (int i = 1; i < _block.ExpressionCount; i++) {
+ yield return _block.GetExpression(i);
+ }
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains two expressions and has no variables.
+ /// </summary>
+ /// <param name="arg0">The first expression in the block.</param>
+ /// <param name="arg1">The second expression in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Expression arg0, Expression arg1) {
+ RequiresCanRead(arg0, "arg0");
+ RequiresCanRead(arg1, "arg1");
+
+ return new Block2(arg0, arg1);
+ }
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains three expressions and has no variables.
+ /// </summary>
+ /// <param name="arg0">The first expression in the block.</param>
+ /// <param name="arg1">The second expression in the block.</param>
+ /// <param name="arg2">The third expression in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2) {
+ RequiresCanRead(arg0, "arg0");
+ RequiresCanRead(arg1, "arg1");
+ RequiresCanRead(arg2, "arg2");
+ return new Block3(arg0, arg1, arg2);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains four expressions and has no variables.
+ /// </summary>
+ /// <param name="arg0">The first expression in the block.</param>
+ /// <param name="arg1">The second expression in the block.</param>
+ /// <param name="arg2">The third expression in the block.</param>
+ /// <param name="arg3">The fourth expression in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
+ RequiresCanRead(arg0, "arg0");
+ RequiresCanRead(arg1, "arg1");
+ RequiresCanRead(arg2, "arg2");
+ RequiresCanRead(arg3, "arg3");
+ return new Block4(arg0, arg1, arg2, arg3);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains five expressions and has no variables.
+ /// </summary>
+ /// <param name="arg0">The first expression in the block.</param>
+ /// <param name="arg1">The second expression in the block.</param>
+ /// <param name="arg2">The third expression in the block.</param>
+ /// <param name="arg3">The fourth expression in the block.</param>
+ /// <param name="arg4">The fifth expression in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) {
+ RequiresCanRead(arg0, "arg0");
+ RequiresCanRead(arg1, "arg1");
+ RequiresCanRead(arg2, "arg2");
+ RequiresCanRead(arg3, "arg3");
+ RequiresCanRead(arg4, "arg4");
+
+ return new Block5(arg0, arg1, arg2, arg3, arg4);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given expressions and has no variables.
+ /// </summary>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(params Expression[] expressions) {
+ ContractUtils.RequiresNotNull(expressions, "expressions");
+
+ switch (expressions.Length) {
+ case 2: return Block(expressions[0], expressions[1]);
+ case 3: return Block(expressions[0], expressions[1], expressions[2]);
+ case 4: return Block(expressions[0], expressions[1], expressions[2], expressions[3]);
+ case 5: return Block(expressions[0], expressions[1], expressions[2], expressions[3], expressions[4]);
+ default:
+ ContractUtils.RequiresNotEmpty(expressions, "expressions");
+ RequiresCanRead(expressions, "expressions");
+ return new BlockN(expressions.Copy());
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given expressions and has no variables.
+ /// </summary>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(IEnumerable<Expression> expressions) {
+ return Block(EmptyReadOnlyCollection<ParameterExpression>.Instance, expressions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given expressions, has no variables and has specific result type.
+ /// </summary>
+ /// <param name="type">The result type of the block.</param>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Type type, params Expression[] expressions) {
+ ContractUtils.RequiresNotNull(expressions, "expressions");
+ return Block(type, (IEnumerable<Expression>)expressions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given expressions, has no variables and has specific result type.
+ /// </summary>
+ /// <param name="type">The result type of the block.</param>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Type type, IEnumerable<Expression> expressions) {
+ return Block(type, EmptyReadOnlyCollection<ParameterExpression>.Instance, expressions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given variables and expressions.
+ /// </summary>
+ /// <param name="variables">The variables in the block.</param>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(IEnumerable<ParameterExpression> variables, params Expression[] expressions) {
+ return Block(variables, (IEnumerable<Expression>)expressions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given variables and expressions.
+ /// </summary>
+ /// <param name="type">The result type of the block.</param>
+ /// <param name="variables">The variables in the block.</param>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Type type, IEnumerable<ParameterExpression> variables, params Expression[] expressions) {
+ return Block(type, variables, (IEnumerable<Expression>)expressions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given variables and expressions.
+ /// </summary>
+ /// <param name="variables">The variables in the block.</param>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(IEnumerable<ParameterExpression> variables, IEnumerable<Expression> expressions) {
+ ContractUtils.RequiresNotNull(expressions, "expressions");
+ var expressionList = expressions.ToReadOnly();
+ ContractUtils.RequiresNotEmpty(expressionList, "expressions");
+ RequiresCanRead(expressionList, "expressions");
+
+ return Block(expressionList.Last().Type, variables, expressionList);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="BlockExpression"/> that contains the given variables and expressions.
+ /// </summary>
+ /// <param name="type">The result type of the block.</param>
+ /// <param name="variables">The variables in the block.</param>
+ /// <param name="expressions">The expressions in the block.</param>
+ /// <returns>The created <see cref="BlockExpression"/>.</returns>
+ public static BlockExpression Block(Type type, IEnumerable<ParameterExpression> variables, IEnumerable<Expression> expressions) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(expressions, "expressions");
+
+ var expressionList = expressions.ToReadOnly();
+ var variableList = variables.ToReadOnly();
+
+ ContractUtils.RequiresNotEmpty(expressionList, "expressions");
+ RequiresCanRead(expressionList, "expressions");
+ ValidateVariables(variableList, "variables");
+
+ Expression last = expressionList.Last();
+ if (type != typeof(void)) {
+ if (!TypeUtils.AreReferenceAssignable(type, last.Type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ }
+
+ if (!TypeUtils.AreEquivalent(type, last.Type)) {
+ return new ScopeWithType(variableList, expressionList, type);
+ } else {
+ if (expressionList.Count == 1) {
+ return new Scope1(variableList, expressionList[0]);
+ } else {
+ return new ScopeN(variableList, expressionList);
+ }
+ }
+ }
+
+ // Checks that all variables are non-null, not byref, and unique.
+ internal static void ValidateVariables(ReadOnlyCollection<ParameterExpression> varList, string collectionName) {
+ if (varList.Count == 0) {
+ return;
+ }
+
+ int count = varList.Count;
+ var set = new Set<ParameterExpression>(count);
+ for (int i = 0; i < count; i++) {
+ ParameterExpression v = varList[i];
+ if (v == null) {
+ throw new ArgumentNullException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0}[{1}]", collectionName, set.Count));
+ }
+ if (v.IsByRef) {
+ throw Error.VariableMustNotBeByRef(v, v.Type);
+ }
+ if (set.Contains(v)) {
+ throw Error.DuplicateVariable(v);
+ }
+ set.Add(v);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/CatchBlock.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/CatchBlock.cs
new file mode 100644
index 00000000000..f2698e54764
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/CatchBlock.cs
@@ -0,0 +1,163 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents a catch statement in a try block.
+ /// This must have the same return type (i.e., the type of <see cref="P:CatchBlock.Body"/>) as the try block it is associated with.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.CatchBlockProxy))]
+#endif
+ public sealed class CatchBlock {
+ private readonly Type _test;
+ private readonly ParameterExpression _var;
+ private readonly Expression _body;
+ private readonly Expression _filter;
+
+ internal CatchBlock(Type test, ParameterExpression variable, Expression body, Expression filter) {
+ _test = test;
+ _var = variable;
+ _body = body;
+ _filter = filter;
+ }
+
+ /// <summary>
+ /// Gets a reference to the <see cref="Exception"/> object caught by this handler.
+ /// </summary>
+ public ParameterExpression Variable {
+ get { return _var; }
+ }
+
+ /// <summary>
+ /// Gets the type of <see cref="Exception"/> this handler catches.
+ /// </summary>
+ public Type Test {
+ get { return _test; }
+ }
+
+ /// <summary>
+ /// Gets the body of the catch block.
+ /// </summary>
+ public Expression Body {
+ get { return _body; }
+ }
+
+ /// <summary>
+ /// Gets the body of the <see cref="CatchBlock"/>'s filter.
+ /// </summary>
+ public Expression Filter {
+ get {
+ return _filter;
+ }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="String"/> that represents the current <see cref="Object"/>.
+ /// </summary>
+ /// <returns>A <see cref="String"/> that represents the current <see cref="Object"/>. </returns>
+ public override string ToString() {
+ return ExpressionStringBuilder.CatchBlockToString(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="CatchBlock"/> representing a catch statement.
+ /// The <see cref="Type"/> of object to be caught can be specified but no reference to the object
+ /// will be available for use in the <see cref="CatchBlock"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
+ /// <param name="body">The body of the catch statement.</param>
+ /// <returns>The created <see cref="CatchBlock"/>.</returns>
+ public static CatchBlock Catch(Type type, Expression body) {
+ return MakeCatchBlock(type, null, body, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="CatchBlock"/> representing a catch statement with a reference to the caught object for use in the handler body.
+ /// </summary>
+ /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
+ /// <param name="body">The body of the catch statement.</param>
+ /// <returns>The created <see cref="CatchBlock"/>.</returns>
+ public static CatchBlock Catch(ParameterExpression variable, Expression body) {
+ ContractUtils.RequiresNotNull(variable, "variable");
+ return MakeCatchBlock(variable.Type, variable, body, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="CatchBlock"/> representing a catch statement with
+ /// an <see cref="Exception"/> filter but no reference to the caught <see cref="Exception"/> object.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
+ /// <param name="body">The body of the catch statement.</param>
+ /// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
+ /// <returns>The created <see cref="CatchBlock"/>.</returns>
+ public static CatchBlock Catch(Type type, Expression body, Expression filter) {
+ return MakeCatchBlock(type, null, body, filter);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="CatchBlock"/> representing a catch statement with
+ /// an <see cref="Exception"/> filter and a reference to the caught <see cref="Exception"/> object.
+ /// </summary>
+ /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
+ /// <param name="body">The body of the catch statement.</param>
+ /// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
+ /// <returns>The created <see cref="CatchBlock"/>.</returns>
+ public static CatchBlock Catch(ParameterExpression variable, Expression body, Expression filter) {
+ ContractUtils.RequiresNotNull(variable, "variable");
+ return MakeCatchBlock(variable.Type, variable, body, filter);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="CatchBlock"/> representing a catch statement with the specified elements.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
+ /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
+ /// <param name="body">The body of the catch statement.</param>
+ /// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
+ /// <returns>The created <see cref="CatchBlock"/>.</returns>
+ /// <remarks><paramref name="type"/> must be non-null and match the type of <paramref name="variable"/> (if it is supplied).</remarks>
+ public static CatchBlock MakeCatchBlock(Type type, ParameterExpression variable, Expression body, Expression filter) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.Requires(variable == null || TypeUtils.AreEquivalent(variable.Type, type), "variable");
+ if (variable != null && variable.IsByRef) {
+ throw Error.VariableMustNotBeByRef(variable, variable.Type);
+ }
+ RequiresCanRead(body, "body");
+ if (filter != null) {
+ RequiresCanRead(filter, "filter");
+ ContractUtils.Requires(filter.Type == typeof(bool), Strings.ArgumentMustBeBoolean);
+ }
+
+ return new CatchBlock(type, variable, body, filter);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConditionalExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConditionalExpression.cs
new file mode 100644
index 00000000000..d7d0cf0a33f
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConditionalExpression.cs
@@ -0,0 +1,214 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents an expression that has a conditional operator.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.ConditionalExpressionProxy))]
+#endif
+ public class ConditionalExpression : Expression {
+ private readonly Expression _test;
+ private readonly Expression _true;
+
+ internal ConditionalExpression(Expression test, Expression ifTrue) {
+ _test = test;
+ _true = ifTrue;
+ }
+
+ internal static ConditionalExpression Make(Expression test, Expression ifTrue, Expression ifFalse, Type type) {
+ if (ifTrue.Type != type || ifFalse.Type != type) {
+ return new FullConditionalExpressionWithType(test, ifTrue, ifFalse, type);
+ } if (ifFalse is DefaultExpression && ifFalse.Type == typeof(void)) {
+ return new ConditionalExpression(test, ifTrue);
+ } else {
+ return new FullConditionalExpression(test, ifTrue, ifFalse);
+ }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Conditional; }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public override Type Type {
+ get { return IfTrue.Type; }
+ }
+
+ /// <summary>
+ /// Gets the test of the conditional operation.
+ /// </summary>
+ public Expression Test {
+ get { return _test; }
+ }
+ /// <summary>
+ /// Gets the expression to execute if the test evaluates to true.
+ /// </summary>
+ public Expression IfTrue {
+ get { return _true; }
+ }
+ /// <summary>
+ /// Gets the expression to execute if the test evaluates to false.
+ /// </summary>
+ public Expression IfFalse {
+ get { return GetFalse(); }
+ }
+
+ internal virtual Expression GetFalse() {
+ return Expression.Empty();
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitConditional(this);
+ }
+ }
+
+ internal class FullConditionalExpression : ConditionalExpression {
+ private readonly Expression _false;
+
+ internal FullConditionalExpression(Expression test, Expression ifTrue, Expression ifFalse)
+ : base(test, ifTrue) {
+ _false = ifFalse;
+ }
+
+ internal override Expression GetFalse() {
+ return _false;
+ }
+ }
+
+ internal class FullConditionalExpressionWithType : FullConditionalExpression {
+ private readonly Type _type;
+
+ internal FullConditionalExpressionWithType(Expression test, Expression ifTrue, Expression ifFalse, Type type)
+ : base(test, ifTrue, ifFalse) {
+ _type = type;
+ }
+
+ public sealed override Type Type {
+ get { return _type; }
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a <see cref="ConditionalExpression"/>.
+ /// </summary>
+ /// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
+ /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
+ /// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param>
+ /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
+ /// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values.</returns>
+ public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse) {
+ RequiresCanRead(test, "test");
+ RequiresCanRead(ifTrue, "ifTrue");
+ RequiresCanRead(ifFalse, "ifFalse");
+
+ if (test.Type != typeof(bool)) {
+ throw Error.ArgumentMustBeBoolean();
+ }
+ if (!TypeUtils.AreEquivalent(ifTrue.Type, ifFalse.Type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+
+ return ConditionalExpression.Make(test, ifTrue, ifFalse, ifTrue.Type);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="ConditionalExpression"/>.
+ /// </summary>
+ /// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
+ /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
+ /// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param>
+ /// <param name="type">A <see cref="Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
+ /// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values.</returns>
+ /// <remarks>This method allows explicitly unifying the result type of the conditional expression in cases where the types of <paramref name="ifTrue"/>
+ /// and <paramref name="ifFalse"/> expressions are not equal. Types of both <paramref name="ifTrue"/> and <paramref name="ifFalse"/> must be implicitly
+ /// reference assignable to the result type. The <paramref name="type"/> is allowed to be <see cref="System.Void"/>.</remarks>
+ public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse, Type type) {
+ RequiresCanRead(test, "test");
+ RequiresCanRead(ifTrue, "ifTrue");
+ RequiresCanRead(ifFalse, "ifFalse");
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (test.Type != typeof(bool)) {
+ throw Error.ArgumentMustBeBoolean();
+ }
+
+ if (type != typeof(void)) {
+ if (!TypeUtils.AreReferenceAssignable(type, ifTrue.Type) ||
+ !TypeUtils.AreReferenceAssignable(type, ifFalse.Type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ }
+
+ return ConditionalExpression.Make(test, ifTrue, ifFalse, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ConditionalExpression"/>.
+ /// </summary>
+ /// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
+ /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
+ /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
+ /// properties set to the specified values. The <see cref="P:ConditionalExpression.IfFalse"/> property is set to default expression and
+ /// the type of the resulting <see cref="ConditionalExpression"/> returned by this method is <see cref="System.Void"/>.</returns>
+ public static ConditionalExpression IfThen(Expression test, Expression ifTrue) {
+ return Condition(test, ifTrue, Expression.Empty(), typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ConditionalExpression"/>.
+ /// </summary>
+ /// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
+ /// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
+ /// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param>
+ /// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
+ /// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values. The type of the resulting <see cref="ConditionalExpression"/>
+ /// returned by this method is <see cref="System.Void"/>.</returns>
+ public static ConditionalExpression IfThenElse(Expression test, Expression ifTrue, Expression ifFalse) {
+ return Condition(test, ifTrue, ifFalse, typeof(void));
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConstantExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConstantExpression.cs
new file mode 100644
index 00000000000..65c89b8b4a0
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ConstantExpression.cs
@@ -0,0 +1,136 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents an expression that has a constant value.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.ConstantExpressionProxy))]
+#endif
+ public class ConstantExpression : Expression {
+ // Possible optimization: we could have a Constant<T> subclass that
+ // stores the unboxed value.
+ private readonly object _value;
+
+ internal ConstantExpression(object value) {
+ _value = value;
+ }
+
+ internal static ConstantExpression Make(object value, Type type) {
+ if ((value == null && type == typeof(object)) || (value != null && value.GetType() == type)) {
+ return new ConstantExpression(value);
+ } else {
+ return new TypedConstantExpression(value, type);
+ }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public override Type Type {
+ get {
+ if (_value == null) {
+ return typeof(object);
+ }
+ return _value.GetType();
+ }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Constant; }
+ }
+ /// <summary>
+ /// Gets the value of the constant expression.
+ /// </summary>
+ public object Value {
+ get { return _value; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitConstant(this);
+ }
+ }
+
+ internal class TypedConstantExpression : ConstantExpression {
+ private readonly Type _type;
+
+ internal TypedConstantExpression(object value, Type type)
+ : base(value) {
+ _type = type;
+ }
+
+ public sealed override Type Type {
+ get { return _type; }
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="ConstantExpression"/> that has the <see cref="P:ConstantExpression.Value"/> property set to the specified value. .
+ /// </summary>
+ /// <param name="value">An <see cref="System.Object"/> to set the <see cref="P:ConstantExpression.Value"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="ConstantExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Constant"/> and the <see cref="P:Expression.Value"/> property set to the specified value.
+ /// </returns>
+ public static ConstantExpression Constant(object value) {
+ return ConstantExpression.Make(value, value == null ? typeof(object) : value.GetType());
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="ConstantExpression"/> that has the <see cref="P:ConstantExpression.Value"/>
+ /// and <see cref="P:ConstantExpression.Type"/> properties set to the specified values. .
+ /// </summary>
+ /// <param name="value">An <see cref="System.Object"/> to set the <see cref="P:ConstantExpression.Value"/> property equal to.</param>
+ /// <param name="type">A <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="ConstantExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Constant"/> and the <see cref="P:ConstantExpression.Value"/> and
+ /// <see cref="P:Expression.Type"/> properties set to the specified values.
+ /// </returns>
+ public static ConstantExpression Constant(object value, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+ if (value == null && type.IsValueType && !TypeUtils.IsNullableType(type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ if (value != null && !type.IsAssignableFrom(value.GetType())) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ return ConstantExpression.Make(value, type);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugInfoExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugInfoExpression.cs
new file mode 100644
index 00000000000..b0fc4c0c266
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugInfoExpression.cs
@@ -0,0 +1,247 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Emits or clears a sequence point for debug information.
+ ///
+ /// This allows the debugger to highlight the correct source code when
+ /// debugging.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.DebugInfoExpressionProxy))]
+#endif
+ public class DebugInfoExpression : Expression {
+
+ private readonly SymbolDocumentInfo _document;
+
+ internal DebugInfoExpression(SymbolDocumentInfo document) {
+ _document = document;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return typeof(void); }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.DebugInfo; }
+ }
+
+ /// <summary>
+ /// Gets the start line of this <see cref="DebugInfoExpression" />.
+ /// </summary>
+ public virtual int StartLine {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ /// <summary>
+ /// Gets the start column of this <see cref="DebugInfoExpression" />.
+ /// </summary>
+ public virtual int StartColumn {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ /// <summary>
+ /// Gets the end line of this <see cref="DebugInfoExpression" />.
+ /// </summary>
+ public virtual int EndLine {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ /// <summary>
+ /// Gets the end column of this <see cref="DebugInfoExpression" />.
+ /// </summary>
+ public virtual int EndColumn {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="SymbolDocumentInfo"/> that represents the source file.
+ /// </summary>
+ public SymbolDocumentInfo Document {
+ get { return _document; }
+ }
+
+ /// <summary>
+ /// Gets the value to indicate if the <see cref="DebugInfoExpression"/> is for clearing a sequence point.
+ /// </summary>
+ public virtual bool IsClear {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitDebugInfo(this);
+ }
+ }
+
+ #region Specialized subclasses
+
+ internal sealed class SpanDebugInfoExpression : DebugInfoExpression {
+ private readonly int _startLine, _startColumn, _endLine, _endColumn;
+
+ internal SpanDebugInfoExpression(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn)
+ : base(document) {
+ _startLine = startLine;
+ _startColumn = startColumn;
+ _endLine = endLine;
+ _endColumn = endColumn;
+ }
+
+ public override int StartLine {
+ get {
+ return _startLine;
+ }
+ }
+
+ public override int StartColumn {
+ get {
+ return _startColumn;
+ }
+ }
+
+ public override int EndLine {
+ get {
+ return _endLine;
+ }
+ }
+
+ public override int EndColumn {
+ get {
+ return _endColumn;
+ }
+ }
+
+ public override bool IsClear {
+ get {
+ return false;
+ }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitDebugInfo(this);
+ }
+ }
+
+ internal sealed class ClearDebugInfoExpression : DebugInfoExpression {
+ internal ClearDebugInfoExpression(SymbolDocumentInfo document)
+ : base(document) {
+ }
+
+ public override bool IsClear {
+ get {
+ return true;
+ }
+ }
+
+ public override int StartLine {
+ get {
+ return 0xfeefee;
+ }
+ }
+
+ public override int StartColumn {
+ get {
+ return 0;
+ }
+ }
+
+ public override int EndLine {
+ get {
+ return 0xfeefee;
+ }
+ }
+
+ public override int EndColumn {
+ get {
+ return 0;
+ }
+ }
+ }
+ #endregion
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="DebugInfoExpression"/> with the specified span.
+ /// </summary>
+ /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
+ /// <param name="startLine">The start line of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
+ /// <param name="startColumn">The start column of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
+ /// <param name="endLine">The end line of this <see cref="DebugInfoExpression" />. Must be greater or equal than the start line.</param>
+ /// <param name="endColumn">The end column of this <see cref="DebugInfoExpression" />. If the end line is the same as the start line, it must be greater or equal than the start column. In any case, must be greater than 0.</param>
+ /// <returns>An instance of <see cref="DebugInfoExpression"/>.</returns>
+ public static DebugInfoExpression DebugInfo(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn) {
+ ContractUtils.RequiresNotNull(document, "document");
+ if (startLine == 0xfeefee && startColumn == 0 && endLine == 0xfeefee && endColumn == 0) {
+ return new ClearDebugInfoExpression(document);
+ }
+
+ ValidateSpan(startLine, startColumn, endLine, endColumn);
+ return new SpanDebugInfoExpression(document, startLine, startColumn, endLine, endColumn);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DebugInfoExpression"/> for clearing a sequence point.
+ /// </summary>
+ /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
+ /// <returns>An instance of <see cref="DebugInfoExpression"/> for clearning a sequence point.</returns>
+ public static DebugInfoExpression ClearDebugInfo(SymbolDocumentInfo document) {
+ ContractUtils.RequiresNotNull(document, "document");
+
+ return new ClearDebugInfoExpression(document);
+ }
+
+ private static void ValidateSpan(int startLine, int startColumn, int endLine, int endColumn) {
+ if (startLine < 1) {
+ throw Error.OutOfRange("startLine", 1);
+ }
+ if (startColumn < 1) {
+ throw Error.OutOfRange("startColumn", 1);
+ }
+ if (endLine < 1) {
+ throw Error.OutOfRange("endLine", 1);
+ }
+ if (endColumn < 1) {
+ throw Error.OutOfRange("endColumn", 1);
+ }
+ if (startLine > endLine) {
+ throw Error.StartEndMustBeOrdered();
+ }
+ if (startLine == endLine && startColumn > endColumn) {
+ throw Error.StartEndMustBeOrdered();
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugViewWriter.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugViewWriter.cs
new file mode 100644
index 00000000000..db51b68f785
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DebugViewWriter.cs
@@ -0,0 +1,1196 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Collections.ObjectModel;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ internal sealed class DebugViewWriter : ExpressionVisitor {
+ [Flags]
+ private enum Flow {
+ None,
+ Space,
+ NewLine,
+
+ Break = 0x8000 // newline if column > MaxColumn
+ };
+
+ private const int Tab = 4;
+ private const int MaxColumn = 120;
+
+ private TextWriter _out;
+ private int _column;
+
+ private Stack<int> _stack = new Stack<int>();
+ private int _delta;
+ private Flow _flow;
+
+ // All the unique lambda expressions in the ET, will be used for displaying all
+ // the lambda definitions.
+ private Queue<LambdaExpression> _lambdas;
+
+ // Associate every unique anonymous LambdaExpression in the tree with an integer.
+ // The id is used to create a name for the anonymous lambda.
+ //
+ private Dictionary<LambdaExpression, int> _lambdaIds;
+
+ // Associate every unique anonymous parameter or variable in the tree with an integer.
+ // The id is used to create a name for the anonymous parameter or variable.
+ //
+ private Dictionary<ParameterExpression, int> _paramIds;
+
+ // Associate every unique anonymous LabelTarget in the tree with an integer.
+ // The id is used to create a name for the anonymous LabelTarget.
+ //
+ private Dictionary<LabelTarget, int> _labelIds;
+
+ private DebugViewWriter(TextWriter file) {
+ _out = file;
+ }
+
+ private int Base {
+ get {
+ return _stack.Count > 0 ? _stack.Peek() : 0;
+ }
+ }
+
+ private int Delta {
+ get { return _delta; }
+ }
+
+ private int Depth {
+ get { return Base + Delta; }
+ }
+
+ private void Indent() {
+ _delta += Tab;
+ }
+ private void Dedent() {
+ _delta -= Tab;
+ }
+
+ private void NewLine() {
+ _flow = Flow.NewLine;
+ }
+
+ private static int GetId<T>(T e, ref Dictionary<T, int> ids) {
+ if (ids == null) {
+ ids = new Dictionary<T, int>();
+ ids.Add(e, 1);
+ return 1;
+ } else {
+ int id;
+ if (!ids.TryGetValue(e, out id)) {
+ // e is met the first time
+ id = ids.Count + 1;
+ ids.Add(e, id);
+ }
+ return id;
+ }
+ }
+
+ private int GetLambdaId(LambdaExpression le) {
+ Debug.Assert(String.IsNullOrEmpty(le.Name));
+ return GetId(le, ref _lambdaIds);
+ }
+
+ private int GetParamId(ParameterExpression p) {
+ Debug.Assert(String.IsNullOrEmpty(p.Name));
+ return GetId(p, ref _paramIds);
+ }
+
+ private int GetLabelTargetId(LabelTarget target) {
+ Debug.Assert(String.IsNullOrEmpty(target.Name));
+ return GetId(target, ref _labelIds);
+ }
+
+ /// <summary>
+ /// Write out the given AST
+ /// </summary>
+ internal static void WriteTo(Expression node, TextWriter writer) {
+ Debug.Assert(node != null);
+ Debug.Assert(writer != null);
+
+ new DebugViewWriter(writer).WriteTo(node);
+ }
+
+ private void WriteTo(Expression node) {
+ var lambda = node as LambdaExpression;
+ if (lambda != null) {
+ WriteLambda(lambda);
+ } else {
+ Visit(node);
+ Debug.Assert(_stack.Count == 0);
+ }
+
+ //
+ // Output all lambda expression definitions.
+ // in the order of their appearances in the tree.
+ //
+ while (_lambdas != null && _lambdas.Count > 0) {
+ WriteLine();
+ WriteLine();
+ WriteLambda(_lambdas.Dequeue());
+ }
+ }
+
+ #region The printing code
+
+ private void Out(string s) {
+ Out(Flow.None, s, Flow.None);
+ }
+
+ private void Out(Flow before, string s) {
+ Out(before, s, Flow.None);
+ }
+
+ private void Out(string s, Flow after) {
+ Out(Flow.None, s, after);
+ }
+
+ private void Out(Flow before, string s, Flow after) {
+ switch (GetFlow(before)) {
+ case Flow.None:
+ break;
+ case Flow.Space:
+ Write(" ");
+ break;
+ case Flow.NewLine:
+ WriteLine();
+ Write(new String(' ', Depth));
+ break;
+ }
+ Write(s);
+ _flow = after;
+ }
+
+ private void WriteLine() {
+ _out.WriteLine();
+ _column = 0;
+ }
+ private void Write(string s) {
+ _out.Write(s);
+ _column += s.Length;
+ }
+
+ private Flow GetFlow(Flow flow) {
+ Flow last;
+
+ last = CheckBreak(_flow);
+ flow = CheckBreak(flow);
+
+ // Get the biggest flow that is requested None < Space < NewLine
+ return (Flow)System.Math.Max((int)last, (int)flow);
+ }
+
+ private Flow CheckBreak(Flow flow) {
+ if ((flow & Flow.Break) != 0) {
+ if (_column > (MaxColumn + Depth)) {
+ flow = Flow.NewLine;
+ } else {
+ flow &= ~Flow.Break;
+ }
+ }
+ return flow;
+ }
+
+ #endregion
+
+ #region The AST Output
+
+ // More proper would be to make this a virtual method on Action
+ private static string FormatBinder(CallSiteBinder binder) {
+ ConvertBinder convert;
+ GetMemberBinder getMember;
+ SetMemberBinder setMember;
+ DeleteMemberBinder deleteMember;
+ GetIndexBinder getIndex;
+ SetIndexBinder setIndex;
+ DeleteIndexBinder deleteIndex;
+ InvokeMemberBinder call;
+ InvokeBinder invoke;
+ CreateInstanceBinder create;
+ UnaryOperationBinder unary;
+ BinaryOperationBinder binary;
+
+ if ((convert = binder as ConvertBinder) != null) {
+ return "Convert " + convert.Type.ToString();
+ } else if ((getMember = binder as GetMemberBinder) != null) {
+ return "GetMember " + getMember.Name;
+ } else if ((setMember = binder as SetMemberBinder) != null) {
+ return "SetMember " + setMember.Name;
+ } else if ((deleteMember = binder as DeleteMemberBinder) != null) {
+ return "DeleteMember " + deleteMember.Name;
+ } else if ((getIndex = binder as GetIndexBinder) != null) {
+ return "GetIndex";
+ } else if ((setIndex = binder as SetIndexBinder) != null) {
+ return "SetIndex";
+ } else if ((deleteIndex = binder as DeleteIndexBinder) != null) {
+ return "DeleteIndex";
+ } else if ((call = binder as InvokeMemberBinder) != null) {
+ return "Call " + call.Name;
+ } else if ((invoke = binder as InvokeBinder) != null) {
+ return "Invoke";
+ } else if ((create = binder as CreateInstanceBinder) != null) {
+ return "Create";
+ } else if ((unary = binder as UnaryOperationBinder) != null) {
+ return "UnaryOperation " + unary.Operation;
+ } else if ((binary = binder as BinaryOperationBinder) != null) {
+ return "BinaryOperation " + binary.Operation;
+ } else {
+ return binder.ToString();
+ }
+ }
+
+ private void VisitExpressions<T>(char open, IList<T> expressions) where T : Expression {
+ VisitExpressions<T>(open, ',', expressions);
+ }
+
+ private void VisitExpressions<T>(char open, char separator, IList<T> expressions) where T : Expression {
+ VisitExpressions(open, separator, expressions, e => Visit(e));
+ }
+
+ private void VisitDeclarations(IList<ParameterExpression> expressions) {
+ VisitExpressions('(', ',', expressions, variable =>
+ {
+ Out(variable.Type.ToString());
+ if (variable.IsByRef) {
+ Out("&");
+ }
+ Out(" ");
+ VisitParameter(variable);
+ });
+ }
+
+ private void VisitExpressions<T>(char open, char separator, IList<T> expressions, Action<T> visit) {
+ Out(open.ToString());
+
+ if (expressions != null) {
+ Indent();
+ bool isFirst = true;
+ foreach (T e in expressions) {
+ if (isFirst) {
+ if (open == '{' || expressions.Count > 1) {
+ NewLine();
+ }
+ isFirst = false;
+ } else {
+ Out(separator.ToString(), Flow.NewLine);
+ }
+ visit(e);
+ }
+ Dedent();
+ }
+
+ char close;
+ switch (open) {
+ case '(': close = ')'; break;
+ case '{': close = '}'; break;
+ case '[': close = ']'; break;
+ case '<': close = '>'; break;
+ default: throw ContractUtils.Unreachable;
+ }
+
+ if (open == '{') {
+ NewLine();
+ }
+ Out(close.ToString(), Flow.Break);
+ }
+
+ protected internal override Expression VisitDynamic(DynamicExpression node) {
+ Out(".Dynamic", Flow.Space);
+ Out(FormatBinder(node.Binder));
+ VisitExpressions('(', node.Arguments);
+ return node;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ protected internal override Expression VisitBinary(BinaryExpression node) {
+ if (node.NodeType == ExpressionType.ArrayIndex) {
+ ParenthesizedVisit(node, node.Left);
+ Out("[");
+ Visit(node.Right);
+ Out("]");
+ } else {
+ bool parenthesizeLeft = NeedsParentheses(node, node.Left);
+ bool parenthesizeRight = NeedsParentheses(node, node.Right);
+
+ string op;
+ bool isChecked = false;
+ Flow beforeOp = Flow.Space;
+ switch (node.NodeType) {
+ case ExpressionType.Assign: op = "="; break;
+ case ExpressionType.Equal: op = "=="; break;
+ case ExpressionType.NotEqual: op = "!="; break;
+ case ExpressionType.AndAlso: op = "&&"; beforeOp = Flow.Break | Flow.Space; break;
+ case ExpressionType.OrElse: op = "||"; beforeOp = Flow.Break | Flow.Space; break;
+ case ExpressionType.GreaterThan: op = ">"; break;
+ case ExpressionType.LessThan: op = "<"; break;
+ case ExpressionType.GreaterThanOrEqual: op = ">="; break;
+ case ExpressionType.LessThanOrEqual: op = "<="; break;
+ case ExpressionType.Add: op = "+"; break;
+ case ExpressionType.AddAssign: op = "+="; break;
+ case ExpressionType.AddAssignChecked: op = "+="; isChecked = true; break;
+ case ExpressionType.AddChecked: op = "+"; isChecked = true; break;
+ case ExpressionType.Subtract: op = "-"; break;
+ case ExpressionType.SubtractAssign: op = "-="; break;
+ case ExpressionType.SubtractAssignChecked: op = "-="; isChecked = true; break;
+ case ExpressionType.SubtractChecked: op = "-"; isChecked = true; break;
+ case ExpressionType.Divide: op = "/"; break;
+ case ExpressionType.DivideAssign: op = "/="; break;
+ case ExpressionType.Modulo: op = "%"; break;
+ case ExpressionType.ModuloAssign: op = "%="; break;
+ case ExpressionType.Multiply: op = "*"; break;
+ case ExpressionType.MultiplyAssign: op = "*="; break;
+ case ExpressionType.MultiplyAssignChecked: op = "*="; isChecked = true; break;
+ case ExpressionType.MultiplyChecked: op = "*"; isChecked = true; break;
+ case ExpressionType.LeftShift: op = "<<"; break;
+ case ExpressionType.LeftShiftAssign: op = "<<="; break;
+ case ExpressionType.RightShift: op = ">>"; break;
+ case ExpressionType.RightShiftAssign: op = ">>="; break;
+ case ExpressionType.And: op = "&"; break;
+ case ExpressionType.AndAssign: op = "&="; break;
+ case ExpressionType.Or: op = "|"; break;
+ case ExpressionType.OrAssign: op = "|="; break;
+ case ExpressionType.ExclusiveOr: op = "^"; break;
+ case ExpressionType.ExclusiveOrAssign: op = "^="; break;
+ case ExpressionType.Power: op = "**"; break;
+ case ExpressionType.PowerAssign: op = "**="; break;
+ case ExpressionType.Coalesce: op = "??"; break;
+
+ default:
+ throw new InvalidOperationException();
+ }
+
+ if (parenthesizeLeft) {
+ Out("(", Flow.None);
+ }
+
+ Visit(node.Left);
+ if (parenthesizeLeft) {
+ Out(Flow.None, ")", Flow.Break);
+ }
+
+ // prepend # to the operator to represent checked op
+ if (isChecked) {
+ op = String.Format(
+ CultureInfo.CurrentCulture,
+ "#{0}",
+ op
+ );
+ }
+ Out(beforeOp, op, Flow.Space | Flow.Break);
+
+ if (parenthesizeRight) {
+ Out("(", Flow.None);
+ }
+ Visit(node.Right);
+ if (parenthesizeRight) {
+ Out(Flow.None, ")", Flow.Break);
+ }
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitParameter(ParameterExpression node) {
+ // Have '$' for the DebugView of ParameterExpressions
+ Out("$");
+ if (String.IsNullOrEmpty(node.Name)) {
+ // If no name if provided, generate a name as $var1, $var2.
+ // No guarantee for not having name conflicts with user provided variable names.
+ //
+ int id = GetParamId(node);
+ Out("var" + id);
+ } else {
+ Out(GetDisplayName(node.Name));
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitLambda<T>(Expression<T> node) {
+ Out(
+ String.Format(CultureInfo.CurrentCulture,
+ "{0} {1}<{2}>",
+ ".Lambda",
+ GetLambdaName(node),
+ node.Type.ToString()
+ )
+ );
+
+ if (_lambdas == null) {
+ _lambdas = new Queue<LambdaExpression>();
+ }
+
+ // N^2 performance, for keeping the order of the lambdas.
+ if (!_lambdas.Contains(node)) {
+ _lambdas.Enqueue(node);
+ }
+
+ return node;
+ }
+
+ private static bool IsSimpleExpression(Expression node) {
+ var binary = node as BinaryExpression;
+ if (binary != null) {
+ return !(binary.Left is BinaryExpression || binary.Right is BinaryExpression);
+ }
+
+ return false;
+ }
+
+ protected internal override Expression VisitConditional(ConditionalExpression node) {
+ if (IsSimpleExpression(node.Test)) {
+ Out(".If (");
+ Visit(node.Test);
+ Out(") {", Flow.NewLine);
+ } else {
+ Out(".If (", Flow.NewLine);
+ Indent();
+ Visit(node.Test);
+ Dedent();
+ Out(Flow.NewLine, ") {", Flow.NewLine);
+ }
+ Indent();
+ Visit(node.IfTrue);
+ Dedent();
+ Out(Flow.NewLine, "} .Else {", Flow.NewLine);
+ Indent();
+ Visit(node.IfFalse);
+ Dedent();
+ Out(Flow.NewLine, "}");
+ return node;
+ }
+
+ protected internal override Expression VisitConstant(ConstantExpression node) {
+ object value = node.Value;
+
+ if (value == null) {
+ Out("null");
+ } else if ((value is string) && node.Type == typeof(string)) {
+ Out(String.Format(
+ CultureInfo.CurrentCulture,
+ "\"{0}\"",
+ value));
+ } else if ((value is char) && node.Type == typeof(char)) {
+ Out(String.Format(
+ CultureInfo.CurrentCulture,
+ "'{0}'",
+ value));
+ } else if ((value is int) && node.Type == typeof(int)
+ || (value is bool) && node.Type == typeof(bool)) {
+ Out(value.ToString());
+ } else {
+ string suffix = GetConstantValueSuffix(node.Type);
+ if (suffix != null) {
+ Out(value.ToString());
+ Out(suffix);
+ } else {
+ Out(String.Format(
+ CultureInfo.CurrentCulture,
+ ".Constant<{0}>({1})",
+ node.Type.ToString(),
+ value));
+ }
+ }
+ return node;
+ }
+
+ private static string GetConstantValueSuffix(Type type) {
+ if (type == typeof(UInt32)) {
+ return "U";
+ }
+ if (type == typeof(Int64)) {
+ return "L";
+ }
+ if (type == typeof(UInt64)) {
+ return "UL";
+ }
+ if (type == typeof(Double)) {
+ return "D";
+ }
+ if (type == typeof(Single)) {
+ return "F";
+ }
+ if (type == typeof(Decimal)) {
+ return "M";
+ }
+ return null;
+ }
+
+ protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
+ Out(".RuntimeVariables");
+ VisitExpressions('(', node.Variables);
+ return node;
+ }
+
+ // Prints ".instanceField" or "declaringType.staticField"
+ private void OutMember(Expression node, Expression instance, MemberInfo member) {
+ if (instance != null) {
+ ParenthesizedVisit(node, instance);
+ Out("." + member.Name);
+ } else {
+ // For static members, include the type name
+ Out(member.DeclaringType.ToString() + "." + member.Name);
+ }
+ }
+
+ protected internal override Expression VisitMember(MemberExpression node) {
+ OutMember(node, node.Expression, node.Member);
+ return node;
+ }
+
+ protected internal override Expression VisitInvocation(InvocationExpression node) {
+ Out(".Invoke ");
+ ParenthesizedVisit(node, node.Expression);
+ VisitExpressions('(', node.Arguments);
+ return node;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static bool NeedsParentheses(Expression parent, Expression child) {
+ Debug.Assert(parent != null);
+ if (child == null) {
+ return false;
+ }
+
+ // Some nodes always have parentheses because of how they are
+ // displayed, for example: ".Unbox(obj.Foo)"
+ switch (parent.NodeType) {
+ case ExpressionType.Increment:
+ case ExpressionType.Decrement:
+ case ExpressionType.IsTrue:
+ case ExpressionType.IsFalse:
+ case ExpressionType.Unbox:
+ return true;
+ }
+
+ int childOpPrec = GetOperatorPrecedence(child);
+ int parentOpPrec = GetOperatorPrecedence(parent);
+
+ if (childOpPrec == parentOpPrec) {
+ // When parent op and child op has the same precedence,
+ // we want to be a little conservative to have more clarity.
+ // Parentheses are not needed if
+ // 1) Both ops are &&, ||, &, |, or ^, all of them are the only
+ // op that has the precedence.
+ // 2) Parent op is + or *, e.g. x + (y - z) can be simplified to
+ // x + y - z.
+ // 3) Parent op is -, / or %, and the child is the left operand.
+ // In this case, if left and right operand are the same, we don't
+ // remove parenthesis, e.g. (x + y) - (x + y)
+ //
+ switch (parent.NodeType) {
+ case ExpressionType.AndAlso:
+ case ExpressionType.OrElse:
+ case ExpressionType.And:
+ case ExpressionType.Or:
+ case ExpressionType.ExclusiveOr:
+ // Since these ops are the only ones on their precedence,
+ // the child op must be the same.
+ Debug.Assert(child.NodeType == parent.NodeType);
+ // We remove the parenthesis, e.g. x && y && z
+ return false;
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ return false;
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ BinaryExpression binary = parent as BinaryExpression;
+ Debug.Assert(binary != null);
+ // Need to have parenthesis for the right operand.
+ return child == binary.Right;
+ }
+ return true;
+ }
+
+ // Special case: negate of a constant needs parentheses, to
+ // disambiguate it from a negative constant.
+ if (child != null && child.NodeType == ExpressionType.Constant &&
+ (parent.NodeType == ExpressionType.Negate || parent.NodeType == ExpressionType.NegateChecked)) {
+ return true;
+ }
+
+ // If the parent op has higher precedence, need parentheses for the child.
+ return childOpPrec < parentOpPrec;
+ }
+
+ // the greater the higher
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static int GetOperatorPrecedence(Expression node) {
+
+ // Roughly matches C# operator precedence, with some additional
+ // operators. Also things which are not binary/unary expressions,
+ // such as conditional and type testing, don't use this mechanism.
+ switch (node.NodeType) {
+ // Assignment
+ case ExpressionType.Assign:
+ case ExpressionType.ExclusiveOrAssign:
+ case ExpressionType.AddAssign:
+ case ExpressionType.AddAssignChecked:
+ case ExpressionType.SubtractAssign:
+ case ExpressionType.SubtractAssignChecked:
+ case ExpressionType.DivideAssign:
+ case ExpressionType.ModuloAssign:
+ case ExpressionType.MultiplyAssign:
+ case ExpressionType.MultiplyAssignChecked:
+ case ExpressionType.LeftShiftAssign:
+ case ExpressionType.RightShiftAssign:
+ case ExpressionType.AndAssign:
+ case ExpressionType.OrAssign:
+ case ExpressionType.PowerAssign:
+ case ExpressionType.Coalesce:
+ return 1;
+
+ // Conditional (?:) would go here
+
+ // Conditional OR
+ case ExpressionType.OrElse:
+ return 2;
+
+ // Conditional AND
+ case ExpressionType.AndAlso:
+ return 3;
+
+ // Logical OR
+ case ExpressionType.Or:
+ return 4;
+
+ // Logical XOR
+ case ExpressionType.ExclusiveOr:
+ return 5;
+
+ // Logical AND
+ case ExpressionType.And:
+ return 6;
+
+ // Equality
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ return 7;
+
+ // Relational, type testing
+ case ExpressionType.GreaterThan:
+ case ExpressionType.LessThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.TypeAs:
+ case ExpressionType.TypeIs:
+ case ExpressionType.TypeEqual:
+ return 8;
+
+ // Shift
+ case ExpressionType.LeftShift:
+ case ExpressionType.RightShift:
+ return 9;
+
+ // Additive
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ return 10;
+
+ // Multiplicative
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ return 11;
+
+ // Unary
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.UnaryPlus:
+ case ExpressionType.Not:
+ case ExpressionType.Convert:
+ case ExpressionType.ConvertChecked:
+ case ExpressionType.PreIncrementAssign:
+ case ExpressionType.PreDecrementAssign:
+ case ExpressionType.OnesComplement:
+ case ExpressionType.Increment:
+ case ExpressionType.Decrement:
+ case ExpressionType.IsTrue:
+ case ExpressionType.IsFalse:
+ case ExpressionType.Unbox:
+ case ExpressionType.Throw:
+ return 12;
+
+ // Power, which is not in C#
+ // But VB/Python/Ruby put it here, above unary.
+ case ExpressionType.Power:
+ return 13;
+
+ // Primary, which includes all other node types:
+ // member access, calls, indexing, new.
+ case ExpressionType.PostIncrementAssign:
+ case ExpressionType.PostDecrementAssign:
+ default:
+ return 14;
+
+ // These aren't expressions, so never need parentheses:
+ // constants, variables
+ case ExpressionType.Constant:
+ case ExpressionType.Parameter:
+ return 15;
+ }
+ }
+
+ private void ParenthesizedVisit(Expression parent, Expression nodeToVisit) {
+ if (NeedsParentheses(parent, nodeToVisit)) {
+ Out("(");
+ Visit(nodeToVisit);
+ Out(")");
+ } else {
+ Visit(nodeToVisit);
+ }
+ }
+
+ protected internal override Expression VisitMethodCall(MethodCallExpression node) {
+ Out(".Call ");
+ if (node.Object != null) {
+ ParenthesizedVisit(node, node.Object);
+ } else if (node.Method.DeclaringType != null) {
+ Out(node.Method.DeclaringType.ToString());
+ } else {
+ Out("<UnknownType>");
+ }
+ Out(".");
+ Out(node.Method.Name);
+ VisitExpressions('(', node.Arguments);
+ return node;
+ }
+
+ protected internal override Expression VisitNewArray(NewArrayExpression node) {
+ if (node.NodeType == ExpressionType.NewArrayBounds) {
+ // .NewArray MyType[expr1, expr2]
+ Out(".NewArray " + node.Type.GetElementType().ToString());
+ VisitExpressions('[', node.Expressions);
+ } else {
+ // .NewArray MyType {expr1, expr2}
+ Out(".NewArray " + node.Type.ToString(), Flow.Space);
+ VisitExpressions('{', node.Expressions);
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitNew(NewExpression node) {
+ Out(".New " + node.Type.ToString());
+ VisitExpressions('(', node.Arguments);
+ return node;
+ }
+
+ protected override ElementInit VisitElementInit(ElementInit node) {
+ if (node.Arguments.Count == 1) {
+ Visit(node.Arguments[0]);
+ } else {
+ VisitExpressions('{', node.Arguments);
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitListInit(ListInitExpression node) {
+ Visit(node.NewExpression);
+ VisitExpressions('{', ',', node.Initializers, e => VisitElementInit(e));
+ return node;
+ }
+
+ protected override MemberAssignment VisitMemberAssignment(MemberAssignment assignment) {
+ Out(assignment.Member.Name);
+ Out(Flow.Space, "=", Flow.Space);
+ Visit(assignment.Expression);
+ return assignment;
+ }
+
+ protected override MemberListBinding VisitMemberListBinding(MemberListBinding binding) {
+ Out(binding.Member.Name);
+ Out(Flow.Space, "=", Flow.Space);
+ VisitExpressions('{', ',', binding.Initializers, e => VisitElementInit(e));
+ return binding;
+ }
+
+ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) {
+ Out(binding.Member.Name);
+ Out(Flow.Space, "=", Flow.Space);
+ VisitExpressions('{', ',', binding.Bindings, e => VisitMemberBinding(e));
+ return binding;
+ }
+
+ protected internal override Expression VisitMemberInit(MemberInitExpression node) {
+ Visit(node.NewExpression);
+ VisitExpressions('{', ',', node.Bindings, e => VisitMemberBinding(e));
+ return node;
+ }
+
+ protected internal override Expression VisitTypeBinary(TypeBinaryExpression node) {
+ ParenthesizedVisit(node, node.Expression);
+ switch (node.NodeType) {
+ case ExpressionType.TypeIs:
+ Out(Flow.Space, ".Is", Flow.Space);
+ break;
+ case ExpressionType.TypeEqual:
+ Out(Flow.Space, ".TypeEqual", Flow.Space);
+ break;
+ }
+ Out(node.TypeOperand.ToString());
+ return node;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ protected internal override Expression VisitUnary(UnaryExpression node) {
+ bool parenthesize = NeedsParentheses(node, node.Operand);
+
+ switch (node.NodeType) {
+ case ExpressionType.Convert:
+ Out("(" + node.Type.ToString() + ")");
+ break;
+ case ExpressionType.ConvertChecked:
+ Out("#(" + node.Type.ToString() + ")");
+ break;
+ case ExpressionType.TypeAs:
+ break;
+ case ExpressionType.Not:
+ Out(node.Type == typeof(bool) ? "!" : "~");
+ break;
+ case ExpressionType.OnesComplement:
+ Out("~");
+ break;
+ case ExpressionType.Negate:
+ Out("-");
+ break;
+ case ExpressionType.NegateChecked:
+ Out("#-");
+ break;
+ case ExpressionType.UnaryPlus:
+ Out("+");
+ break;
+ case ExpressionType.ArrayLength:
+ break;
+ case ExpressionType.Quote:
+ Out("'");
+ break;
+ case ExpressionType.Throw:
+ if (node.Operand == null) {
+ Out(".Rethrow");
+ } else {
+ Out(".Throw", Flow.Space);
+ }
+ break;
+ case ExpressionType.IsFalse:
+ Out(".IsFalse");
+ break;
+ case ExpressionType.IsTrue:
+ Out(".IsTrue");
+ break;
+ case ExpressionType.Decrement:
+ Out(".Decrement");
+ break;
+ case ExpressionType.Increment:
+ Out(".Increment");
+ break;
+ case ExpressionType.PreDecrementAssign:
+ Out("--");
+ break;
+ case ExpressionType.PreIncrementAssign:
+ Out("++");
+ break;
+ case ExpressionType.Unbox:
+ Out(".Unbox");
+ break;
+ }
+
+ ParenthesizedVisit(node, node.Operand);
+
+ switch (node.NodeType) {
+ case ExpressionType.TypeAs:
+ Out(Flow.Space, ".As", Flow.Space | Flow.Break);
+ Out(node.Type.ToString());
+ break;
+
+ case ExpressionType.ArrayLength:
+ Out(".Length");
+ break;
+
+ case ExpressionType.PostDecrementAssign:
+ Out("--");
+ break;
+
+ case ExpressionType.PostIncrementAssign:
+ Out("++");
+ break;
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitBlock(BlockExpression node) {
+ Out(".Block");
+
+ // Display <type> if the type of the BlockExpression is different from the
+ // last expression's type in the block.
+ if (node.Type != node.GetExpression(node.ExpressionCount - 1).Type) {
+ Out(String.Format(CultureInfo.CurrentCulture, "<{0}>", node.Type.ToString()));
+ }
+
+ VisitDeclarations(node.Variables);
+ Out(" ");
+ // Use ; to separate expressions in the block
+ VisitExpressions('{', ';', node.Expressions);
+
+ return node;
+ }
+
+ protected internal override Expression VisitDefault(DefaultExpression node) {
+ Out(".Default(" + node.Type.ToString() + ")");
+ return node;
+ }
+
+ protected internal override Expression VisitLabel(LabelExpression node) {
+ Out(".Label", Flow.NewLine);
+ Indent();
+ Visit(node.DefaultValue);
+ Dedent();
+ NewLine();
+ DumpLabel(node.Target);
+ return node;
+ }
+
+ protected internal override Expression VisitGoto(GotoExpression node) {
+ Out("." + node.Kind.ToString(), Flow.Space);
+ Out(GetLabelTargetName(node.Target), Flow.Space);
+ Out("{", Flow.Space);
+ Visit(node.Value);
+ Out(Flow.Space, "}");
+ return node;
+ }
+
+ protected internal override Expression VisitLoop(LoopExpression node) {
+ Out(".Loop", Flow.Space);
+ if (node.ContinueLabel != null) {
+ DumpLabel(node.ContinueLabel);
+ }
+ Out(" {", Flow.NewLine);
+ Indent();
+ Visit(node.Body);
+ Dedent();
+ Out(Flow.NewLine, "}");
+ if (node.BreakLabel != null) {
+ Out("", Flow.NewLine);
+ DumpLabel(node.BreakLabel);
+ }
+ return node;
+ }
+
+ protected override SwitchCase VisitSwitchCase(SwitchCase node) {
+ foreach (var test in node.TestValues) {
+ Out(".Case (");
+ Visit(test);
+ Out("):", Flow.NewLine);
+ }
+ Indent(); Indent();
+ Visit(node.Body);
+ Dedent(); Dedent();
+ NewLine();
+ return node;
+ }
+
+ protected internal override Expression VisitSwitch(SwitchExpression node) {
+ Out(".Switch ");
+ Out("(");
+ Visit(node.SwitchValue);
+ Out(") {", Flow.NewLine);
+ Visit(node.Cases, VisitSwitchCase);
+ if (node.DefaultBody != null) {
+ Out(".Default:", Flow.NewLine);
+ Indent(); Indent();
+ Visit(node.DefaultBody);
+ Dedent(); Dedent();
+ NewLine();
+ }
+ Out("}");
+ return node;
+ }
+
+ protected override CatchBlock VisitCatchBlock(CatchBlock node) {
+ Out(Flow.NewLine, "} .Catch (" + node.Test.ToString());
+ if (node.Variable != null) {
+ Out(Flow.Space, "");
+ VisitParameter(node.Variable);
+ }
+ if (node.Filter != null) {
+ Out(") .If (", Flow.Break);
+ Visit(node.Filter);
+ }
+ Out(") {", Flow.NewLine);
+ Indent();
+ Visit(node.Body);
+ Dedent();
+ return node;
+ }
+
+ protected internal override Expression VisitTry(TryExpression node) {
+ Out(".Try {", Flow.NewLine);
+ Indent();
+ Visit(node.Body);
+ Dedent();
+ Visit(node.Handlers, VisitCatchBlock);
+ if (node.Finally != null) {
+ Out(Flow.NewLine, "} .Finally {", Flow.NewLine);
+ Indent();
+ Visit(node.Finally);
+ Dedent();
+ } else if (node.Fault != null) {
+ Out(Flow.NewLine, "} .Fault {", Flow.NewLine);
+ Indent();
+ Visit(node.Fault);
+ Dedent();
+ }
+
+ Out(Flow.NewLine, "}");
+ return node;
+ }
+
+ protected internal override Expression VisitIndex(IndexExpression node) {
+ if (node.Indexer != null) {
+ OutMember(node, node.Object, node.Indexer);
+ } else {
+ ParenthesizedVisit(node, node.Object);
+ }
+
+ VisitExpressions('[', node.Arguments);
+ return node;
+ }
+
+ protected internal override Expression VisitExtension(Expression node) {
+ Out(String.Format(CultureInfo.CurrentCulture, ".Extension<{0}>", node.GetType().ToString()));
+
+ if (node.CanReduce) {
+ Out(Flow.Space, "{", Flow.NewLine);
+ Indent();
+ Visit(node.Reduce());
+ Dedent();
+ Out(Flow.NewLine, "}");
+ }
+
+ return node;
+ }
+
+ protected internal override Expression VisitDebugInfo(DebugInfoExpression node) {
+ Out(String.Format(
+ CultureInfo.CurrentCulture,
+ ".DebugInfo({0}: {1}, {2} - {3}, {4})",
+ node.Document.FileName,
+ node.StartLine,
+ node.StartColumn,
+ node.EndLine,
+ node.EndColumn)
+ );
+ return node;
+ }
+
+
+ private void DumpLabel(LabelTarget target) {
+ Out(String.Format(CultureInfo.CurrentCulture, ".LabelTarget {0}:", GetLabelTargetName(target)));
+ }
+
+ private string GetLabelTargetName(LabelTarget target) {
+ if (string.IsNullOrEmpty(target.Name)) {
+ // Create the label target name as #Label1, #Label2, etc.
+ return String.Format(CultureInfo.CurrentCulture, "#Label{0}", GetLabelTargetId(target));
+ } else {
+ return GetDisplayName(target.Name);
+ }
+ }
+
+ private void WriteLambda(LambdaExpression lambda) {
+ Out(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ ".Lambda {0}<{1}>",
+ GetLambdaName(lambda),
+ lambda.Type.ToString())
+ );
+
+ VisitDeclarations(lambda.Parameters);
+
+ Out(Flow.Space, "{", Flow.NewLine);
+ Indent();
+ Visit(lambda.Body);
+ Dedent();
+ Out(Flow.NewLine, "}");
+ Debug.Assert(_stack.Count == 0);
+ }
+
+ private string GetLambdaName(LambdaExpression lambda) {
+ if (String.IsNullOrEmpty(lambda.Name)) {
+ return "#Lambda" + GetLambdaId(lambda);
+ }
+ return GetDisplayName(lambda.Name);
+ }
+
+ /// <summary>
+ /// Return true if the input string contains any whitespace character.
+ /// Otherwise false.
+ /// </summary>
+ private static bool ContainsWhiteSpace(string name) {
+ foreach (char c in name) {
+ if (Char.IsWhiteSpace(c)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static string QuoteName(string name) {
+ return String.Format(CultureInfo.CurrentCulture, "'{0}'", name);
+ }
+
+ private static string GetDisplayName(string name) {
+ if (ContainsWhiteSpace(name)) {
+ // if name has whitespaces in it, quote it
+ return QuoteName(name);
+ } else {
+ return name;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DefaultExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DefaultExpression.cs
new file mode 100644
index 00000000000..3c3c31fa192
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DefaultExpression.cs
@@ -0,0 +1,87 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents the default value of a type or an empty expression.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.DefaultExpressionProxy))]
+#endif
+ public sealed class DefaultExpression : Expression {
+ private readonly Type _type;
+
+ internal DefaultExpression(Type type) {
+ _type = type;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Default; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitDefault(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates an empty expression that has <see cref="System.Void"/> type.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="DefaultExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Default"/> and the <see cref="P:Expression.Type"/> property set to <see cref="System.Void"/>.
+ /// </returns>
+ public static DefaultExpression Empty() {
+ return new DefaultExpression(typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DefaultExpression"/> that has the <see cref="P:Expression.Type"/> property set to the specified type.
+ /// </summary>
+ /// <param name="type">A <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="DefaultExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
+ /// <see cref="F:ExpressionType.Default"/> and the <see cref="P:Expression.Type"/> property set to the specified type.
+ /// </returns>
+ public static DefaultExpression Default(Type type) {
+ if (type == typeof(void)) {
+ return Empty();
+ }
+ return new DefaultExpression(type);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs
new file mode 100644
index 00000000000..1b7127284bf
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs
@@ -0,0 +1,841 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a dynamic operation.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.DynamicExpressionProxy))]
+#endif
+ public class DynamicExpression : Expression, IArgumentProvider {
+ private readonly CallSiteBinder _binder;
+ private readonly Type _delegateType;
+
+ internal DynamicExpression(Type delegateType, CallSiteBinder binder) {
+ Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == typeof(object) || GetType() != typeof(DynamicExpression));
+ _delegateType = delegateType;
+ _binder = binder;
+ }
+
+ internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, ReadOnlyCollection<Expression> arguments) {
+ if (returnType == typeof(object)) {
+ return new DynamicExpressionN(delegateType, binder, arguments);
+ } else {
+ return new TypedDynamicExpressionN(returnType, delegateType, binder, arguments);
+ }
+ }
+
+ internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0) {
+ if (returnType == typeof(object)) {
+ return new DynamicExpression1(delegateType, binder, arg0);
+ } else {
+ return new TypedDynamicExpression1(returnType, delegateType, binder, arg0);
+ }
+ }
+
+ internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
+ if (returnType == typeof(object)) {
+ return new DynamicExpression2(delegateType, binder, arg0, arg1);
+ } else {
+ return new TypedDynamicExpression2(returnType, delegateType, binder, arg0, arg1);
+ }
+ }
+
+ internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
+ if (returnType == typeof(object)) {
+ return new DynamicExpression3(delegateType, binder, arg0, arg1, arg2);
+ } else {
+ return new TypedDynamicExpression3(returnType, delegateType, binder, arg0, arg1, arg2);
+ }
+ }
+
+ internal static DynamicExpression Make(Type returnType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
+ if (returnType == typeof(object)) {
+ return new DynamicExpression4(delegateType, binder, arg0, arg1, arg2, arg3);
+ } else {
+ return new TypedDynamicExpression4(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
+ }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public override Type Type {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Dynamic; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="CallSiteBinder" />, which determines the runtime behavior of the
+ /// dynamic site.
+ /// </summary>
+ public CallSiteBinder Binder {
+ get { return _binder; }
+ }
+
+ /// <summary>
+ /// Gets the type of the delegate used by the <see cref="CallSite" />.
+ /// </summary>
+ public Type DelegateType {
+ get { return _delegateType; }
+ }
+
+ /// <summary>
+ /// Gets the arguments to the dynamic operation.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Arguments {
+ get { return GetOrMakeArguments(); }
+ }
+
+ internal virtual ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ throw ContractUtils.Unreachable;
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitDynamic(this);
+ }
+
+ /// <summary>
+ /// Makes a copy of this node replacing the args with the provided values. The
+ /// number of the args needs to match the number of the current block.
+ ///
+ /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
+ /// subclass of DynamicExpression which is being used.
+ /// </summary>
+ internal virtual DynamicExpression Rewrite(Expression[] args) {
+ throw ContractUtils.Unreachable;
+ }
+
+ #region IArgumentProvider Members
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ throw ContractUtils.Unreachable;
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ #endregion
+ }
+
+ #region Specialized Subclasses
+
+ internal class DynamicExpressionN : DynamicExpression, IArgumentProvider {
+ private IList<Expression> _arguments; // storage for the original IList or readonly collection. See IArgumentProvider for more info.
+
+ internal DynamicExpressionN(Type delegateType, CallSiteBinder binder, IList<Expression> arguments)
+ : base(delegateType, binder) {
+ _arguments = arguments;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(ref _arguments);
+ }
+
+ internal override DynamicExpression Rewrite(Expression[] args) {
+ Debug.Assert(args.Length == ((IArgumentProvider)this).ArgumentCount);
+
+ return Expression.MakeDynamic(DelegateType, Binder, args);
+ }
+ }
+
+ internal class TypedDynamicExpressionN : DynamicExpressionN {
+ private readonly Type _returnType;
+
+ internal TypedDynamicExpressionN(Type returnType, Type delegateType, CallSiteBinder binder, IList<Expression> arguments)
+ : base(delegateType, binder, arguments) {
+ Debug.Assert(delegateType.GetMethod("Invoke").GetReturnType() == returnType);
+ _returnType = returnType;
+ }
+
+ public sealed override Type Type {
+ get { return _returnType; }
+ }
+ }
+
+ internal class DynamicExpression1 : DynamicExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
+
+ internal DynamicExpression1(Type delegateType, CallSiteBinder binder, Expression arg0)
+ : base(delegateType, binder) {
+ _arg0 = arg0;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 1;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override DynamicExpression Rewrite(Expression[] args) {
+ Debug.Assert(args.Length == 1);
+
+ return Expression.MakeDynamic(DelegateType, Binder, args[0]);
+ }
+ }
+
+ internal sealed class TypedDynamicExpression1 : DynamicExpression1 {
+ private readonly Type _retType;
+
+ internal TypedDynamicExpression1(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0)
+ : base(delegateType, binder, arg0) {
+ _retType = retType;
+ }
+
+ public sealed override Type Type {
+ get { return _retType; }
+ }
+ }
+
+ internal class DynamicExpression2 : DynamicExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
+ private readonly Expression _arg1; // storage for the 2nd argument
+
+ internal DynamicExpression2(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
+ : base(delegateType, binder) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 2;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override DynamicExpression Rewrite(Expression[] args) {
+ Debug.Assert(args.Length == 2);
+
+ return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1]);
+ }
+ }
+
+ internal sealed class TypedDynamicExpression2 : DynamicExpression2 {
+ private readonly Type _retType;
+
+ internal TypedDynamicExpression2(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1)
+ : base(delegateType, binder, arg0, arg1) {
+ _retType = retType;
+ }
+
+ public sealed override Type Type {
+ get { return _retType; }
+ }
+ }
+
+ internal class DynamicExpression3 : DynamicExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
+ private readonly Expression _arg1, _arg2; // storage for the 2nd & 3rd arguments
+
+ internal DynamicExpression3(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
+ : base(delegateType, binder) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 3;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override DynamicExpression Rewrite(Expression[] args) {
+ Debug.Assert(args.Length == 3);
+
+ return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2]);
+ }
+ }
+
+ internal sealed class TypedDynamicExpression3 : DynamicExpression3 {
+ private readonly Type _retType;
+
+ internal TypedDynamicExpression3(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2)
+ : base(delegateType, binder, arg0, arg1, arg2) {
+ _retType = retType;
+ }
+
+ public sealed override Type Type {
+ get { return _retType; }
+ }
+ }
+
+ internal class DynamicExpression4 : DynamicExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider for more info.
+ private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th arguments
+
+ internal DynamicExpression4(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
+ : base(delegateType, binder) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ _arg3 = arg3;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ case 3: return _arg3;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 4;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override DynamicExpression Rewrite(Expression[] args) {
+ Debug.Assert(args.Length == 4);
+
+ return Expression.MakeDynamic(DelegateType, Binder, args[0], args[1], args[2], args[3]);
+ }
+ }
+
+ internal sealed class TypedDynamicExpression4 : DynamicExpression4 {
+ private readonly Type _retType;
+
+ internal TypedDynamicExpression4(Type retType, Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
+ : base(delegateType, binder, arg0, arg1, arg2, arg3) {
+ _retType = retType;
+ }
+
+ public sealed override Type Type {
+ get { return _retType; }
+ }
+ }
+
+ #endregion
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="arguments">The arguments to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
+ /// <see cref="DynamicExpression.Binder">Binder</see>, and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, params Expression[] arguments) {
+ return MakeDynamic(delegateType, binder, (IEnumerable<Expression>)arguments);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="arguments">The arguments to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
+ /// <see cref="DynamicExpression.Binder">Binder</see>, and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, IEnumerable<Expression> arguments) {
+ ContractUtils.RequiresNotNull(delegateType, "delegateType");
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.Requires(delegateType.IsSubclassOf(typeof(Delegate)), "delegateType", Strings.TypeMustBeDerivedFromSystemDelegate);
+
+ var method = GetValidMethodForDynamic(delegateType);
+
+ var args = arguments.ToReadOnly();
+ ValidateArgumentTypes(method, ExpressionType.Dynamic, ref args);
+
+ return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, args);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and one argument.
+ /// </summary>
+ /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="arg0">The argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
+ /// <see cref="DynamicExpression.Binder">Binder</see>, and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0) {
+ ContractUtils.RequiresNotNull(delegateType, "delegatType");
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.Requires(delegateType.IsSubclassOf(typeof(Delegate)), "delegateType", Strings.TypeMustBeDerivedFromSystemDelegate);
+
+ var method = GetValidMethodForDynamic(delegateType);
+ var parameters = method.GetParametersCached();
+
+ ValidateArgumentCount(method, ExpressionType.Dynamic, 2, parameters);
+ ValidateDynamicArgument(arg0);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
+
+ return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and two arguments.
+ /// </summary>
+ /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <param name="arg1">The second argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
+ /// <see cref="DynamicExpression.Binder">Binder</see>, and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1) {
+ ContractUtils.RequiresNotNull(delegateType, "delegatType");
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.Requires(delegateType.IsSubclassOf(typeof(Delegate)), "delegateType", Strings.TypeMustBeDerivedFromSystemDelegate);
+
+ var method = GetValidMethodForDynamic(delegateType);
+ var parameters = method.GetParametersCached();
+
+ ValidateArgumentCount(method, ExpressionType.Dynamic, 3, parameters);
+ ValidateDynamicArgument(arg0);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
+ ValidateDynamicArgument(arg1);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
+
+ return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and three arguments.
+ /// </summary>
+ /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <param name="arg1">The second argument to the dynamic operation.</param>
+ /// <param name="arg2">The third argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
+ /// <see cref="DynamicExpression.Binder">Binder</see>, and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2) {
+ ContractUtils.RequiresNotNull(delegateType, "delegatType");
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.Requires(delegateType.IsSubclassOf(typeof(Delegate)), "delegateType", Strings.TypeMustBeDerivedFromSystemDelegate);
+
+ var method = GetValidMethodForDynamic(delegateType);
+ var parameters = method.GetParametersCached();
+
+ ValidateArgumentCount(method, ExpressionType.Dynamic, 4, parameters);
+ ValidateDynamicArgument(arg0);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
+ ValidateDynamicArgument(arg1);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
+ ValidateDynamicArgument(arg2);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
+
+ return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" /> and four arguments.
+ /// </summary>
+ /// <param name="delegateType">The type of the delegate used by the <see cref="CallSite" />.</param>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <param name="arg1">The second argument to the dynamic operation.</param>
+ /// <param name="arg2">The third argument to the dynamic operation.</param>
+ /// <param name="arg3">The fourth argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.DelegateType">DelegateType</see>,
+ /// <see cref="DynamicExpression.Binder">Binder</see>, and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ public static DynamicExpression MakeDynamic(Type delegateType, CallSiteBinder binder, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
+ ContractUtils.RequiresNotNull(delegateType, "delegatType");
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.Requires(delegateType.IsSubclassOf(typeof(Delegate)), "delegateType", Strings.TypeMustBeDerivedFromSystemDelegate);
+
+ var method = GetValidMethodForDynamic(delegateType);
+ var parameters = method.GetParametersCached();
+
+ ValidateArgumentCount(method, ExpressionType.Dynamic, 5, parameters);
+ ValidateDynamicArgument(arg0);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg0, parameters[1]);
+ ValidateDynamicArgument(arg1);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg1, parameters[2]);
+ ValidateDynamicArgument(arg2);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg2, parameters[3]);
+ ValidateDynamicArgument(arg3);
+ ValidateOneArgument(method, ExpressionType.Dynamic, arg3, parameters[4]);
+
+ return DynamicExpression.Make(method.GetReturnType(), delegateType, binder, arg0, arg1, arg2, arg3);
+ }
+
+ private static MethodInfo GetValidMethodForDynamic(Type delegateType) {
+ var method = delegateType.GetMethod("Invoke");
+ var pi = method.GetParametersCached();
+ ContractUtils.Requires(pi.Length > 0 && pi[0].ParameterType == typeof(CallSite), "delegateType", Strings.FirstArgumentMustBeCallSite);
+ return method;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="returnType">The result type of the dynamic expression.</param>
+ /// <param name="arguments">The arguments to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.Binder">Binder</see> and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
+ /// result will be inferred from the types of the arguments and the specified return type.
+ /// </remarks>
+ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, params Expression[] arguments) {
+ return Dynamic(binder, returnType, (IEnumerable<Expression>)arguments);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="returnType">The result type of the dynamic expression.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.Binder">Binder</see> and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
+ /// result will be inferred from the types of the arguments and the specified return type.
+ /// </remarks>
+ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ValidateDynamicArgument(arg0);
+
+ DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
+ returnType,
+ DelegateHelpers.GetNextTypeInfo(
+ arg0.Type,
+ DelegateHelpers.NextTypeInfo(typeof(CallSite))
+ )
+ );
+
+ Type delegateType = info.DelegateType;
+ if (delegateType == null) {
+ delegateType = info.MakeDelegateType(returnType, arg0);
+ }
+
+ return DynamicExpression.Make(returnType, delegateType, binder, arg0);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="returnType">The result type of the dynamic expression.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <param name="arg1">The second argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.Binder">Binder</see> and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
+ /// result will be inferred from the types of the arguments and the specified return type.
+ /// </remarks>
+ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ValidateDynamicArgument(arg0);
+ ValidateDynamicArgument(arg1);
+
+ DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
+ returnType,
+ DelegateHelpers.GetNextTypeInfo(
+ arg1.Type,
+ DelegateHelpers.GetNextTypeInfo(
+ arg0.Type,
+ DelegateHelpers.NextTypeInfo(typeof(CallSite))
+ )
+ )
+ );
+
+ Type delegateType = info.DelegateType;
+ if (delegateType == null) {
+ delegateType = info.MakeDelegateType(returnType, arg0, arg1);
+ }
+
+ return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="returnType">The result type of the dynamic expression.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <param name="arg1">The second argument to the dynamic operation.</param>
+ /// <param name="arg2">The third argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.Binder">Binder</see> and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
+ /// result will be inferred from the types of the arguments and the specified return type.
+ /// </remarks>
+ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ValidateDynamicArgument(arg0);
+ ValidateDynamicArgument(arg1);
+ ValidateDynamicArgument(arg2);
+
+ DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
+ returnType,
+ DelegateHelpers.GetNextTypeInfo(
+ arg2.Type,
+ DelegateHelpers.GetNextTypeInfo(
+ arg1.Type,
+ DelegateHelpers.GetNextTypeInfo(
+ arg0.Type,
+ DelegateHelpers.NextTypeInfo(typeof(CallSite))
+ )
+ )
+ )
+ );
+
+ Type delegateType = info.DelegateType;
+ if (delegateType == null) {
+ delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2);
+ }
+
+ return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="returnType">The result type of the dynamic expression.</param>
+ /// <param name="arg0">The first argument to the dynamic operation.</param>
+ /// <param name="arg1">The second argument to the dynamic operation.</param>
+ /// <param name="arg2">The third argument to the dynamic operation.</param>
+ /// <param name="arg3">The fourth argument to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.Binder">Binder</see> and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
+ /// result will be inferred from the types of the arguments and the specified return type.
+ /// </remarks>
+ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ValidateDynamicArgument(arg0);
+ ValidateDynamicArgument(arg1);
+ ValidateDynamicArgument(arg2);
+ ValidateDynamicArgument(arg3);
+
+ DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
+ returnType,
+ DelegateHelpers.GetNextTypeInfo(
+ arg3.Type,
+ DelegateHelpers.GetNextTypeInfo(
+ arg2.Type,
+ DelegateHelpers.GetNextTypeInfo(
+ arg1.Type,
+ DelegateHelpers.GetNextTypeInfo(
+ arg0.Type,
+ DelegateHelpers.NextTypeInfo(typeof(CallSite))
+ )
+ )
+ )
+ )
+ );
+
+ Type delegateType = info.DelegateType;
+ if (delegateType == null) {
+ delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2, arg3);
+ }
+
+ return DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2, arg3);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
+ /// </summary>
+ /// <param name="binder">The runtime binder for the dynamic operation.</param>
+ /// <param name="returnType">The result type of the dynamic expression.</param>
+ /// <param name="arguments">The arguments to the dynamic operation.</param>
+ /// <returns>
+ /// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
+ /// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
+ /// <see cref="DynamicExpression.Binder">Binder</see> and
+ /// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
+ /// result will be inferred from the types of the arguments and the specified return type.
+ /// </remarks>
+ public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, IEnumerable<Expression> arguments) {
+ ContractUtils.RequiresNotNull(arguments, "arguments");
+ ContractUtils.RequiresNotNull(returnType, "returnType");
+
+ var args = arguments.ToReadOnly();
+ ContractUtils.RequiresNotEmpty(args, "args");
+ return MakeDynamic(binder, returnType, args);
+ }
+
+ private static DynamicExpression MakeDynamic(CallSiteBinder binder, Type returnType, ReadOnlyCollection<Expression> args) {
+ ContractUtils.RequiresNotNull(binder, "binder");
+
+ for (int i = 0; i < args.Count; i++) {
+ Expression arg = args[i];
+
+ ValidateDynamicArgument(arg);
+ }
+
+ Type delegateType = DelegateHelpers.MakeCallSiteDelegate(args, returnType);
+
+ // Since we made a delegate with argument types that exactly match,
+ // we can skip delegate and argument validation
+
+ switch (args.Count) {
+ case 1: return DynamicExpression.Make(returnType, delegateType, binder, args[0]);
+ case 2: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1]);
+ case 3: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2]);
+ case 4: return DynamicExpression.Make(returnType, delegateType, binder, args[0], args[1], args[2], args[3]);
+ default: return DynamicExpression.Make(returnType, delegateType, binder, args);
+ }
+ }
+
+ private static void ValidateDynamicArgument(Expression arg) {
+ RequiresCanRead(arg, "arguments");
+ var type = arg.Type;
+ ContractUtils.RequiresNotNull(type, "type");
+ TypeUtils.ValidateType(type);
+ ContractUtils.Requires(type != typeof(void), Strings.ArgumentTypeCannotBeVoid);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ElementInit.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ElementInit.cs
new file mode 100644
index 00000000000..b4795931fef
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ElementInit.cs
@@ -0,0 +1,129 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Reflection;
+using System.Text;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents the initialization of a list.
+ /// </summary>
+ public sealed class ElementInit : IArgumentProvider {
+ private MethodInfo _addMethod;
+ private ReadOnlyCollection<Expression> _arguments;
+
+ internal ElementInit(MethodInfo addMethod, ReadOnlyCollection<Expression> arguments) {
+ _addMethod = addMethod;
+ _arguments = arguments;
+ }
+ /// <summary>
+ /// Gets the <see cref="MethodInfo"/> used to add elements to the object.
+ /// </summary>
+ public MethodInfo AddMethod {
+ get { return _addMethod; }
+ }
+
+ /// <summary>
+ /// Gets the list of elements to be added to the object.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Arguments {
+ get { return _arguments; }
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="String"/> representation of the node.
+ /// </summary>
+ /// <returns>A <see cref="String"/> representation of the node.</returns>
+ public override string ToString() {
+ return ExpressionStringBuilder.ElementInitBindingToString(this);
+ }
+ }
+
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates an <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression that represents the initialization of a list.
+ /// </summary>
+ /// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
+ /// <param name="arguments">An array containing the Expressions to be used to initialize the list.</param>
+ /// <returns>The created <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression.</returns>
+ public static ElementInit ElementInit(MethodInfo addMethod, params Expression[] arguments) {
+ return ElementInit(addMethod, arguments as IEnumerable<Expression>);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression that represents the initialization of a list.
+ /// </summary>
+ /// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
+ /// <param name="arguments">An <see cref="IEnumerable{T}"/> containing <see cref="Expression"/> elements to initialize the list.</param>
+ /// <returns>The created <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression.</returns>
+ public static ElementInit ElementInit(MethodInfo addMethod, IEnumerable<Expression> arguments) {
+ ContractUtils.RequiresNotNull(addMethod, "addMethod");
+ ContractUtils.RequiresNotNull(arguments, "arguments");
+
+ var argumentsRO = arguments.ToReadOnly();
+
+ RequiresCanRead(argumentsRO, "arguments");
+ ValidateElementInitAddMethodInfo(addMethod);
+ ValidateArgumentTypes(addMethod, ExpressionType.Call, ref argumentsRO);
+ return new ElementInit(addMethod, argumentsRO);
+ }
+
+ private static void ValidateElementInitAddMethodInfo(MethodInfo addMethod) {
+ ValidateMethodInfo(addMethod);
+ ParameterInfo[] pis = addMethod.GetParametersCached();
+ if (pis.Length == 0) {
+ throw Error.ElementInitializerMethodWithZeroArgs();
+ }
+ if (!addMethod.Name.Equals("Add", StringComparison.OrdinalIgnoreCase)) {
+ throw Error.ElementInitializerMethodNotAdd();
+ }
+ if (addMethod.IsStatic) {
+ throw Error.ElementInitializerMethodStatic();
+ }
+ foreach (ParameterInfo pi in pis) {
+ if (pi.ParameterType.IsByRef) {
+ throw Error.ElementInitializerMethodNoRefOutParam(pi.Name, addMethod.Name);
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.DebuggerProxy.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.DebuggerProxy.cs
new file mode 100644
index 00000000000..335eaf728c1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.DebuggerProxy.cs
@@ -0,0 +1,462 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.ObjectModel;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+#if !SILVERLIGHT
+ public partial class Expression {
+ #region Generated Expression Debugger Proxies
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_debug_proxies from: generate_tree.py
+
+ internal class BinaryExpressionProxy {
+ private readonly BinaryExpression _node;
+
+ public BinaryExpressionProxy(BinaryExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public LambdaExpression Conversion { get { return _node.Conversion; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Boolean IsLifted { get { return _node.IsLifted; } }
+ public Boolean IsLiftedToNull { get { return _node.IsLiftedToNull; } }
+ public Expression Left { get { return _node.Left; } }
+ public MethodInfo Method { get { return _node.Method; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression Right { get { return _node.Right; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class BlockExpressionProxy {
+ private readonly BlockExpression _node;
+
+ public BlockExpressionProxy(BlockExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ReadOnlyCollection<Expression> Expressions { get { return _node.Expressions; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression Result { get { return _node.Result; } }
+ public Type Type { get { return _node.Type; } }
+ public ReadOnlyCollection<ParameterExpression> Variables { get { return _node.Variables; } }
+ }
+
+ internal class CatchBlockProxy {
+ private readonly CatchBlock _node;
+
+ public CatchBlockProxy(CatchBlock node) {
+ _node = node;
+ }
+
+ public Expression Body { get { return _node.Body; } }
+ public Expression Filter { get { return _node.Filter; } }
+ public Type Test { get { return _node.Test; } }
+ public ParameterExpression Variable { get { return _node.Variable; } }
+ }
+
+ internal class ConditionalExpressionProxy {
+ private readonly ConditionalExpression _node;
+
+ public ConditionalExpressionProxy(ConditionalExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression IfFalse { get { return _node.IfFalse; } }
+ public Expression IfTrue { get { return _node.IfTrue; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression Test { get { return _node.Test; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class ConstantExpressionProxy {
+ private readonly ConstantExpression _node;
+
+ public ConstantExpressionProxy(ConstantExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ public Object Value { get { return _node.Value; } }
+ }
+
+ internal class DebugInfoExpressionProxy {
+ private readonly DebugInfoExpression _node;
+
+ public DebugInfoExpressionProxy(DebugInfoExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public SymbolDocumentInfo Document { get { return _node.Document; } }
+ public Int32 EndColumn { get { return _node.EndColumn; } }
+ public Int32 EndLine { get { return _node.EndLine; } }
+ public Boolean IsClear { get { return _node.IsClear; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Int32 StartColumn { get { return _node.StartColumn; } }
+ public Int32 StartLine { get { return _node.StartLine; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class DefaultExpressionProxy {
+ private readonly DefaultExpression _node;
+
+ public DefaultExpressionProxy(DefaultExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class DynamicExpressionProxy {
+ private readonly DynamicExpression _node;
+
+ public DynamicExpressionProxy(DynamicExpression node) {
+ _node = node;
+ }
+
+ public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
+ public CallSiteBinder Binder { get { return _node.Binder; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Type DelegateType { get { return _node.DelegateType; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class GotoExpressionProxy {
+ private readonly GotoExpression _node;
+
+ public GotoExpressionProxy(GotoExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public GotoExpressionKind Kind { get { return _node.Kind; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public LabelTarget Target { get { return _node.Target; } }
+ public Type Type { get { return _node.Type; } }
+ public Expression Value { get { return _node.Value; } }
+ }
+
+ internal class IndexExpressionProxy {
+ private readonly IndexExpression _node;
+
+ public IndexExpressionProxy(IndexExpression node) {
+ _node = node;
+ }
+
+ public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public PropertyInfo Indexer { get { return _node.Indexer; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression Object { get { return _node.Object; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class InvocationExpressionProxy {
+ private readonly InvocationExpression _node;
+
+ public InvocationExpressionProxy(InvocationExpression node) {
+ _node = node;
+ }
+
+ public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression Expression { get { return _node.Expression; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class LabelExpressionProxy {
+ private readonly LabelExpression _node;
+
+ public LabelExpressionProxy(LabelExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression DefaultValue { get { return _node.DefaultValue; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public LabelTarget Target { get { return _node.Target; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class LambdaExpressionProxy {
+ private readonly LambdaExpression _node;
+
+ public LambdaExpressionProxy(LambdaExpression node) {
+ _node = node;
+ }
+
+ public Expression Body { get { return _node.Body; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public String Name { get { return _node.Name; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public ReadOnlyCollection<ParameterExpression> Parameters { get { return _node.Parameters; } }
+ public Type ReturnType { get { return _node.ReturnType; } }
+ public Boolean TailCall { get { return _node.TailCall; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class ListInitExpressionProxy {
+ private readonly ListInitExpression _node;
+
+ public ListInitExpressionProxy(ListInitExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ReadOnlyCollection<ElementInit> Initializers { get { return _node.Initializers; } }
+ public NewExpression NewExpression { get { return _node.NewExpression; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class LoopExpressionProxy {
+ private readonly LoopExpression _node;
+
+ public LoopExpressionProxy(LoopExpression node) {
+ _node = node;
+ }
+
+ public Expression Body { get { return _node.Body; } }
+ public LabelTarget BreakLabel { get { return _node.BreakLabel; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public LabelTarget ContinueLabel { get { return _node.ContinueLabel; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class MemberExpressionProxy {
+ private readonly MemberExpression _node;
+
+ public MemberExpressionProxy(MemberExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression Expression { get { return _node.Expression; } }
+ public MemberInfo Member { get { return _node.Member; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class MemberInitExpressionProxy {
+ private readonly MemberInitExpression _node;
+
+ public MemberInitExpressionProxy(MemberInitExpression node) {
+ _node = node;
+ }
+
+ public ReadOnlyCollection<MemberBinding> Bindings { get { return _node.Bindings; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public NewExpression NewExpression { get { return _node.NewExpression; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class MethodCallExpressionProxy {
+ private readonly MethodCallExpression _node;
+
+ public MethodCallExpressionProxy(MethodCallExpression node) {
+ _node = node;
+ }
+
+ public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public MethodInfo Method { get { return _node.Method; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression Object { get { return _node.Object; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class NewArrayExpressionProxy {
+ private readonly NewArrayExpression _node;
+
+ public NewArrayExpressionProxy(NewArrayExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ReadOnlyCollection<Expression> Expressions { get { return _node.Expressions; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class NewExpressionProxy {
+ private readonly NewExpression _node;
+
+ public NewExpressionProxy(NewExpression node) {
+ _node = node;
+ }
+
+ public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public ConstructorInfo Constructor { get { return _node.Constructor; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ReadOnlyCollection<MemberInfo> Members { get { return _node.Members; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class ParameterExpressionProxy {
+ private readonly ParameterExpression _node;
+
+ public ParameterExpressionProxy(ParameterExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Boolean IsByRef { get { return _node.IsByRef; } }
+ public String Name { get { return _node.Name; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class RuntimeVariablesExpressionProxy {
+ private readonly RuntimeVariablesExpression _node;
+
+ public RuntimeVariablesExpressionProxy(RuntimeVariablesExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ public ReadOnlyCollection<ParameterExpression> Variables { get { return _node.Variables; } }
+ }
+
+ internal class SwitchCaseProxy {
+ private readonly SwitchCase _node;
+
+ public SwitchCaseProxy(SwitchCase node) {
+ _node = node;
+ }
+
+ public Expression Body { get { return _node.Body; } }
+ public ReadOnlyCollection<Expression> TestValues { get { return _node.TestValues; } }
+ }
+
+ internal class SwitchExpressionProxy {
+ private readonly SwitchExpression _node;
+
+ public SwitchExpressionProxy(SwitchExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public ReadOnlyCollection<SwitchCase> Cases { get { return _node.Cases; } }
+ public MethodInfo Comparison { get { return _node.Comparison; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression DefaultBody { get { return _node.DefaultBody; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression SwitchValue { get { return _node.SwitchValue; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class TryExpressionProxy {
+ private readonly TryExpression _node;
+
+ public TryExpressionProxy(TryExpression node) {
+ _node = node;
+ }
+
+ public Expression Body { get { return _node.Body; } }
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression Fault { get { return _node.Fault; } }
+ public Expression Finally { get { return _node.Finally; } }
+ public ReadOnlyCollection<CatchBlock> Handlers { get { return _node.Handlers; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ internal class TypeBinaryExpressionProxy {
+ private readonly TypeBinaryExpression _node;
+
+ public TypeBinaryExpressionProxy(TypeBinaryExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Expression Expression { get { return _node.Expression; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Type Type { get { return _node.Type; } }
+ public Type TypeOperand { get { return _node.TypeOperand; } }
+ }
+
+ internal class UnaryExpressionProxy {
+ private readonly UnaryExpression _node;
+
+ public UnaryExpressionProxy(UnaryExpression node) {
+ _node = node;
+ }
+
+ public Boolean CanReduce { get { return _node.CanReduce; } }
+ public String DebugView { get { return _node.DebugView; } }
+ public Boolean IsLifted { get { return _node.IsLifted; } }
+ public Boolean IsLiftedToNull { get { return _node.IsLiftedToNull; } }
+ public MethodInfo Method { get { return _node.Method; } }
+ public ExpressionType NodeType { get { return _node.NodeType; } }
+ public Expression Operand { get { return _node.Operand; } }
+ public Type Type { get { return _node.Type; } }
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ }
+#endif
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.cs
new file mode 100644
index 00000000000..9a79ee68251
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/Expression.cs
@@ -0,0 +1,403 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Threading;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// The base type for all nodes in Expression Trees.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ public abstract partial class Expression {
+ private delegate LambdaExpression LambdaFactory(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters);
+
+ private static readonly CacheDict<Type, MethodInfo> _LambdaDelegateCache = new CacheDict<Type, MethodInfo>(40);
+ private static CacheDict<Type, LambdaFactory> _LambdaFactories;
+
+ // LINQ protected ctor from 3.5
+
+#if !MICROSOFT_SCRIPTING_CORE // needs ConditionWeakTable in 4.0
+
+ // For 4.0, many frequently used Expression nodes have had their memory
+ // footprint reduced by removing the Type and NodeType fields. This has
+ // large performance benefits to all users of Expression Trees.
+ //
+ // To support the 3.5 protected constructor, we store the fields that
+ // used to be here in a ConditionalWeakTable.
+
+ private class ExtensionInfo {
+ public ExtensionInfo(ExpressionType nodeType, Type type) {
+ NodeType = nodeType;
+ Type = type;
+ }
+
+ internal readonly ExpressionType NodeType;
+ internal readonly Type Type;
+ }
+
+ private static ConditionalWeakTable<Expression, ExtensionInfo> _legacyCtorSupportTable;
+
+ /// <summary>
+ /// Constructs a new instance of <see cref="Expression"/>.
+ /// </summary>
+ /// <param name="nodeType">The <see ctype="ExpressionType"/> of the <see cref="Expression"/>.</param>
+ /// <param name="type">The <see cref="Type"/> of the <see cref="Expression"/>.</param>
+ [Obsolete("use a different constructor that does not take ExpressionType. Then override NodeType and Type properties to provide the values that would be specified to this constructor.")]
+ protected Expression(ExpressionType nodeType, Type type) {
+ // Can't enforce anything that V1 didn't
+ if (_legacyCtorSupportTable == null) {
+ Interlocked.CompareExchange(
+ ref _legacyCtorSupportTable,
+ new ConditionalWeakTable<Expression, ExtensionInfo>(),
+ null
+ );
+ }
+
+ _legacyCtorSupportTable.Add(this, new ExtensionInfo(nodeType, type));
+ }
+#endif
+
+ /// <summary>
+ /// Constructs a new instance of <see cref="Expression"/>.
+ /// </summary>
+ protected Expression() {
+ }
+
+ /// <summary>
+ /// The <see cref="ExpressionType"/> of the <see cref="Expression"/>.
+ /// </summary>
+ public virtual ExpressionType NodeType {
+ get {
+#if !MICROSOFT_SCRIPTING_CORE
+ ExtensionInfo extInfo;
+ if (_legacyCtorSupportTable.TryGetValue(this, out extInfo)) {
+ return extInfo.NodeType;
+ }
+#endif
+ // the extension expression failed to override NodeType
+ throw Error.ExtensionNodeMustOverrideProperty("Expression.NodeType");
+ }
+ }
+
+
+ /// <summary>
+ /// The <see cref="Type"/> of the value represented by this <see cref="Expression"/>.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
+ public virtual Type Type {
+ get {
+#if !MICROSOFT_SCRIPTING_CORE
+ ExtensionInfo extInfo;
+ if (_legacyCtorSupportTable.TryGetValue(this, out extInfo)) {
+ return extInfo.Type;
+ }
+#endif
+ // the extension expression failed to override Type
+ throw Error.ExtensionNodeMustOverrideProperty("Expression.Type");
+ }
+ }
+
+ /// <summary>
+ /// Indicates that the node can be reduced to a simpler node. If this
+ /// returns true, Reduce() can be called to produce the reduced form.
+ /// </summary>
+ public virtual bool CanReduce {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Reduces this node to a simpler expression. If CanReduce returns
+ /// true, this should return a valid expression. This method is
+ /// allowed to return another node which itself must be reduced.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ public virtual Expression Reduce() {
+ ContractUtils.Requires(!CanReduce, "this", Strings.ReducibleMustOverrideReduce);
+ return this;
+ }
+
+ /// <summary>
+ /// Reduces the node and then calls the visitor delegate on the reduced expression.
+ /// Throws an exception if the node isn't reducible.
+ /// </summary>
+ /// <param name="visitor">An instance of <see cref="Func{Expression, Expression}"/>.</param>
+ /// <returns>The expression being visited, or an expression which should replace it in the tree.</returns>
+ /// <remarks>
+ /// Override this method to provide logic to walk the node's children.
+ /// A typical implementation will call visitor.Visit on each of its
+ /// children, and if any of them change, should return a new copy of
+ /// itself with the modified children.
+ /// </remarks>
+ protected internal virtual Expression VisitChildren(Func<Expression, Expression> visitor) {
+ ContractUtils.Requires(CanReduce, "this", Strings.MustBeReducible);
+ return visitor(ReduceExtensions());
+ }
+
+ // Visitor pattern: this is the method that dispatches back to the visitor
+ // NOTE: this is unlike the Visit method, which provides a hook for
+ // derived classes to extend the visitor framework to be able to walk
+ // themselves
+ internal virtual Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitExtension(this);
+ }
+
+ /// <summary>
+ /// Reduces this node to a simpler expression. If CanReduce returns
+ /// true, this should return a valid expression. This method is
+ /// allowed to return another node which itself must be reduced.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ /// <remarks >
+ /// Unlike Reduce, this method checks that the reduced node satisfies
+ /// certain invariants.
+ /// </remarks>
+ public Expression ReduceAndCheck() {
+ ContractUtils.Requires(CanReduce, "this", Strings.MustBeReducible);
+
+ var newNode = Reduce();
+
+ // 1. Reduction must return a new, non-null node
+ // 2. Reduction must return a new node whose result type can be assigned to the type of the original node
+ ContractUtils.Requires(newNode != null && newNode != this, "this", Strings.MustReduceToDifferent);
+ ContractUtils.Requires(TypeUtils.AreReferenceAssignable(Type, newNode.Type), "this", Strings.ReducedNotCompatible);
+ return newNode;
+ }
+
+ /// <summary>
+ /// Reduces the expression to a known node type (i.e. not an Extension node)
+ /// or simply returns the expression if it is already a known type.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ public Expression ReduceExtensions() {
+ var node = this;
+ while (node.NodeType == ExpressionType.Extension) {
+ node = node.ReduceAndCheck();
+ }
+ return node;
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="String"/> representation of the Expression.
+ /// </summary>
+ /// <returns>A <see cref="String"/> representation of the Expression.</returns>
+ public override string ToString() {
+ return ExpressionStringBuilder.ExpressionToString(this);
+ }
+
+#if MICROSOFT_SCRIPTING_CORE
+ /// <summary>
+ /// Writes a <see cref="String"/> representation of the <see cref="Expression"/> to a <see cref="TextWriter"/>.
+ /// </summary>
+ /// <param name="writer">A <see cref="TextWriter"/> that will be used to build the string representation.</param>
+ public void DumpExpression(TextWriter writer) {
+ DebugViewWriter.WriteTo(this, writer);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="String"/> representation of the Expression.
+ /// </summary>
+ /// <returns>A <see cref="String"/> representation of the Expression.</returns>
+ public string DebugView {
+#else
+ private string DebugView {
+#endif
+ get {
+ using (System.IO.StringWriter writer = new System.IO.StringWriter(CultureInfo.CurrentCulture)) {
+ DebugViewWriter.WriteTo(this, writer);
+ return writer.ToString();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
+ ///
+ /// This is called from various methods where we internally hold onto an IList of T
+ /// or a readonly collection of T. We check to see if we've already returned a
+ /// readonly collection of T and if so simply return the other one. Otherwise we do
+ /// a thread-safe replacement of the list w/ a readonly collection which wraps it.
+ ///
+ /// Ultimately this saves us from having to allocate a ReadOnlyCollection for our
+ /// data types because the compiler is capable of going directly to the IList of T.
+ /// </summary>
+ internal static ReadOnlyCollection<T> ReturnReadOnly<T>(ref IList<T> collection) {
+ IList<T> value = collection;
+
+ // if it's already read-only just return it.
+ ReadOnlyCollection<T> res = value as ReadOnlyCollection<T>;
+ if (res != null) {
+ return res;
+ }
+
+ // otherwise make sure only readonly collection every gets exposed
+ Interlocked.CompareExchange<IList<T>>(
+ ref collection,
+ value.ToReadOnly(),
+ value
+ );
+
+ // and return it
+ return (ReadOnlyCollection<T>)collection;
+ }
+
+ /// <summary>
+ /// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
+ ///
+ /// This is similar to the ReturnReadOnly of T. This version supports nodes which hold
+ /// onto multiple Expressions where one is typed to object. That object field holds either
+ /// an expression or a ReadOnlyCollection of Expressions. When it holds a ReadOnlyCollection
+ /// the IList which backs it is a ListArgumentProvider which uses the Expression which
+ /// implements IArgumentProvider to get 2nd and additional values. The ListArgumentProvider
+ /// continues to hold onto the 1st expression.
+ ///
+ /// This enables users to get the ReadOnlyCollection w/o it consuming more memory than if
+ /// it was just an array. Meanwhile The DLR internally avoids accessing which would force
+ /// the readonly collection to be created resulting in a typical memory savings.
+ /// </summary>
+ internal static ReadOnlyCollection<Expression> ReturnReadOnly(IArgumentProvider provider, ref object collection) {
+ Expression tObj = collection as Expression;
+ if (tObj != null) {
+ // otherwise make sure only one readonly collection ever gets exposed
+ Interlocked.CompareExchange(
+ ref collection,
+ new ReadOnlyCollection<Expression>(new ListArgumentProvider(provider, tObj)),
+ tObj
+ );
+ }
+
+ // and return what is not guaranteed to be a readonly collection
+ return (ReadOnlyCollection<Expression>)collection;
+ }
+
+ /// <summary>
+ /// Helper which is used for specialized subtypes which use ReturnReadOnly(ref object, ...).
+ /// This is the reverse version of ReturnReadOnly which takes an IArgumentProvider.
+ ///
+ /// This is used to return the 1st argument. The 1st argument is typed as object and either
+ /// contains a ReadOnlyCollection or the Expression. We check for the Expression and if it's
+ /// present we return that, otherwise we return the 1st element of the ReadOnlyCollection.
+ /// </summary>
+ internal static T ReturnObject<T>(object collectionOrT) where T : class {
+ T t = collectionOrT as T;
+ if (t != null) {
+ return t;
+ }
+
+ return ((ReadOnlyCollection<T>)collectionOrT)[0];
+ }
+
+ private static void RequiresCanRead(Expression expression, string paramName) {
+ if (expression == null) {
+ throw new ArgumentNullException(paramName);
+ }
+
+ // validate that we can read the node
+ switch (expression.NodeType) {
+ case ExpressionType.Index:
+ IndexExpression index = (IndexExpression)expression;
+ if (index.Indexer != null && !index.Indexer.CanRead) {
+ throw new ArgumentException(Strings.ExpressionMustBeReadable, paramName);
+ }
+ break;
+ case ExpressionType.MemberAccess:
+ MemberExpression member = (MemberExpression)expression;
+ MemberInfo memberInfo = member.Member;
+ if (memberInfo.MemberType == MemberTypes.Property) {
+ PropertyInfo prop = (PropertyInfo)memberInfo;
+ if (!prop.CanRead) {
+ throw new ArgumentException(Strings.ExpressionMustBeReadable, paramName);
+ }
+ }
+ break;
+ }
+ }
+
+ private static void RequiresCanRead(IEnumerable<Expression> items, string paramName) {
+ if (items != null) {
+ // this is called a lot, avoid allocating an enumerator if we can...
+ IList<Expression> listItems = items as IList<Expression>;
+ if (listItems != null) {
+ for (int i = 0; i < listItems.Count; i++) {
+ RequiresCanRead(listItems[i], paramName);
+ }
+ return;
+ }
+
+ foreach (var i in items) {
+ RequiresCanRead(i, paramName);
+ }
+ }
+ }
+ private static void RequiresCanWrite(Expression expression, string paramName) {
+ if (expression == null) {
+ throw new ArgumentNullException(paramName);
+ }
+
+ bool canWrite = false;
+ switch (expression.NodeType) {
+ case ExpressionType.Index:
+ IndexExpression index = (IndexExpression)expression;
+ if (index.Indexer != null) {
+ canWrite = index.Indexer.CanWrite;
+ } else {
+ canWrite = true;
+ }
+ break;
+ case ExpressionType.MemberAccess:
+ MemberExpression member = (MemberExpression)expression;
+ switch (member.Member.MemberType) {
+ case MemberTypes.Property:
+ PropertyInfo prop = (PropertyInfo)member.Member;
+ canWrite = prop.CanWrite;
+ break;
+ case MemberTypes.Field:
+ FieldInfo field = (FieldInfo)member.Member;
+ canWrite = !(field.IsInitOnly || field.IsLiteral);
+ break;
+ }
+ break;
+ case ExpressionType.Parameter:
+ canWrite = true;
+ break;
+ }
+
+ if (!canWrite) {
+ throw new ArgumentException(Strings.ExpressionMustBeWriteable, paramName);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionStringBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionStringBuilder.cs
new file mode 100644
index 00000000000..7e8ee3c7512
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionStringBuilder.cs
@@ -0,0 +1,755 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Text;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ internal sealed class ExpressionStringBuilder : ExpressionVisitor {
+ private StringBuilder _out;
+
+ // Associate every unique label or anonymous parameter in the tree with an integer.
+ // The label is displayed as Label_#.
+ private Dictionary<object, int> _ids;
+
+ private ExpressionStringBuilder() {
+ _out = new StringBuilder();
+ }
+
+ public override string ToString() {
+ return _out.ToString();
+ }
+
+ private void AddLabel(LabelTarget label) {
+ if (_ids == null) {
+ _ids = new Dictionary<object, int>();
+ _ids.Add(label, 0);
+ } else {
+ if (!_ids.ContainsKey(label)) {
+ _ids.Add(label, _ids.Count);
+ }
+ }
+ }
+
+ private int GetLabelId(LabelTarget label) {
+ if (_ids == null) {
+ _ids = new Dictionary<object, int>();
+ AddLabel(label);
+ return 0;
+ } else {
+ int id;
+ if (!_ids.TryGetValue(label, out id)) {
+ //label is met the first time
+ id = _ids.Count;
+ AddLabel(label);
+ }
+ return id;
+ }
+ }
+
+ private void AddParam(ParameterExpression p) {
+ if (_ids == null) {
+ _ids = new Dictionary<object, int>();
+ _ids.Add(_ids, 0);
+ } else {
+ if (!_ids.ContainsKey(p)) {
+ _ids.Add(p, _ids.Count);
+ }
+ }
+ }
+
+ private int GetParamId(ParameterExpression p) {
+ if (_ids == null) {
+ _ids = new Dictionary<object, int>();
+ AddParam(p);
+ return 0;
+ } else {
+ int id;
+ if (!_ids.TryGetValue(p, out id)) {
+ // p is met the first time
+ id = _ids.Count;
+ AddParam(p);
+ }
+ return id;
+ }
+ }
+
+ #region The printing code
+
+ private void Out(string s) {
+ _out.Append(s);
+ }
+
+ private void Out(char c) {
+ _out.Append(c);
+ }
+
+ #endregion
+
+ #region Output an expresstion tree to a string
+
+ /// <summary>
+ /// Output a given expression tree to a string.
+ /// </summary>
+ internal static string ExpressionToString(Expression node) {
+ Debug.Assert(node != null);
+ ExpressionStringBuilder esb = new ExpressionStringBuilder();
+ esb.Visit(node);
+ return esb.ToString();
+ }
+
+ internal static string CatchBlockToString(CatchBlock node) {
+ Debug.Assert(node != null);
+ ExpressionStringBuilder esb = new ExpressionStringBuilder();
+ esb.VisitCatchBlock(node);
+ return esb.ToString();
+ }
+
+ internal static string SwitchCaseToString(SwitchCase node) {
+ Debug.Assert(node != null);
+ ExpressionStringBuilder esb = new ExpressionStringBuilder();
+ esb.VisitSwitchCase(node);
+ return esb.ToString();
+ }
+
+ /// <summary>
+ /// Output a given member binding to a string.
+ /// </summary>
+ internal static string MemberBindingToString(MemberBinding node) {
+ Debug.Assert(node != null);
+ ExpressionStringBuilder esb = new ExpressionStringBuilder();
+ esb.VisitMemberBinding(node);
+ return esb.ToString();
+ }
+
+ /// <summary>
+ /// Output a given ElementInit to a string.
+ /// </summary>
+ internal static string ElementInitBindingToString(ElementInit node) {
+ Debug.Assert(node != null);
+ ExpressionStringBuilder esb = new ExpressionStringBuilder();
+ esb.VisitElementInit(node);
+ return esb.ToString();
+ }
+
+ // More proper would be to make this a virtual method on Action
+ private static string FormatBinder(CallSiteBinder binder) {
+ ConvertBinder convert;
+ GetMemberBinder getMember;
+ SetMemberBinder setMember;
+ DeleteMemberBinder deleteMember;
+ GetIndexBinder getIndex;
+ SetIndexBinder setIndex;
+ DeleteIndexBinder deleteIndex;
+ InvokeMemberBinder call;
+ InvokeBinder invoke;
+ CreateInstanceBinder create;
+ UnaryOperationBinder unary;
+ BinaryOperationBinder binary;
+
+ if ((convert = binder as ConvertBinder) != null) {
+ return "Convert " + convert.Type;
+ } else if ((getMember = binder as GetMemberBinder) != null) {
+ return "GetMember " + getMember.Name;
+ } else if ((setMember = binder as SetMemberBinder) != null) {
+ return "SetMember " + setMember.Name;
+ } else if ((deleteMember = binder as DeleteMemberBinder) != null) {
+ return "DeleteMember " + deleteMember.Name;
+ } else if ((getIndex = binder as GetIndexBinder) != null) {
+ return "GetIndex";
+ } else if ((setIndex = binder as SetIndexBinder) != null) {
+ return "SetIndex";
+ } else if ((deleteIndex = binder as DeleteIndexBinder) != null) {
+ return "DeleteIndex";
+ } else if ((call = binder as InvokeMemberBinder) != null) {
+ return "Call " + call.Name;
+ } else if ((invoke = binder as InvokeBinder) != null) {
+ return "Invoke";
+ } else if ((create = binder as CreateInstanceBinder) != null) {
+ return "Create";
+ } else if ((unary = binder as UnaryOperationBinder) != null) {
+ return unary.Operation.ToString();
+ } else if ((binary = binder as BinaryOperationBinder) != null) {
+ return binary.Operation.ToString();
+ } else {
+ return "CallSiteBinder";
+ }
+ }
+
+ private void VisitExpressions<T>(char open, IList<T> expressions, char close) where T : Expression {
+ Out(open);
+ if (expressions != null) {
+ bool isFirst = true;
+ foreach (T e in expressions) {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ Out(", ");
+ }
+ Visit(e);
+ }
+ }
+ Out(close);
+ }
+
+ protected internal override Expression VisitDynamic(DynamicExpression node) {
+ Out(FormatBinder(node.Binder));
+ VisitExpressions('(', node.Arguments, ')');
+ return node;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ protected internal override Expression VisitBinary(BinaryExpression node) {
+ if (node.NodeType == ExpressionType.ArrayIndex) {
+ Visit(node.Left);
+ Out("[");
+ Visit(node.Right);
+ Out("]");
+ } else {
+ string op;
+ switch (node.NodeType) {
+ case ExpressionType.Assign: op = "="; break;
+ case ExpressionType.Equal: op = "=="; break;
+ case ExpressionType.NotEqual: op = "!="; break;
+ case ExpressionType.AndAlso: op = "AndAlso"; break;
+ case ExpressionType.OrElse: op = "OrElse"; break;
+ case ExpressionType.GreaterThan: op = ">"; break;
+ case ExpressionType.LessThan: op = "<"; break;
+ case ExpressionType.GreaterThanOrEqual: op = ">="; break;
+ case ExpressionType.LessThanOrEqual: op = "<="; break;
+ case ExpressionType.Add: op = "+"; break;
+ case ExpressionType.AddAssign: op = "+="; break;
+ case ExpressionType.AddAssignChecked: op = "+="; break;
+ case ExpressionType.AddChecked: op = "+"; break;
+ case ExpressionType.Subtract: op = "-"; break;
+ case ExpressionType.SubtractAssign: op = "-="; break;
+ case ExpressionType.SubtractAssignChecked: op = "-="; break;
+ case ExpressionType.SubtractChecked: op = "-"; break;
+ case ExpressionType.Divide: op = "/"; break;
+ case ExpressionType.DivideAssign: op = "/="; break;
+ case ExpressionType.Modulo: op = "%"; break;
+ case ExpressionType.ModuloAssign: op = "%="; break;
+ case ExpressionType.Multiply: op = "*"; break;
+ case ExpressionType.MultiplyAssign: op = "*="; break;
+ case ExpressionType.MultiplyAssignChecked: op = "*="; break;
+ case ExpressionType.MultiplyChecked: op = "*"; break;
+ case ExpressionType.LeftShift: op = "<<"; break;
+ case ExpressionType.LeftShiftAssign: op = "<<="; break;
+ case ExpressionType.RightShift: op = ">>"; break;
+ case ExpressionType.RightShiftAssign: op = ">>="; break;
+ case ExpressionType.And:
+ if (node.Type == typeof(bool) || node.Type == typeof(bool?)) {
+ op = "And";
+ } else {
+ op = "&";
+ }
+ break;
+ case ExpressionType.AndAssign:
+ if (node.Type == typeof(bool) || node.Type == typeof(bool?)) {
+ op = "&&=";
+ } else {
+ op = "&=";
+ }
+ break;
+ case ExpressionType.Or:
+ if (node.Type == typeof(bool) || node.Type == typeof(bool?)) {
+ op = "Or";
+ } else {
+ op = "|";
+ }
+ break;
+ case ExpressionType.OrAssign:
+ if (node.Type == typeof(bool) || node.Type == typeof(bool?)) {
+ op = "||=";
+ } else { op = "|="; }
+ break;
+ case ExpressionType.ExclusiveOr: op = "^"; break;
+ case ExpressionType.ExclusiveOrAssign: op = "^="; break;
+ case ExpressionType.Power: op = "^"; break;
+ case ExpressionType.PowerAssign: op = "**="; break;
+ case ExpressionType.Coalesce: op = "??"; break;
+
+ default:
+ throw new InvalidOperationException();
+ }
+ Out("(");
+ Visit(node.Left);
+ Out(' ');
+ Out(op);
+ Out(' ');
+ Visit(node.Right);
+ Out(")");
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitParameter(ParameterExpression node) {
+ if (node.IsByRef) {
+ Out("ref ");
+ }
+ if (String.IsNullOrEmpty(node.Name)) {
+ int id = GetParamId(node);
+ Out("Param_" + id);
+ } else {
+ Out(node.Name);
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitLambda<T>(Expression<T> node) {
+ if (node.Parameters.Count == 1) {
+ // p => body
+ Visit(node.Parameters[0]);
+ } else {
+ // (p1, p2, ..., pn) => body
+ VisitExpressions('(', node.Parameters, ')');
+ }
+ Out(" => ");
+ Visit(node.Body);
+ return node;
+ }
+
+ protected internal override Expression VisitListInit(ListInitExpression node) {
+ Visit(node.NewExpression);
+ Out(" {");
+ for (int i = 0, n = node.Initializers.Count; i < n; i++) {
+ if (i > 0) {
+ Out(", ");
+ }
+ Out(node.Initializers[i].ToString());
+ }
+ Out("}");
+ return node;
+ }
+
+ protected internal override Expression VisitConditional(ConditionalExpression node) {
+ Out("IIF(");
+ Visit(node.Test);
+ Out(", ");
+ Visit(node.IfTrue);
+ Out(", ");
+ Visit(node.IfFalse);
+ Out(")");
+ return node;
+ }
+
+ protected internal override Expression VisitConstant(ConstantExpression node) {
+ if (node.Value != null) {
+ string sValue = node.Value.ToString();
+ if (node.Value is string) {
+ Out("\"");
+ Out(sValue);
+ Out("\"");
+ } else if (sValue == node.Value.GetType().ToString()) {
+ Out("value(");
+ Out(sValue);
+ Out(")");
+ } else {
+ Out(sValue);
+ }
+ } else {
+ Out("null");
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitDebugInfo(DebugInfoExpression node) {
+ string s = String.Format(
+ CultureInfo.CurrentCulture,
+ "<DebugInfo({0}: {1}, {2}, {3}, {4})>",
+ node.Document.FileName,
+ node.StartLine,
+ node.StartColumn,
+ node.EndLine,
+ node.EndColumn
+ );
+ Out(s);
+ return node;
+ }
+
+ protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
+ VisitExpressions('(', node.Variables, ')');
+ return node;
+ }
+
+ // Prints ".instanceField" or "declaringType.staticField"
+ private void OutMember(Expression instance, MemberInfo member) {
+ if (instance != null) {
+ Visit(instance);
+ Out("." + member.Name);
+ } else {
+ // For static members, include the type name
+ Out(member.DeclaringType.Name + "." + member.Name);
+ }
+ }
+
+ protected internal override Expression VisitMember(MemberExpression node) {
+ OutMember(node.Expression, node.Member);
+ return node;
+ }
+
+ protected internal override Expression VisitMemberInit(MemberInitExpression node) {
+ if (node.NewExpression.Arguments.Count == 0 &&
+ node.NewExpression.Type.Name.Contains("<")) {
+ // anonymous type constructor
+ Out("new");
+ } else {
+ Visit(node.NewExpression);
+ }
+ Out(" {");
+ for (int i = 0, n = node.Bindings.Count; i < n; i++) {
+ MemberBinding b = node.Bindings[i];
+ if (i > 0) {
+ Out(", ");
+ }
+ VisitMemberBinding(b);
+ }
+ Out("}");
+ return node;
+ }
+
+ protected override MemberAssignment VisitMemberAssignment(MemberAssignment assignment) {
+ Out(assignment.Member.Name);
+ Out(" = ");
+ Visit(assignment.Expression);
+ return assignment;
+ }
+
+ protected override MemberListBinding VisitMemberListBinding(MemberListBinding binding) {
+ Out(binding.Member.Name);
+ Out(" = {");
+ for (int i = 0, n = binding.Initializers.Count; i < n; i++) {
+ if (i > 0) {
+ Out(", ");
+ }
+ VisitElementInit(binding.Initializers[i]);
+ }
+ Out("}");
+ return binding;
+ }
+
+ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) {
+ Out(binding.Member.Name);
+ Out(" = {");
+ for (int i = 0, n = binding.Bindings.Count; i < n; i++) {
+ if (i > 0) {
+ Out(", ");
+ }
+ VisitMemberBinding(binding.Bindings[i]);
+ }
+ Out("}");
+ return binding;
+ }
+
+ protected override ElementInit VisitElementInit(ElementInit initializer) {
+ Out(initializer.AddMethod.ToString());
+ VisitExpressions('(', initializer.Arguments, ')');
+ return initializer;
+ }
+
+ protected internal override Expression VisitInvocation(InvocationExpression node) {
+ Out("Invoke(");
+ Visit(node.Expression);
+ for (int i = 0, n = node.Arguments.Count; i < n; i++) {
+ Out(", ");
+ Visit(node.Arguments[i]);
+ }
+ Out(")");
+ return node;
+ }
+
+ protected internal override Expression VisitMethodCall(MethodCallExpression node) {
+ int start = 0;
+ Expression ob = node.Object;
+
+ if (Attribute.GetCustomAttribute(node.Method, typeof(ExtensionAttribute)) != null) {
+ start = 1;
+ ob = node.Arguments[0];
+ }
+
+ if (ob != null) {
+ Visit(ob);
+ Out(".");
+ }
+ Out(node.Method.Name);
+ Out("(");
+ for (int i = start, n = node.Arguments.Count; i < n; i++) {
+ if (i > start)
+ Out(", ");
+ Visit(node.Arguments[i]);
+ }
+ Out(")");
+ return node;
+ }
+
+ protected internal override Expression VisitNewArray(NewArrayExpression node) {
+ switch (node.NodeType) {
+ case ExpressionType.NewArrayBounds:
+ // new MyType[](expr1, expr2)
+ Out("new " + node.Type.ToString());
+ VisitExpressions('(', node.Expressions, ')');
+ break;
+ case ExpressionType.NewArrayInit:
+ // new [] {expr1, expr2}
+ Out("new [] ");
+ VisitExpressions('{', node.Expressions, '}');
+ break;
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitNew(NewExpression node) {
+ Out("new " + node.Type.Name);
+ Out("(");
+ for (int i = 0; i < node.Arguments.Count; i++) {
+ if (i > 0) {
+ Out(", ");
+ }
+ if (node.Members != null) {
+ Out(node.Members[i].Name);
+ Out(" = ");
+ }
+ Visit(node.Arguments[i]);
+ }
+ Out(")");
+ return node;
+ }
+
+ protected internal override Expression VisitTypeBinary(TypeBinaryExpression node) {
+ Out("(");
+ Visit(node.Expression);
+ switch (node.NodeType) {
+ case ExpressionType.TypeIs:
+ Out(" Is ");
+ break;
+ case ExpressionType.TypeEqual:
+ Out(" TypeEqual ");
+ break;
+ }
+ Out(node.TypeOperand.Name);
+ Out(")");
+ return node;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ protected internal override Expression VisitUnary(UnaryExpression node) {
+ switch (node.NodeType) {
+ case ExpressionType.TypeAs:
+ Out("(");
+ break;
+ case ExpressionType.Not:
+ Out("Not(");
+ break;
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ Out("-");
+ break;
+ case ExpressionType.UnaryPlus:
+ Out("+");
+ break;
+ case ExpressionType.Quote:
+ break;
+ case ExpressionType.Throw:
+ Out("throw(");
+ break;
+ case ExpressionType.Increment:
+ Out("Increment(");
+ break;
+ case ExpressionType.Decrement:
+ Out("Decrement(");
+ break;
+ case ExpressionType.PreIncrementAssign:
+ Out("++");
+ break;
+ case ExpressionType.PreDecrementAssign:
+ Out("--");
+ break;
+ case ExpressionType.OnesComplement:
+ Out("~(");
+ break;
+ default:
+ Out(node.NodeType.ToString());
+ Out("(");
+ break;
+ }
+
+ Visit(node.Operand);
+
+ switch (node.NodeType) {
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.UnaryPlus:
+ case ExpressionType.PreDecrementAssign:
+ case ExpressionType.PreIncrementAssign:
+ case ExpressionType.Quote:
+ break;
+ case ExpressionType.TypeAs:
+ Out(" As ");
+ Out(node.Type.Name);
+ Out(")");
+ break;
+ case ExpressionType.PostIncrementAssign:
+ Out("++");
+ break;
+ case ExpressionType.PostDecrementAssign:
+ Out("--");
+ break;
+ default:
+ Out(")");
+ break;
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitBlock(BlockExpression node) {
+ Out("{");
+ foreach (var v in node.Variables) {
+ Out("var ");
+ Visit(v);
+ Out(";");
+ }
+ Out(" ... }");
+ return node;
+ }
+
+ protected internal override Expression VisitDefault(DefaultExpression node) {
+ Out("default(");
+ Out(node.Type.Name);
+ Out(")");
+ return node;
+ }
+
+ protected internal override Expression VisitLabel(LabelExpression node) {
+ Out("{ ... } ");
+ DumpLabel(node.Target);
+ Out(":");
+ return node;
+ }
+
+ protected internal override Expression VisitGoto(GotoExpression node) {
+ Out(node.Kind.ToString().ToLower(CultureInfo.CurrentCulture));
+ DumpLabel(node.Target);
+ if (node.Value != null) {
+ Out(" (");
+ Visit(node.Value);
+ Out(") ");
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitLoop(LoopExpression node) {
+ Out("loop { ... }");
+ return node;
+ }
+
+ protected override SwitchCase VisitSwitchCase(SwitchCase node) {
+ Out("case ");
+ VisitExpressions('(', node.TestValues, ')');
+ Out(": ...");
+ return node;
+ }
+
+ protected internal override Expression VisitSwitch(SwitchExpression node) {
+ Out("switch ");
+ Out("(");
+ Visit(node.SwitchValue);
+ Out(") { ... }");
+ return node;
+ }
+
+ protected override CatchBlock VisitCatchBlock(CatchBlock node) {
+ Out("catch (" + node.Test.Name);
+ if (node.Variable != null) {
+ Out(node.Variable.Name ?? "");
+ }
+ Out(") { ... }");
+ return node;
+ }
+
+ protected internal override Expression VisitTry(TryExpression node) {
+ Out("try { ... }");
+ return node;
+ }
+
+ protected internal override Expression VisitIndex(IndexExpression node) {
+ if (node.Object != null) {
+ Visit(node.Object);
+ } else {
+ Debug.Assert(node.Indexer != null);
+ Out(node.Indexer.DeclaringType.Name);
+ }
+ if (node.Indexer != null) {
+ Out(".");
+ Out(node.Indexer.Name);
+ }
+
+ VisitExpressions('[', node.Arguments, ']');
+ return node;
+ }
+
+ protected internal override Expression VisitExtension(Expression node) {
+ // Prefer an overriden ToString, if available.
+ var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.ExactBinding;
+ var toString = node.GetType().GetMethod("ToString", flags, null, Type.EmptyTypes, null);
+ if (toString.DeclaringType != typeof(Expression)) {
+ Out(node.ToString());
+ return node;
+ }
+
+ Out("[");
+ // For 3.5 subclasses, print the NodeType.
+ // For Extension nodes, print the class name.
+ if (node.NodeType == ExpressionType.Extension) {
+ Out(node.GetType().FullName);
+ } else {
+ Out(node.NodeType.ToString());
+ }
+ Out("]");
+ return node;
+ }
+
+ private void DumpLabel(LabelTarget target) {
+ if (!String.IsNullOrEmpty(target.Name)) {
+ Out(target.Name);
+ } else {
+ int labelId = GetLabelId(target);
+ Out("UnamedLabel_" + labelId);
+ }
+ }
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionType.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionType.cs
new file mode 100644
index 00000000000..feba35e0a49
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionType.cs
@@ -0,0 +1,379 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Describes the node types for the nodes of an expression tree.
+ /// </summary>
+ public enum ExpressionType {
+
+ #region Generated Expression Tree Node Types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_tree_nodes from: generate_tree.py
+
+ /// <summary>
+ /// A node that represents arithmetic addition without overflow checking.
+ /// </summary>
+ Add,
+ /// <summary>
+ /// A node that represents arithmetic addition with overflow checking.
+ /// </summary>
+ AddChecked,
+ /// <summary>
+ /// A node that represents a bitwise AND operation.
+ /// </summary>
+ And,
+ /// <summary>
+ /// A node that represents a short-circuiting conditional AND operation.
+ /// </summary>
+ AndAlso,
+ /// <summary>
+ /// A node that represents getting the length of a one-dimensional array.
+ /// </summary>
+ ArrayLength,
+ /// <summary>
+ /// A node that represents indexing into a one-dimensional array.
+ /// </summary>
+ ArrayIndex,
+ /// <summary>
+ /// A node that represents represents a method call.
+ /// </summary>
+ Call,
+ /// <summary>
+ /// A node that represents a null coalescing operation.
+ /// </summary>
+ Coalesce,
+ /// <summary>
+ /// A node that represents a conditional operation.
+ /// </summary>
+ Conditional,
+ /// <summary>
+ /// A node that represents an expression that has a constant value.
+ /// </summary>
+ Constant,
+ /// <summary>
+ /// A node that represents a cast or conversion operation. If the operation is a numeric conversion, it overflows silently if the converted value does not fit the target type.
+ /// </summary>
+ Convert,
+ /// <summary>
+ /// A node that represents a cast or conversion operation. If the operation is a numeric conversion, an exception is thrown if the converted value does not fit the target type.
+ /// </summary>
+ ConvertChecked,
+ /// <summary>
+ /// A node that represents arithmetic division.
+ /// </summary>
+ Divide,
+ /// <summary>
+ /// A node that represents an equality comparison.
+ /// </summary>
+ Equal,
+ /// <summary>
+ /// A node that represents a bitwise XOR operation.
+ /// </summary>
+ ExclusiveOr,
+ /// <summary>
+ /// A node that represents a "greater than" numeric comparison.
+ /// </summary>
+ GreaterThan,
+ /// <summary>
+ /// A node that represents a "greater than or equal" numeric comparison.
+ /// </summary>
+ GreaterThanOrEqual,
+ /// <summary>
+ /// A node that represents applying a delegate or lambda expression to a list of argument expressions.
+ /// </summary>
+ Invoke,
+ /// <summary>
+ /// A node that represents a lambda expression.
+ /// </summary>
+ Lambda,
+ /// <summary>
+ /// A node that represents a bitwise left-shift operation.
+ /// </summary>
+ LeftShift,
+ /// <summary>
+ /// A node that represents a "less than" numeric comparison.
+ /// </summary>
+ LessThan,
+ /// <summary>
+ /// A node that represents a "less than or equal" numeric comparison.
+ /// </summary>
+ LessThanOrEqual,
+ /// <summary>
+ /// A node that represents creating a new IEnumerable object and initializing it from a list of elements.
+ /// </summary>
+ ListInit,
+ /// <summary>
+ /// A node that represents reading from a field or property.
+ /// </summary>
+ MemberAccess,
+ /// <summary>
+ /// A node that represents creating a new object and initializing one or more of its members.
+ /// </summary>
+ MemberInit,
+ /// <summary>
+ /// A node that represents an arithmetic remainder operation.
+ /// </summary>
+ Modulo,
+ /// <summary>
+ /// A node that represents arithmetic multiplication without overflow checking.
+ /// </summary>
+ Multiply,
+ /// <summary>
+ /// A node that represents arithmetic multiplication with overflow checking.
+ /// </summary>
+ MultiplyChecked,
+ /// <summary>
+ /// A node that represents an arithmetic negation operation.
+ /// </summary>
+ Negate,
+ /// <summary>
+ /// A node that represents a unary plus operation. The result of a predefined unary plus operation is simply the value of the operand, but user-defined implementations may have non-trivial results.
+ /// </summary>
+ UnaryPlus,
+ /// <summary>
+ /// A node that represents an arithmetic negation operation that has overflow checking.
+ /// </summary>
+ NegateChecked,
+ /// <summary>
+ /// A node that represents calling a constructor to create a new object.
+ /// </summary>
+ New,
+ /// <summary>
+ /// A node that represents creating a new one-dimensional array and initializing it from a list of elements.
+ /// </summary>
+ NewArrayInit,
+ /// <summary>
+ /// A node that represents creating a new array where the bounds for each dimension are specified.
+ /// </summary>
+ NewArrayBounds,
+ /// <summary>
+ /// A node that represents a bitwise complement operation.
+ /// </summary>
+ Not,
+ /// <summary>
+ /// A node that represents an inequality comparison.
+ /// </summary>
+ NotEqual,
+ /// <summary>
+ /// A node that represents a bitwise OR operation.
+ /// </summary>
+ Or,
+ /// <summary>
+ /// A node that represents a short-circuiting conditional OR operation.
+ /// </summary>
+ OrElse,
+ /// <summary>
+ /// A node that represents a reference to a parameter or variable defined in the context of the expression.
+ /// </summary>
+ Parameter,
+ /// <summary>
+ /// A node that represents raising a number to a power.
+ /// </summary>
+ Power,
+ /// <summary>
+ /// A node that represents an expression that has a constant value of type Expression. A Quote node can contain references to parameters defined in the context of the expression it represents.
+ /// </summary>
+ Quote,
+ /// <summary>
+ /// A node that represents a bitwise right-shift operation.
+ /// </summary>
+ RightShift,
+ /// <summary>
+ /// A node that represents arithmetic subtraction without overflow checking.
+ /// </summary>
+ Subtract,
+ /// <summary>
+ /// A node that represents arithmetic subtraction with overflow checking.
+ /// </summary>
+ SubtractChecked,
+ /// <summary>
+ /// A node that represents an explicit reference or boxing conversion where null reference (Nothing in Visual Basic) is supplied if the conversion fails.
+ /// </summary>
+ TypeAs,
+ /// <summary>
+ /// A node that represents a type test.
+ /// </summary>
+ TypeIs,
+ /// <summary>
+ /// A node that represents an assignment.
+ /// </summary>
+ Assign,
+ /// <summary>
+ /// A node that represents a block of expressions.
+ /// </summary>
+ Block,
+ /// <summary>
+ /// A node that represents a debugging information.
+ /// </summary>
+ DebugInfo,
+ /// <summary>
+ /// A node that represents a unary decrement.
+ /// </summary>
+ Decrement,
+ /// <summary>
+ /// A node that represents a dynamic operation.
+ /// </summary>
+ Dynamic,
+ /// <summary>
+ /// A node that represents a default value.
+ /// </summary>
+ Default,
+ /// <summary>
+ /// A node that represents an extension expression.
+ /// </summary>
+ Extension,
+ /// <summary>
+ /// A node that represents a goto.
+ /// </summary>
+ Goto,
+ /// <summary>
+ /// A node that represents a unary increment.
+ /// </summary>
+ Increment,
+ /// <summary>
+ /// A node that represents an index operation.
+ /// </summary>
+ Index,
+ /// <summary>
+ /// A node that represents a label.
+ /// </summary>
+ Label,
+ /// <summary>
+ /// A node that represents a list of runtime variables.
+ /// </summary>
+ RuntimeVariables,
+ /// <summary>
+ /// A node that represents a loop.
+ /// </summary>
+ Loop,
+ /// <summary>
+ /// A node that represents a switch operation.
+ /// </summary>
+ Switch,
+ /// <summary>
+ /// A node that represents a throwing of an exception.
+ /// </summary>
+ Throw,
+ /// <summary>
+ /// A node that represents a try-catch expression.
+ /// </summary>
+ Try,
+ /// <summary>
+ /// A node that represents an unbox value type operation.
+ /// </summary>
+ Unbox,
+ /// <summary>
+ /// A node that represents an arithmetic addition compound assignment without overflow checking.
+ /// </summary>
+ AddAssign,
+ /// <summary>
+ /// A node that represents a bitwise AND compound assignment.
+ /// </summary>
+ AndAssign,
+ /// <summary>
+ /// A node that represents an arithmetic division compound assignment .
+ /// </summary>
+ DivideAssign,
+ /// <summary>
+ /// A node that represents a bitwise XOR compound assignment.
+ /// </summary>
+ ExclusiveOrAssign,
+ /// <summary>
+ /// A node that represents a bitwise left-shift compound assignment.
+ /// </summary>
+ LeftShiftAssign,
+ /// <summary>
+ /// A node that represents an arithmetic remainder compound assignment.
+ /// </summary>
+ ModuloAssign,
+ /// <summary>
+ /// A node that represents arithmetic multiplication compound assignment without overflow checking.
+ /// </summary>
+ MultiplyAssign,
+ /// <summary>
+ /// A node that represents a bitwise OR compound assignment.
+ /// </summary>
+ OrAssign,
+ /// <summary>
+ /// A node that represents raising a number to a power compound assignment.
+ /// </summary>
+ PowerAssign,
+ /// <summary>
+ /// A node that represents a bitwise right-shift compound assignment.
+ /// </summary>
+ RightShiftAssign,
+ /// <summary>
+ /// A node that represents arithmetic subtraction compound assignment without overflow checking.
+ /// </summary>
+ SubtractAssign,
+ /// <summary>
+ /// A node that represents an arithmetic addition compound assignment with overflow checking.
+ /// </summary>
+ AddAssignChecked,
+ /// <summary>
+ /// A node that represents arithmetic multiplication compound assignment with overflow checking.
+ /// </summary>
+ MultiplyAssignChecked,
+ /// <summary>
+ /// A node that represents arithmetic subtraction compound assignment with overflow checking.
+ /// </summary>
+ SubtractAssignChecked,
+ /// <summary>
+ /// A node that represents an unary prefix increment.
+ /// </summary>
+ PreIncrementAssign,
+ /// <summary>
+ /// A node that represents an unary prefix decrement.
+ /// </summary>
+ PreDecrementAssign,
+ /// <summary>
+ /// A node that represents an unary postfix increment.
+ /// </summary>
+ PostIncrementAssign,
+ /// <summary>
+ /// A node that represents an unary postfix decrement.
+ /// </summary>
+ PostDecrementAssign,
+ /// <summary>
+ /// A node that represents a exact type test.
+ /// </summary>
+ TypeEqual,
+ /// <summary>
+ /// A node that represents a ones complement.
+ /// </summary>
+ OnesComplement,
+ /// <summary>
+ /// A node that represents a true condition value.
+ /// </summary>
+ IsTrue,
+ /// <summary>
+ /// A node that represents a false condition value.
+ /// </summary>
+ IsFalse,
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionVisitor.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionVisitor.cs
new file mode 100644
index 00000000000..bc86995dfa6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ExpressionVisitor.cs
@@ -0,0 +1,791 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents a visitor or rewriter for expression trees.
+ /// </summary>
+ /// <remarks>
+ /// This class is designed to be inherited to create more specialized
+ /// classes whose functionality requires traversing, examining or copying
+ /// an expression tree.
+ /// </remarks>
+ public abstract class ExpressionVisitor {
+
+ /// <summary>
+ /// Initializes a new instance of <see cref="ExpressionVisitor"/>.
+ /// </summary>
+ protected ExpressionVisitor() {
+ }
+
+ /// <summary>
+ /// Dispatches the expression to one of the more specialized visit methods in this class.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ public virtual Expression Visit(Expression node) {
+ if (node != null) {
+ return node.Accept(this);
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Dispatches the list of expressions to one of the more specialized visit methods in this class.
+ /// </summary>
+ /// <param name="nodes">The expressions to visit.</param>
+ /// <returns>The modified expression list, if any of the elements were modified;
+ /// otherwise, returns the original expression list.</returns>
+ protected ReadOnlyCollection<Expression> Visit(ReadOnlyCollection<Expression> nodes) {
+ Expression[] newNodes = null;
+ for (int i = 0, n = nodes.Count; i < n; i++) {
+ Expression node = Visit(nodes[i]);
+
+ if (newNodes != null) {
+ newNodes[i] = node;
+ } else if (!object.ReferenceEquals(node, nodes[i])) {
+ newNodes = new Expression[n];
+ for (int j = 0; j < i; j++) {
+ newNodes[j] = nodes[j];
+ }
+ newNodes[i] = node;
+ }
+ }
+ if (newNodes == null) {
+ return nodes;
+ }
+ return new TrueReadOnlyCollection<Expression>(newNodes);
+ }
+
+ internal Expression[] VisitArguments(IArgumentProvider nodes) {
+ Expression[] newNodes = null;
+ for (int i = 0, n = nodes.ArgumentCount; i < n; i++) {
+ Expression curNode = nodes.GetArgument(i);
+ Expression node = Visit(curNode);
+
+ if (newNodes != null) {
+ newNodes[i] = node;
+ } else if (!object.ReferenceEquals(node, curNode)) {
+ newNodes = new Expression[n];
+ for (int j = 0; j < i; j++) {
+ newNodes[j] = nodes.GetArgument(j);
+ }
+ newNodes[i] = node;
+ }
+ }
+ return newNodes;
+ }
+
+ /// <summary>
+ /// Visits all nodes in the collection using a specified element visitor.
+ /// </summary>
+ /// <typeparam name="T">The type of the nodes.</typeparam>
+ /// <param name="nodes">The nodes to visit.</param>
+ /// <param name="elementVisitor">A delegate that visits a single element,
+ /// optionally replacing it with a new element.</param>
+ /// <returns>The modified node list, if any of the elements were modified;
+ /// otherwise, returns the original node list.</returns>
+ protected static ReadOnlyCollection<T> Visit<T>(ReadOnlyCollection<T> nodes, Func<T, T> elementVisitor) {
+ T[] newNodes = null;
+ for (int i = 0, n = nodes.Count; i < n; i++) {
+ T node = elementVisitor(nodes[i]);
+ if (newNodes != null) {
+ newNodes[i] = node;
+ } else if (!object.ReferenceEquals(node, nodes[i])) {
+ newNodes = new T[n];
+ for (int j = 0; j < i; j++) {
+ newNodes[j] = nodes[j];
+ }
+ newNodes[i] = node;
+ }
+ }
+ if (newNodes == null) {
+ return nodes;
+ }
+ return new TrueReadOnlyCollection<T>(newNodes);
+ }
+
+ /// <summary>
+ /// Visits an expression, casting the result back to the original expression type.
+ /// </summary>
+ /// <typeparam name="T">The type of the expression.</typeparam>
+ /// <param name="node">The expression to visit.</param>
+ /// <param name="callerName">The name of the calling method; used to report to report a better error message.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ /// <exception cref="InvalidOperationException">The visit method for this node returned a different type.</exception>
+ protected T VisitAndConvert<T>(T node, string callerName) where T : Expression {
+ if (node == null) {
+ return null;
+ }
+ node = Visit(node) as T;
+ if (node == null) {
+ throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
+ }
+ return node;
+ }
+
+ /// <summary>
+ /// Visits an expression, casting the result back to the original expression type.
+ /// </summary>
+ /// <typeparam name="T">The type of the expression.</typeparam>
+ /// <param name="nodes">The expression to visit.</param>
+ /// <param name="callerName">The name of the calling method; used to report to report a better error message.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ /// <exception cref="InvalidOperationException">The visit method for this node returned a different type.</exception>
+ protected ReadOnlyCollection<T> VisitAndConvert<T>(ReadOnlyCollection<T> nodes, string callerName) where T : Expression {
+ T[] newNodes = null;
+ for (int i = 0, n = nodes.Count; i < n; i++) {
+ T node = Visit(nodes[i]) as T;
+ if (node == null) {
+ throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
+ }
+
+ if (newNodes != null) {
+ newNodes[i] = node;
+ } else if (!object.ReferenceEquals(node, nodes[i])) {
+ newNodes = new T[n];
+ for (int j = 0; j < i; j++) {
+ newNodes[j] = nodes[j];
+ }
+ newNodes[i] = node;
+ }
+ }
+ if (newNodes == null) {
+ return nodes;
+ }
+ return new TrueReadOnlyCollection<T>(newNodes);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="BinaryExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitBinary(BinaryExpression node) {
+ // Walk children in evaluation order: left, conversion, right
+ Expression l = Visit(node.Left);
+ LambdaExpression c = VisitAndConvert(node.Conversion, "VisitBinary");
+ Expression r = Visit(node.Right);
+ if (l == node.Left && r == node.Right && c == node.Conversion) {
+ return node;
+ }
+ if (node.IsReferenceComparison) {
+ if (node.NodeType == ExpressionType.Equal) {
+ return Expression.ReferenceEqual(l, r);
+ } else {
+ return Expression.ReferenceNotEqual(l, r);
+ }
+ }
+ var result = Expression.MakeBinary(node.NodeType, l, r, node.IsLiftedToNull, node.Method, c);
+ ValidateBinary(node, result);
+ return result;
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="BlockExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitBlock(BlockExpression node) {
+ int count = node.ExpressionCount;
+ Expression[] nodes = null;
+ for (int i = 0; i < count; i++) {
+ Expression oldNode = node.GetExpression(i);
+ Expression newNode = Visit(oldNode);
+
+ if (oldNode != newNode) {
+ if (nodes == null) {
+ nodes = new Expression[count];
+ }
+ nodes[i] = newNode;
+ }
+ }
+ var v = VisitAndConvert(node.Variables, "VisitBlock");
+
+ if (v == node.Variables && nodes == null) {
+ return node;
+ } else {
+ for (int i = 0; i < count; i++) {
+ if (nodes[i] == null) {
+ nodes[i] = node.GetExpression(i);
+ }
+ }
+ }
+
+ return node.Rewrite(v, nodes);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="ConditionalExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitConditional(ConditionalExpression node) {
+ Expression t = Visit(node.Test);
+ Expression l = Visit(node.IfTrue);
+ Expression r = Visit(node.IfFalse);
+ if (t == node.Test && l == node.IfTrue && r == node.IfFalse) {
+ return node;
+ }
+ return Expression.Condition(t, l, r, node.Type);
+ }
+
+ /// <summary>
+ /// Visits the <see cref="ConstantExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitConstant(ConstantExpression node) {
+ return node;
+ }
+
+ /// <summary>
+ /// Visits the <see cref="DebugInfoExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitDebugInfo(DebugInfoExpression node) {
+ return node;
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="DynamicExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitDynamic(DynamicExpression node) {
+ Expression[] a = VisitArguments((IArgumentProvider)node);
+ if (a == null) {
+ return node;
+ }
+
+ return node.Rewrite(a);
+ }
+
+ /// <summary>
+ /// Visits the <see cref="DefaultExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitDefault(DefaultExpression node) {
+ return node;
+ }
+
+ /// <summary>
+ /// Visits the children of the extension expression.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ /// <remarks>
+ /// This can be overridden to visit or rewrite specific extension nodes.
+ /// If it is not overridden, this method will call <see cref="Expression.VisitChildren" />,
+ /// which gives the node a chance to walk its children. By default,
+ /// <see cref="Expression.VisitChildren" /> will try to reduce the node.
+ /// </remarks>
+ protected internal virtual Expression VisitExtension(Expression node) {
+ return node.VisitChildren(this.Visit);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="GotoExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitGoto(GotoExpression node) {
+ LabelTarget t = VisitLabelTarget(node.Target);
+ Expression v = Visit(node.Value);
+ if (t == node.Target && v == node.Value) {
+ return node;
+ }
+ return Expression.MakeGoto(node.Kind, t, v, node.Type);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="InvocationExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitInvocation(InvocationExpression node) {
+ Expression e = Visit(node.Expression);
+ Expression[] a = VisitArguments(node);
+ if (e == node.Expression && a == null) {
+ return node;
+ }
+
+ return node.Rewrite(e, a);
+ }
+
+ /// <summary>
+ /// Visits the <see cref="LabelTarget" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual LabelTarget VisitLabelTarget(LabelTarget node) {
+ return node;
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="LabelExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitLabel(LabelExpression node) {
+ LabelTarget l = VisitLabelTarget(node.Target);
+ Expression d = Visit(node.DefaultValue);
+ if (l == node.Target && d == node.DefaultValue) {
+ return node;
+ }
+ return Expression.Label(l, d);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="Expression&lt;T&gt;" />.
+ /// </summary>
+ /// <typeparam name="T">The type of the delegate.</typeparam>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitLambda<T>(Expression<T> node) {
+ Expression b = Visit(node.Body);
+ var p = VisitAndConvert(node.Parameters, "VisitLambda");
+ if (b == node.Body && p == node.Parameters) {
+ return node;
+ }
+ return Expression.Lambda<T>(b, node.Name, node.TailCall, p);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="LoopExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitLoop(LoopExpression node) {
+ LabelTarget @break = VisitLabelTarget(node.BreakLabel);
+ LabelTarget @continue = VisitLabelTarget(node.ContinueLabel);
+ Expression b = Visit(node.Body);
+ if (@break == node.BreakLabel &&
+ @continue == node.ContinueLabel &&
+ b == node.Body) {
+ return node;
+ }
+ return Expression.Loop(b, @break, @continue);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MemberExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitMember(MemberExpression node) {
+ Expression e = Visit(node.Expression);
+ if (e == node.Expression) {
+ return node;
+ }
+ return Expression.MakeMemberAccess(e, node.Member);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="IndexExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitIndex(IndexExpression node) {
+ Expression o = Visit(node.Object);
+ Expression[] a = VisitArguments(node);
+ if (o == node.Object && a == null) {
+ return node;
+ }
+
+ return node.Rewrite(o, a);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MethodCallExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitMethodCall(MethodCallExpression node) {
+ Expression o = Visit(node.Object);
+ Expression[] a = VisitArguments((IArgumentProvider)node);
+ if (o == node.Object && a == null) {
+ return node;
+ }
+
+ return node.Rewrite(o, a);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="NewArrayExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitNewArray(NewArrayExpression node) {
+ ReadOnlyCollection<Expression> e = Visit(node.Expressions);
+ if (e == node.Expressions) {
+ return node;
+ }
+ if (node.NodeType == ExpressionType.NewArrayInit) {
+ return Expression.NewArrayInit(node.Type.GetElementType(), e);
+ }
+ return Expression.NewArrayBounds(node.Type.GetElementType(), e);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="NewExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
+ protected internal virtual Expression VisitNew(NewExpression node) {
+ ReadOnlyCollection<Expression> a = Visit(node.Arguments);
+ if (a == node.Arguments) {
+ return node;
+ }
+ if (node.Members != null) {
+ return Expression.New(node.Constructor, a, node.Members);
+ }
+ return Expression.New(node.Constructor, a);
+ }
+
+ /// <summary>
+ /// Visits the <see cref="ParameterExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitParameter(ParameterExpression node) {
+ return node;
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="RuntimeVariablesExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
+ var v = VisitAndConvert(node.Variables, "VisitRuntimeVariables");
+ if (v == node.Variables) {
+ return node;
+ }
+ return Expression.RuntimeVariables(v);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="SwitchCase" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual SwitchCase VisitSwitchCase(SwitchCase node) {
+ ReadOnlyCollection<Expression> t = Visit(node.TestValues);
+ Expression b = Visit(node.Body);
+ if (t == node.TestValues && b == node.Body) {
+ return node;
+ }
+ return Expression.SwitchCase(b, t);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="SwitchExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitSwitch(SwitchExpression node) {
+ Expression s = Visit(node.SwitchValue);
+ ReadOnlyCollection<SwitchCase> c = Visit(node.Cases, VisitSwitchCase);
+ Expression d = Visit(node.DefaultBody);
+ if (s == node.SwitchValue && c == node.Cases && d == node.DefaultBody) {
+ return node;
+ }
+ var result = Expression.Switch(node.Type, s, d, node.Comparison, c);
+ ValidateSwitch(node, result);
+ return result;
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="CatchBlock" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual CatchBlock VisitCatchBlock(CatchBlock node) {
+ ParameterExpression v = VisitAndConvert(node.Variable, "VisitCatchBlock");
+ Expression f = Visit(node.Filter);
+ Expression b = Visit(node.Body);
+ if (v == node.Variable && b == node.Body && f == node.Filter) {
+ return node;
+ }
+ return Expression.MakeCatchBlock(node.Test, v, b, f);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="TryExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitTry(TryExpression node) {
+ Expression b = Visit(node.Body);
+ ReadOnlyCollection<CatchBlock> h = Visit(node.Handlers, VisitCatchBlock);
+ Expression y = Visit(node.Finally);
+ Expression f = Visit(node.Fault);
+
+ if (b == node.Body &&
+ h == node.Handlers &&
+ y == node.Finally &&
+ f == node.Fault) {
+ return node;
+ }
+ return Expression.MakeTry(node.Type, b, y, f, h);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="TypeBinaryExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitTypeBinary(TypeBinaryExpression node) {
+ Expression e = Visit(node.Expression);
+ if (e == node.Expression) {
+ return node;
+ }
+ if (node.NodeType == ExpressionType.TypeIs) {
+ return Expression.TypeIs(e, node.TypeOperand);
+ }
+ return Expression.TypeEqual(e, node.TypeOperand);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="UnaryExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitUnary(UnaryExpression node) {
+ Expression o = Visit(node.Operand);
+ if (o == node.Operand) {
+ return node;
+ }
+ var result = Expression.MakeUnary(node.NodeType, o, node.Type, node.Method);
+ ValidateUnary(node, result);
+ return result;
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MemberInitExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitMemberInit(MemberInitExpression node) {
+ NewExpression n = VisitAndConvert(node.NewExpression, "VisitMemberInit");
+ ReadOnlyCollection<MemberBinding> bindings = Visit(node.Bindings, VisitMemberBinding);
+ if (n == node.NewExpression && bindings == node.Bindings) {
+ return node;
+ }
+ return Expression.MemberInit(n, bindings);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="ListInitExpression" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected internal virtual Expression VisitListInit(ListInitExpression node) {
+ NewExpression n = VisitAndConvert(node.NewExpression, "VisitListInit");
+ ReadOnlyCollection<ElementInit> initializers = Visit(node.Initializers, VisitElementInit);
+ if (n == node.NewExpression && initializers == node.Initializers) {
+ return node;
+ }
+ return Expression.ListInit(n, initializers);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="ElementInit" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual ElementInit VisitElementInit(ElementInit node) {
+ ReadOnlyCollection<Expression> arguments = Visit(node.Arguments);
+ if (arguments == node.Arguments) {
+ return node;
+ }
+ return Expression.ElementInit(node.AddMethod, arguments);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MemberBinding" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual MemberBinding VisitMemberBinding(MemberBinding node) {
+ switch (node.BindingType) {
+ case MemberBindingType.Assignment:
+ return VisitMemberAssignment((MemberAssignment)node);
+ case MemberBindingType.MemberBinding:
+ return VisitMemberMemberBinding((MemberMemberBinding)node);
+ case MemberBindingType.ListBinding:
+ return VisitMemberListBinding((MemberListBinding)node);
+ default:
+ throw Error.UnhandledBindingType(node.BindingType);
+ }
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MemberAssignment" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment node) {
+ Expression e = Visit(node.Expression);
+ if (e == node.Expression) {
+ return node;
+ }
+ return Expression.Bind(node.Member, e);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MemberMemberBinding" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) {
+ ReadOnlyCollection<MemberBinding> bindings = Visit(node.Bindings, VisitMemberBinding);
+ if (bindings == node.Bindings) {
+ return node;
+ }
+ return Expression.MemberBind(node.Member, bindings);
+ }
+
+ /// <summary>
+ /// Visits the children of the <see cref="MemberListBinding" />.
+ /// </summary>
+ /// <param name="node">The expression to visit.</param>
+ /// <returns>The modified expression, if it or any subexpression was modified;
+ /// otherwise, returns the original expression.</returns>
+ protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding node) {
+ ReadOnlyCollection<ElementInit> initializers = Visit(node.Initializers, VisitElementInit);
+ if (initializers == node.Initializers) {
+ return node;
+ }
+ return Expression.ListBind(node.Member, initializers);
+ }
+
+
+ //
+ // Prevent some common cases of invalid rewrites.
+ //
+ // Essentially, we don't want the rewritten node to be semantically
+ // bound by the factory, which may do the wrong thing. Instead we
+ // require derived classes to be explicit about what they want to do if
+ // types change.
+ //
+ private static void ValidateUnary(UnaryExpression before, UnaryExpression after) {
+ if (before.Method == null) {
+ if (after.Method != null) {
+ throw Error.MustRewriteWithoutMethod(after.Method, "VisitUnary");
+ }
+
+ ValidateChildType(before.Operand.Type, after.Operand.Type, "VisitUnary");
+ }
+ }
+
+ private static void ValidateBinary(BinaryExpression before, BinaryExpression after) {
+ if (before.Method == null) {
+ if (after.Method != null) {
+ throw Error.MustRewriteWithoutMethod(after.Method, "VisitBinary");
+ }
+
+ ValidateChildType(before.Left.Type, after.Left.Type, "VisitBinary");
+ ValidateChildType(before.Right.Type, after.Right.Type, "VisitBinary");
+ }
+ }
+
+ // We wouldn't need this if switch didn't infer the method.
+ private static void ValidateSwitch(SwitchExpression before, SwitchExpression after) {
+ // If we did not have a method, we don't want to bind to one,
+ // it might not be the right thing.
+ if (before.Comparison == null && after.Comparison != null) {
+ throw Error.MustRewriteWithoutMethod(after.Comparison, "VisitSwitch");
+ }
+ }
+
+ // Value types must stay as the same type, otherwise it's now a
+ // different operation, e.g. adding two doubles vs adding two ints.
+ private static void ValidateChildType(Type before, Type after, string methodName) {
+ if (before.IsValueType) {
+ if (TypeUtils.AreEquivalent(before, after)) {
+ // types are the same value type
+ return;
+ }
+ } else if (!after.IsValueType) {
+ // both are reference types
+ return;
+ }
+
+ // Otherwise, it's an invalid type change.
+ throw Error.MustRewriteChildToSameType(before, after, methodName);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/GotoExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/GotoExpression.cs
new file mode 100644
index 00000000000..9b71b08e79e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/GotoExpression.cs
@@ -0,0 +1,362 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Specifies what kind of jump this <see cref="GotoExpression"/> represents.
+ /// </summary>
+ public enum GotoExpressionKind {
+ /// <summary>
+ /// A <see cref="GotoExpression"/> that represents a jump to some location.
+ /// </summary>
+ Goto,
+ /// <summary>
+ /// A <see cref="GotoExpression"/> that represents a return statement.
+ /// </summary>
+ Return,
+ /// <summary>
+ /// A <see cref="GotoExpression"/> that represents a break statement.
+ /// </summary>
+ Break,
+ /// <summary>
+ /// A <see cref="GotoExpression"/> that represents a continue statement.
+ /// </summary>
+ Continue,
+ }
+
+ /// <summary>
+ /// Represents an unconditional jump. This includes return statements, break and continue statements, and other jumps.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.GotoExpressionProxy))]
+#endif
+ public sealed class GotoExpression : Expression {
+ private readonly GotoExpressionKind _kind;
+ private readonly Expression _value;
+ private readonly LabelTarget _target;
+ private readonly Type _type;
+
+ internal GotoExpression(GotoExpressionKind kind, LabelTarget target, Expression value, Type type) {
+ _kind = kind;
+ _value = value;
+ _target = target;
+ _type = type;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Goto; }
+ }
+
+ /// <summary>
+ /// The value passed to the target, or null if the target is of type
+ /// System.Void.
+ /// </summary>
+ public Expression Value {
+ get { return _value; }
+ }
+
+ /// <summary>
+ /// The target label where this node jumps to.
+ /// </summary>
+ public LabelTarget Target {
+ get { return _target; }
+ }
+
+ /// <summary>
+ /// The kind of the goto. For information purposes only.
+ /// </summary>
+ public GotoExpressionKind Kind {
+ get { return _kind; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitGoto(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a break statement.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Break(LabelTarget target) {
+ return MakeGoto(GotoExpressionKind.Break, target, null, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a break statement. The value passed to the label upon jumping can be specified.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Break(LabelTarget target, Expression value) {
+ return MakeGoto(GotoExpressionKind.Break, target, value, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a break statement with the specified type.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// and the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>.
+ /// </returns>
+ public static GotoExpression Break(LabelTarget target, Type type) {
+ return MakeGoto(GotoExpressionKind.Break, target, null, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a break statement with the specified type.
+ /// The value passed to the label upon jumping can be specified.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Break(LabelTarget target, Expression value, Type type) {
+ return MakeGoto(GotoExpressionKind.Break, target, value, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a continue statement.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Continue(LabelTarget target) {
+ return MakeGoto(GotoExpressionKind.Continue, target, null, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a continue statement with the specified type.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Continue(LabelTarget target, Type type) {
+ return MakeGoto(GotoExpressionKind.Continue, target, null, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a return statement.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Return,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Return(LabelTarget target) {
+ return MakeGoto(GotoExpressionKind.Return, target, null, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a return statement with the specified type.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Return,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Return(LabelTarget target, Type type) {
+ return MakeGoto(GotoExpressionKind.Return, target, null, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a return statement. The value passed to the label upon jumping can be specified.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Return(LabelTarget target, Expression value) {
+ return MakeGoto(GotoExpressionKind.Return, target, value, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a return statement with the specified type.
+ /// The value passed to the label upon jumping can be specified.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Return(LabelTarget target, Expression value, Type type) {
+ return MakeGoto(GotoExpressionKind.Return, target, value, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a goto.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
+ /// the <see cref="P:GotoExpression.Target"/> property set to the specified value,
+ /// and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Goto(LabelTarget target) {
+ return MakeGoto(GotoExpressionKind.Goto, target, null, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a goto with the specified type.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
+ /// the <see cref="P:GotoExpression.Target"/> property set to the specified value,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and a null value to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Goto(LabelTarget target, Type type) {
+ return MakeGoto(GotoExpressionKind.Goto, target, null, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a goto. The value passed to the label upon jumping can be specified.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Goto(LabelTarget target, Expression value) {
+ return MakeGoto(GotoExpressionKind.Goto, target, value, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a goto with the specified type.
+ /// The value passed to the label upon jumping can be specified.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression Goto(LabelTarget target, Expression value, Type type) {
+ return MakeGoto(GotoExpressionKind.Goto, target, value, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="GotoExpression"/> representing a jump of the specified <see cref="GotoExpressionKind"/>.
+ /// The value passed to the label upon jumping can also be specified.
+ /// </summary>
+ /// <param name="kind">The <see cref="GotoExpressionKind"/> of the <see cref="GotoExpression"/>.</param>
+ /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
+ /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
+ /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
+ /// <returns>
+ /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to <paramref name="kind"/>,
+ /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
+ /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
+ /// and <paramref name="value"/> to be passed to the target label upon jumping.
+ /// </returns>
+ public static GotoExpression MakeGoto(GotoExpressionKind kind, LabelTarget target, Expression value, Type type) {
+ ValidateGoto(target, ref value, "target", "value");
+ return new GotoExpression(kind, target, value, type);
+ }
+
+ private static void ValidateGoto(LabelTarget target, ref Expression value, string targetParameter, string valueParameter) {
+ ContractUtils.RequiresNotNull(target, targetParameter);
+ if (value == null) {
+ ContractUtils.Requires(target.Type == typeof(void), Strings.LabelMustBeVoidOrHaveExpression);
+ } else {
+ ValidateGotoType(target.Type, ref value, valueParameter);
+ }
+ }
+
+ // Standard argument validation, taken from ValidateArgumentTypes
+ private static void ValidateGotoType(Type expectedType, ref Expression value, string paramName) {
+ RequiresCanRead(value, paramName);
+ if (expectedType != typeof(void)) {
+ if (!TypeUtils.AreReferenceAssignable(expectedType, value.Type)) {
+ // C# autoquotes return values, so we'll do that here
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), expectedType) &&
+ expectedType.IsAssignableFrom(value.GetType())) {
+ value = Expression.Quote(value);
+ }
+ throw Error.ExpressionTypeDoesNotMatchLabel(value.Type, expectedType);
+ }
+ }
+ }
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IArgumentProvider.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IArgumentProvider.cs
new file mode 100644
index 00000000000..87da3a6f43c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IArgumentProvider.cs
@@ -0,0 +1,80 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Collections.Generic;
+using System.Text;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Provides an internal interface for accessing the arguments that multiple tree
+ /// nodes (DynamicExpression, ElementInit, MethodCallExpression, InvocationExpression, NewExpression,
+ /// and InexExpression).
+ ///
+ /// This enables two optimizations which reduce the size of the trees. The first is it enables
+ /// the nodes to hold onto an IList of T instead of a ReadOnlyCollection. This saves the cost
+ /// of allocating the ReadOnlyCollection for each node. The second is that it enables specialized
+ /// subclasses to be created which hold onto a specific number of arguments. For example Block2,
+ /// Block3, Block4. These nodes can therefore avoid allocating both a ReadOnlyCollection and an
+ /// array for storing their elements saving 32 bytes per node.
+ ///
+ /// Meanwhile the nodes can continue to expose the original LINQ properties of ReadOnlyCollections. They
+ /// do this by re-using 1 field for storing both the array or an element that would normally be stored
+ /// in the array.
+ ///
+ /// For the array case the collection is typed to IList of T instead of ReadOnlyCollection of T.
+ /// When the node is initially constructed it is an array. When the compiler accesses the members it
+ /// uses this interface. If a user accesses the members the array is promoted to a ReadOnlyCollection.
+ ///
+ /// For the object case we store the 1st argument in a field typed to object and when the node is initially
+ /// constructed this holds directly onto the Expression. When the compiler accesses the members
+ /// it again uses this interface and the accessor for the 1st argument uses Expression.ReturnObject to
+ /// return the object which handles the Expression or ReadOnlyCollection case. When the user accesses
+ /// the ReadOnlyCollection then the object field is updated to hold directly onto the ReadOnlyCollection.
+ ///
+ /// It is important that the Expressions consistently return the same ReadOnlyCollection otherwise the
+ /// re-writer will be broken and it would be a breaking change from LINQ v1. The problem is that currently
+ /// users can rely on object identity to tell if the node has changed. Storing the readonly collection in
+ /// an overloaded field enables us to both reduce memory usage as well as maintain compatibility and an
+ /// easy to use external API.
+ /// </summary>
+ internal interface IArgumentProvider {
+ Expression GetArgument(int index);
+ int ArgumentCount {
+ get;
+ }
+ }
+
+ static class ArgumentProviderOps {
+ internal static T[] Map<T>(this IArgumentProvider collection, Func<Expression, T> select) {
+ int count = collection.ArgumentCount;
+ T[] result = new T[count];
+ count = 0;
+ for (int i = 0; i < count; i++) {
+ result[i] = select(collection.GetArgument(i));
+ }
+ return result;
+ }
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IndexExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IndexExpression.cs
new file mode 100644
index 00000000000..f067615eef2
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/IndexExpression.cs
@@ -0,0 +1,446 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Text;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents indexing a property or array.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.IndexExpressionProxy))]
+#endif
+ public sealed class IndexExpression : Expression, IArgumentProvider {
+ private readonly Expression _instance;
+ private readonly PropertyInfo _indexer;
+ private IList<Expression> _arguments;
+
+ internal IndexExpression(
+ Expression instance,
+ PropertyInfo indexer,
+ IList<Expression> arguments) {
+
+ if (indexer == null) {
+ Debug.Assert(instance != null && instance.Type.IsArray);
+ Debug.Assert(instance.Type.GetArrayRank() == arguments.Count);
+ }
+
+ _instance = instance;
+ _indexer = indexer;
+ _arguments = arguments;
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Index; }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get {
+ if (_indexer != null) {
+ return _indexer.PropertyType;
+ }
+ return _instance.Type.GetElementType();
+ }
+ }
+
+ /// <summary>
+ /// An object to index.
+ /// </summary>
+ public Expression Object {
+ get { return _instance; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="PropertyInfo"/> for the property if the expression represents an indexed property, returns null otherwise.
+ /// </summary>
+ public PropertyInfo Indexer {
+ get { return _indexer; }
+ }
+
+ /// <summary>
+ /// Gets the arguments to be used to index the property or array.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Arguments {
+ get { return ReturnReadOnly(ref _arguments); }
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitIndex(this);
+ }
+
+ internal Expression Rewrite(Expression instance, Expression[] arguments) {
+ Debug.Assert(instance != null);
+ Debug.Assert(arguments == null || arguments.Length == _arguments.Count);
+
+ return Expression.MakeIndex(instance, _indexer, arguments ?? _arguments);
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates an <see cref="IndexExpression"/> that represents accessing an indexed property in an object.
+ /// </summary>
+ /// <param name="instance">The object to which the property belongs. Should be null if the property is static(shared).</param>
+ /// <param name="indexer">An <see cref="Expression"/> representing the property to index.</param>
+ /// <param name="arguments">An IEnumerable{Expression} contaning the arguments to be used to index the property.</param>
+ /// <returns>The created <see cref="IndexExpression"/>.</returns>
+ public static IndexExpression MakeIndex(Expression instance, PropertyInfo indexer, IEnumerable<Expression> arguments) {
+ if (indexer != null) {
+ return Property(instance, indexer, arguments);
+ } else {
+ return ArrayAccess(instance, arguments);
+ }
+ }
+
+ #region ArrayAccess
+
+ /// <summary>
+ /// Creates an <see cref="IndexExpression"></see> to access an array.
+ /// </summary>
+ /// <param name="array">An expression representing the array to index.</param>
+ /// <param name="indexes">An array containing expressions used to index the array.</param>
+ /// <remarks>The expression representing the array can be obtained by using the MakeMemberAccess method,
+ /// or through NewArrayBounds or NewArrayInit.</remarks>
+ /// <returns>The created <see cref="IndexExpression"/>.</returns>
+ public static IndexExpression ArrayAccess(Expression array, params Expression[] indexes) {
+ return ArrayAccess(array, (IEnumerable<Expression>)indexes);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IndexExpression"></see> to access an array.
+ /// </summary>
+ /// <param name="array">An expression representing the array to index.</param>
+ /// <param name="indexes">An <see cref="IEnumerable{Expression}"/> containing expressions used to index the array.</param>
+ /// <remarks>The expression representing the array can be obtained by using the MakeMemberAccess method,
+ /// or through NewArrayBounds or NewArrayInit.</remarks>
+ /// <returns>The created <see cref="IndexExpression"/>.</returns>
+ public static IndexExpression ArrayAccess(Expression array, IEnumerable<Expression> indexes) {
+ RequiresCanRead(array, "array");
+
+ Type arrayType = array.Type;
+ if (!arrayType.IsArray) {
+ throw Error.ArgumentMustBeArray();
+ }
+
+ var indexList = indexes.ToReadOnly();
+ if (arrayType.GetArrayRank() != indexList.Count) {
+ throw Error.IncorrectNumberOfIndexes();
+ }
+
+ foreach (Expression e in indexList) {
+ RequiresCanRead(e, "indexes");
+ if (e.Type != typeof(int)) {
+ throw Error.ArgumentMustBeArrayIndexType();
+ }
+ }
+
+ return new IndexExpression(array, null, indexList);
+ }
+
+ #endregion
+
+ #region Property
+ /// <summary>
+ /// Creates an <see cref="IndexExpression"/> representing the access to an indexed property.
+ /// </summary>
+ /// <param name="instance">The object to which the property belongs. If the property is static/shared, it must be null.</param>
+ /// <param name="propertyName">The name of the indexer.</param>
+ /// <param name="arguments">An array of <see cref="Expression"/> objects that are used to index the property.</param>
+ /// <returns>The created <see cref="IndexExpression"/>.</returns>
+ public static IndexExpression Property(Expression instance, string propertyName, params Expression[] arguments) {
+ RequiresCanRead(instance, "instance");
+ ContractUtils.RequiresNotNull(propertyName, "indexerName");
+ PropertyInfo pi = FindInstanceProperty(instance.Type, propertyName, arguments);
+ return Property(instance, pi, arguments);
+ }
+
+ #region methods for finding a PropertyInfo by its name
+ /// <summary>
+ /// The method finds the instance property with the specified name in a type. The property's type signature needs to be compatible with
+ /// the arguments if it is a indexer. If the arguments is null or empty, we get a normal property.
+ /// </summary>
+ private static PropertyInfo FindInstanceProperty(Type type, string propertyName, Expression[] arguments) {
+ // bind to public names first
+ BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy;
+ PropertyInfo pi = FindProperty(type, propertyName, arguments, flags);
+ if (pi == null) {
+ flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy;
+ pi = FindProperty(type, propertyName, arguments, flags);
+ }
+ if (pi == null) {
+ if (arguments == null || arguments.Length == 0) {
+ throw Error.InstancePropertyWithoutParameterNotDefinedForType(propertyName, type);
+ } else {
+ throw Error.InstancePropertyWithSpecifiedParametersNotDefinedForType(propertyName, GetArgTypesString(arguments), type);
+ }
+ }
+ return pi;
+ }
+
+ private static string GetArgTypesString(Expression[] arguments) {
+ StringBuilder argTypesStr = new StringBuilder();
+ var isFirst = true;
+ argTypesStr.Append("(");
+ foreach (var t in arguments.Select(arg => arg.Type)) {
+ if (!isFirst) {
+ argTypesStr.Append(", ");
+ }
+ argTypesStr.Append(t.Name);
+ isFirst = false;
+ }
+ argTypesStr.Append(")");
+ return argTypesStr.ToString();
+ }
+
+ private static PropertyInfo FindProperty(Type type, string propertyName, Expression[] arguments, BindingFlags flags) {
+ MemberInfo[] members = type.FindMembers(MemberTypes.Property, flags, Type.FilterNameIgnoreCase, propertyName);
+ if (members == null || members.Length == 0)
+ return null;
+
+ PropertyInfo pi;
+ var propertyInfos = members.Map(t => (PropertyInfo)t);
+ int count = FindBestProperty(propertyInfos, arguments, out pi);
+
+ if (count == 0)
+ return null;
+ if (count > 1)
+ throw Error.PropertyWithMoreThanOneMatch(propertyName, type);
+ return pi;
+ }
+
+ private static int FindBestProperty(IEnumerable<PropertyInfo> properties, Expression[] args, out PropertyInfo property) {
+ int count = 0;
+ property = null;
+ foreach (PropertyInfo pi in properties) {
+ if (pi != null && IsCompatible(pi, args)) {
+ if (property == null) {
+ property = pi;
+ count = 1;
+ }
+ else {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
+ private static bool IsCompatible(PropertyInfo pi, Expression[] args) {
+ MethodInfo mi;
+
+ mi = pi.GetGetMethod(true);
+ ParameterInfo[] parms;
+ if (mi != null) {
+ parms = mi.GetParametersCached();
+ } else {
+ mi = pi.GetSetMethod(true);
+ //The setter has an additional parameter for the value to set,
+ //need to remove the last type to match the arguments.
+ parms = mi.GetParametersCached().RemoveLast();
+ }
+
+ if (mi == null) {
+ return false;
+ }
+ if (args == null) {
+ return parms.Length == 0;
+ }
+
+ if (parms.Length != args.Length)
+ return false;
+ for (int i = 0; i < args.Length; i++) {
+ if (args[i] == null) return false;
+ if (!TypeUtils.AreReferenceAssignable(parms[i].ParameterType, args[i].Type)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ #endregion
+
+ /// <summary>
+ /// Creates an <see cref="IndexExpression"/> representing the access to an indexed property.
+ /// </summary>
+ /// <param name="instance">The object to which the property belongs. If the property is static/shared, it must be null.</param>
+ /// <param name="indexer">The <see cref="PropertyInfo"/> that represents the property to index.</param>
+ /// <param name="arguments">An array of <see cref="Expression"/> objects that are used to index the property.</param>
+ /// <returns>The created <see cref="IndexExpression"/>.</returns>
+ public static IndexExpression Property(Expression instance, PropertyInfo indexer, params Expression[] arguments) {
+ return Property(instance, indexer, (IEnumerable<Expression>)arguments);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="IndexExpression"/> representing the access to an indexed property.
+ /// </summary>
+ /// <param name="instance">The object to which the property belongs. If the property is static/shared, it must be null.</param>
+ /// <param name="indexer">The <see cref="PropertyInfo"/> that represents the property to index.</param>
+ /// <param name="arguments">An <see cref="IEnumerable{T}"/> of <see cref="Expression"/> objects that are used to index the property.</param>
+ /// <returns>The created <see cref="IndexExpression"/>.</returns>
+ public static IndexExpression Property(Expression instance, PropertyInfo indexer, IEnumerable<Expression> arguments) {
+ var argList = arguments.ToReadOnly();
+ ValidateIndexedProperty(instance, indexer, ref argList);
+ return new IndexExpression(instance, indexer, argList);
+ }
+
+ // CTS places no restrictions on properties (see ECMA-335 8.11.3),
+ // so we validate that the property conforms to CLS rules here.
+ //
+ // Does reflection help us out at all? Expression.Property skips all of
+ // these checks, so either it needs more checks or we need less here.
+ private static void ValidateIndexedProperty(Expression instance, PropertyInfo property, ref ReadOnlyCollection<Expression> argList) {
+
+ // If both getter and setter specified, all their parameter types
+ // should match, with exception of the last setter parameter which
+ // should match the type returned by the get method.
+ // Accessor parameters cannot be ByRef.
+
+ ContractUtils.RequiresNotNull(property, "property");
+ ContractUtils.Requires(!property.PropertyType.IsByRef, "property", Strings.PropertyCannotHaveRefType);
+ ContractUtils.Requires(property.PropertyType != typeof(void), "property", Strings.PropertyTypeCannotBeVoid);
+
+ ParameterInfo[] getParameters = null;
+ MethodInfo getter = property.GetGetMethod(true);
+ if (getter != null) {
+ getParameters = getter.GetParametersCached();
+ ValidateAccessor(instance, getter, getParameters, ref argList);
+ }
+
+ MethodInfo setter = property.GetSetMethod(true);
+ if (setter != null) {
+ ParameterInfo[] setParameters = setter.GetParametersCached();
+ ContractUtils.Requires(setParameters.Length > 0, "property", Strings.SetterHasNoParams);
+
+ // valueType is the type of the value passed to the setter (last parameter)
+ Type valueType = setParameters[setParameters.Length - 1].ParameterType;
+ ContractUtils.Requires(!valueType.IsByRef, "property", Strings.PropertyCannotHaveRefType);
+ ContractUtils.Requires(setter.ReturnType == typeof(void), "property", Strings.SetterMustBeVoid);
+ ContractUtils.Requires(property.PropertyType == valueType, "property", Strings.PropertyTyepMustMatchSetter);
+
+ if (getter != null) {
+ ContractUtils.Requires(!(getter.IsStatic ^ setter.IsStatic), "property", Strings.BothAccessorsMustBeStatic);
+ ContractUtils.Requires(getParameters.Length == setParameters.Length - 1, "property", Strings.IndexesOfSetGetMustMatch);
+
+ for (int i = 0; i < getParameters.Length; i++) {
+ ContractUtils.Requires(getParameters[i].ParameterType == setParameters[i].ParameterType, "property", Strings.IndexesOfSetGetMustMatch);
+ }
+ } else {
+ ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList);
+ }
+ }
+
+ if (getter == null && setter == null) {
+ throw Error.PropertyDoesNotHaveAccessor(property);
+ }
+ }
+
+ private static void ValidateAccessor(Expression instance, MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection<Expression> arguments) {
+ ContractUtils.RequiresNotNull(arguments, "arguments");
+
+ ValidateMethodInfo(method);
+ ContractUtils.Requires((method.CallingConvention & CallingConventions.VarArgs) == 0, "method", Strings.AccessorsCannotHaveVarArgs);
+ if (method.IsStatic) {
+ ContractUtils.Requires(instance == null, "instance", Strings.OnlyStaticMethodsHaveNullInstance);
+ } else {
+ ContractUtils.Requires(instance != null, "method", Strings.OnlyStaticMethodsHaveNullInstance);
+ RequiresCanRead(instance, "instance");
+ ValidateCallInstanceType(instance.Type, method);
+ }
+
+ ValidateAccessorArgumentTypes(method, indexes, ref arguments);
+ }
+
+ private static void ValidateAccessorArgumentTypes(MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection<Expression> arguments) {
+ if (indexes.Length > 0) {
+ if (indexes.Length != arguments.Count) {
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ }
+ Expression[] newArgs = null;
+ for (int i = 0, n = indexes.Length; i < n; i++) {
+ Expression arg = arguments[i];
+ ParameterInfo pi = indexes[i];
+ RequiresCanRead(arg, "arguments");
+
+ Type pType = pi.ParameterType;
+ ContractUtils.Requires(!pType.IsByRef, "indexes", Strings.AccessorsCannotHaveByRefArgs);
+ TypeUtils.ValidateType(pType);
+
+ if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) {
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType())) {
+ arg = Expression.Quote(arg);
+ } else {
+ throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method);
+ }
+ }
+ if (newArgs == null && arg != arguments[i]) {
+ newArgs = new Expression[arguments.Count];
+ for (int j = 0; j < i; j++) {
+ newArgs[j] = arguments[j];
+ }
+ }
+ if (newArgs != null) {
+ newArgs[i] = arg;
+ }
+ }
+ if (newArgs != null) {
+ arguments = new TrueReadOnlyCollection<Expression>(newArgs);
+ }
+
+ } else if (arguments.Count > 0) {
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/InvocationExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/InvocationExpression.cs
new file mode 100644
index 00000000000..c4d8b4aa0b8
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/InvocationExpression.cs
@@ -0,0 +1,189 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents an expression that applies a delegate or lambda expression to a list of argument expressions.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.InvocationExpressionProxy))]
+#endif
+ public sealed class InvocationExpression : Expression, IArgumentProvider {
+ private IList<Expression> _arguments;
+ private readonly Expression _lambda;
+ private readonly Type _returnType;
+
+ internal InvocationExpression(Expression lambda, IList<Expression> arguments, Type returnType) {
+ _lambda = lambda;
+ _arguments = arguments;
+ _returnType = returnType;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _returnType; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Invoke; }
+ }
+
+ /// <summary>
+ /// Gets the delegate or lambda expression to be applied.
+ /// </summary>
+ public Expression Expression {
+ get { return _lambda; }
+ }
+
+ /// <summary>
+ /// Gets the arguments that the delegate or lambda expression is applied to.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Arguments {
+ get { return ReturnReadOnly(ref _arguments); }
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitInvocation(this);
+ }
+
+ internal InvocationExpression Rewrite(Expression lambda, Expression[] arguments) {
+ Debug.Assert(lambda != null);
+ Debug.Assert(arguments == null || arguments.Length == _arguments.Count);
+
+ return Expression.Invoke(lambda, arguments ?? _arguments);
+ }
+
+ internal LambdaExpression LambdaOperand {
+ get {
+ return (_lambda.NodeType == ExpressionType.Quote)
+ ? (LambdaExpression)((UnaryExpression)_lambda).Operand
+ : (_lambda as LambdaExpression);
+ }
+ }
+ }
+
+ public partial class Expression {
+
+ ///<summary>
+ ///Creates an <see cref="T:Microsoft.Linq.Expressions.InvocationExpression" /> that
+ ///applies a delegate or lambda expression to a list of argument expressions.
+ ///</summary>
+ ///<returns>
+ ///An <see cref="T:Microsoft.Linq.Expressions.InvocationExpression" /> that
+ ///applies the specified delegate or lambda expression to the provided arguments.
+ ///</returns>
+ ///<param name="expression">
+ ///An <see cref="T:Microsoft.Linq.Expressions.Expression" /> that represents the delegate
+ ///or lambda expression to be applied.
+ ///</param>
+ ///<param name="arguments">
+ ///An array of <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects
+ ///that represent the arguments that the delegate or lambda expression is applied to.
+ ///</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="expression" />.Type does not represent a delegate type or an <see cref="T:Microsoft.Linq.Expressions.Expression`1" />.-or-The <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property of an element of <paramref name="arguments" /> is not assignable to the type of the corresponding parameter of the delegate represented by <paramref name="expression" />.</exception>
+ ///<exception cref="T:System.InvalidOperationException">
+ ///<paramref name="arguments" /> does not contain the same number of elements as the list of parameters for the delegate represented by <paramref name="expression" />.</exception>
+ public static InvocationExpression Invoke(Expression expression, params Expression[] arguments) {
+ return Invoke(expression, (IEnumerable<Expression>)arguments);
+ }
+
+ ///<summary>
+ ///Creates an <see cref="T:Microsoft.Linq.Expressions.InvocationExpression" /> that
+ ///applies a delegate or lambda expression to a list of argument expressions.
+ ///</summary>
+ ///<returns>
+ ///An <see cref="T:Microsoft.Linq.Expressions.InvocationExpression" /> that
+ ///applies the specified delegate or lambda expression to the provided arguments.
+ ///</returns>
+ ///<param name="expression">
+ ///An <see cref="T:Microsoft.Linq.Expressions.Expression" /> that represents the delegate
+ ///or lambda expression to be applied.
+ ///</param>
+ ///<param name="arguments">
+ ///An <see cref="T:System.Collections.Generic.IEnumerable`1" /> of <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects
+ ///that represent the arguments that the delegate or lambda expression is applied to.
+ ///</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="expression" />.Type does not represent a delegate type or an <see cref="T:Microsoft.Linq.Expressions.Expression`1" />.-or-The <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property of an element of <paramref name="arguments" /> is not assignable to the type of the corresponding parameter of the delegate represented by <paramref name="expression" />.</exception>
+ ///<exception cref="T:System.InvalidOperationException">
+ ///<paramref name="arguments" /> does not contain the same number of elements as the list of parameters for the delegate represented by <paramref name="expression" />.</exception>
+ public static InvocationExpression Invoke(Expression expression, IEnumerable<Expression> arguments) {
+ RequiresCanRead(expression, "expression");
+
+ var args = arguments.ToReadOnly();
+ var mi = GetInvokeMethod(expression);
+ ValidateArgumentTypes(mi, ExpressionType.Invoke, ref args);
+ return new InvocationExpression(expression, args, mi.ReturnType);
+ }
+
+ /// <summary>
+ /// Gets the delegate's Invoke method; used by InvocationExpression.
+ /// </summary>
+ /// <param name="expression">The expression to be invoked.</param>
+ internal static MethodInfo GetInvokeMethod(Expression expression) {
+ Type delegateType = expression.Type;
+ if (delegateType == typeof(Delegate)) {
+ throw Error.ExpressionTypeNotInvocable(delegateType);
+ } else if (!typeof(Delegate).IsAssignableFrom(expression.Type)) {
+ Type exprType = TypeUtils.FindGenericType(typeof(Expression<>), expression.Type);
+ if (exprType == null) {
+ throw Error.ExpressionTypeNotInvocable(expression.Type);
+ }
+ delegateType = exprType.GetGenericArguments()[0];
+ }
+
+ return delegateType.GetMethod("Invoke");
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelExpression.cs
new file mode 100644
index 00000000000..6963b7e7c20
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelExpression.cs
@@ -0,0 +1,100 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a label, which can be placed in any <see cref="Expression"/> context. If
+ /// it is jumped to, it will get the value provided by the corresponding
+ /// <see cref="GotoExpression"/>. Otherwise, it gets the value in <see cref="LabelExpression.DefaultValue"/>. If the
+ /// <see cref="Type"/> equals System.Void, no value should be provided.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.LabelExpressionProxy))]
+#endif
+ public sealed class LabelExpression : Expression {
+ private readonly Expression _defaultValue;
+ private readonly LabelTarget _target;
+
+ internal LabelExpression(LabelTarget label, Expression defaultValue) {
+ _target = label;
+ _defaultValue = defaultValue;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _target.Type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Label; }
+ }
+
+ /// <summary>
+ /// The <see cref="LabelTarget"/> which this label is associated with.
+ /// </summary>
+ public LabelTarget Target {
+ get { return _target; }
+ }
+
+ /// <summary>
+ /// The value of the <see cref="LabelExpression"/> when the label is reached through
+ /// normal control flow (e.g. is not jumped to).
+ /// </summary>
+ public Expression DefaultValue {
+ get { return _defaultValue; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitLabel(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="LabelExpression"/> representing a label with no default value.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> which this <see cref="LabelExpression"/> will be associated with.</param>
+ /// <returns>A <see cref="LabelExpression"/> with no default value.</returns>
+ public static LabelExpression Label(LabelTarget target) {
+ return Label(target, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="LabelExpression"/> representing a label with the given default value.
+ /// </summary>
+ /// <param name="target">The <see cref="LabelTarget"/> which this <see cref="LabelExpression"/> will be associated with.</param>
+ /// <param name="defaultValue">The value of this <see cref="LabelExpression"/> when the label is reached through normal control flow.</param>
+ /// <returns>A <see cref="LabelExpression"/> with the given default value.</returns>
+ public static LabelExpression Label(LabelTarget target, Expression defaultValue) {
+ ValidateGoto(target, ref defaultValue, "label", "defaultValue");
+ return new LabelExpression(target, defaultValue);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelTarget.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelTarget.cs
new file mode 100644
index 00000000000..b5e07e4e84b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LabelTarget.cs
@@ -0,0 +1,107 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Used to denote the target of a <see cref="GotoExpression"/>.
+ /// </summary>
+ public sealed class LabelTarget {
+ private readonly Type _type;
+ private readonly string _name;
+
+ internal LabelTarget(Type type, string name) {
+ _type = type;
+ _name = name;
+ }
+
+ /// <summary>
+ /// Gets the name of the label.
+ /// </summary>
+ /// <remarks>The label's name is provided for information purposes only.</remarks>
+ public string Name {
+ get { return _name; }
+ }
+
+ /// <summary>
+ /// The type of value that is passed when jumping to the label
+ /// (or System.Void if no value should be passed).
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
+ public Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="String"/> that represents the current <see cref="Object"/>.
+ /// </summary>
+ /// <returns>A <see cref="String"/> that represents the current <see cref="Object"/>. </returns>
+ public override string ToString() {
+ return String.IsNullOrEmpty(this.Name) ? "UnamedLabel" : this.Name;
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="LabelTarget"/> representing a label with void type and no name.
+ /// </summary>
+ /// <returns>The new <see cref="LabelTarget"/>.</returns>
+ public static LabelTarget Label() {
+ return Label(typeof(void), null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="LabelTarget"/> representing a label with void type and the given name.
+ /// </summary>
+ /// <param name="name">The name of the label.</param>
+ /// <returns>The new <see cref="LabelTarget"/>.</returns>
+ public static LabelTarget Label(string name) {
+ return Label(typeof(void), name);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="LabelTarget"/> representing a label with the given type.
+ /// </summary>
+ /// <param name="type">The type of value that is passed when jumping to the label.</param>
+ /// <returns>The new <see cref="LabelTarget"/>.</returns>
+ public static LabelTarget Label(Type type) {
+ return Label(type, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="LabelTarget"/> representing a label with the given type and name.
+ /// </summary>
+ /// <param name="type">The type of value that is passed when jumping to the label.</param>
+ /// <param name="name">The name of the label.</param>
+ /// <returns>The new <see cref="LabelTarget"/>.</returns>
+ public static LabelTarget Label(Type type, string name) {
+ ContractUtils.RequiresNotNull(type, "type");
+ TypeUtils.ValidateType(type);
+ return new LabelTarget(type, name);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs
new file mode 100644
index 00000000000..5e33e6c1601
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LambdaExpression.cs
@@ -0,0 +1,635 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Threading;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Creates a <see cref="LambdaExpression"/> node.
+ /// This captures a block of code that is similar to a .NET method body.
+ /// </summary>
+ /// <remarks>
+ /// Lambda expressions take input through parameters and are expected to be fully bound.
+ /// </remarks>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.LambdaExpressionProxy))]
+#endif
+ public abstract class LambdaExpression : Expression {
+ private readonly string _name;
+ private readonly Expression _body;
+ private readonly ReadOnlyCollection<ParameterExpression> _parameters;
+ private readonly Type _delegateType;
+ private readonly bool _tailCall;
+
+ internal LambdaExpression(
+ Type delegateType,
+ string name,
+ Expression body,
+ bool tailCall,
+ ReadOnlyCollection<ParameterExpression> parameters
+ ) {
+
+ Debug.Assert(delegateType != null);
+
+ _name = name;
+ _body = body;
+ _parameters = parameters;
+ _delegateType = delegateType;
+ _tailCall = tailCall;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _delegateType; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Lambda; }
+ }
+
+ /// <summary>
+ /// Gets the parameters of the lambda expression.
+ /// </summary>
+ public ReadOnlyCollection<ParameterExpression> Parameters {
+ get { return _parameters; }
+ }
+
+ /// <summary>
+ /// Gets the name of the lambda expression.
+ /// </summary>
+ /// <remarks>Used for debugging purposes.</remarks>
+ public string Name {
+ get { return _name; }
+ }
+
+ /// <summary>
+ /// Gets the body of the lambda expression.
+ /// </summary>
+ public Expression Body {
+ get { return _body; }
+ }
+
+ /// <summary>
+ /// Gets the return type of the lambda expression.
+ /// </summary>
+ public Type ReturnType {
+ get { return Type.GetMethod("Invoke").ReturnType; }
+ }
+
+ /// <summary>
+ /// Gets the value that indicates if the lambda expression will be compiled with
+ /// tail call optimization.
+ /// </summary>
+ public bool TailCall {
+ get { return _tailCall; }
+ }
+
+ /// <summary>
+ /// Produces a delegate that represents the lambda expression.
+ /// </summary>
+ /// <returns>A delegate containing the compiled version of the lambda.</returns>
+ public Delegate Compile() {
+ return LambdaCompiler.Compile(this, null);
+ }
+
+ /// <summary>
+ /// Produces a delegate that represents the lambda expression.
+ /// </summary>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ /// <returns>A delegate containing the compiled version of the lambda.</returns>
+ public Delegate Compile(DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
+ return LambdaCompiler.Compile(this, debugInfoGenerator);
+ }
+
+ /// <summary>
+ /// Compiles the lambda into a method definition.
+ /// </summary>
+ /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
+ public void CompileToMethod(MethodBuilder method) {
+ CompileToMethodInternal(method, null);
+ }
+
+ /// <summary>
+ /// Compiles the lambda into a method definition and custom debug information.
+ /// </summary>
+ /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ public void CompileToMethod(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
+ CompileToMethodInternal(method, debugInfoGenerator);
+ }
+
+ private void CompileToMethodInternal(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.Requires(method.IsStatic, "method");
+ var type = method.DeclaringType as TypeBuilder;
+ ContractUtils.Requires(type != null, "method", Strings.MethodBuilderDoesNotHaveTypeBuilder);
+
+ LambdaCompiler.Compile(this, method, debugInfoGenerator);
+ }
+
+ internal abstract LambdaExpression Accept(StackSpiller spiller);
+ }
+
+ /// <summary>
+ /// Defines a <see cref="Expression{TDelegate}"/> node.
+ /// This captures a block of code that is similar to a .NET method body.
+ /// </summary>
+ /// <typeparam name="TDelegate">The type of the delegate.</typeparam>
+ /// <remarks>
+ /// Lambda expressions take input through parameters and are expected to be fully bound.
+ /// </remarks>
+ public sealed class Expression<TDelegate> : LambdaExpression {
+ internal Expression(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters)
+ : base(typeof(TDelegate), name, body, tailCall, parameters) {
+ }
+
+ /// <summary>
+ /// Produces a delegate that represents the lambda expression.
+ /// </summary>
+ /// <returns>A delegate containing the compiled version of the lambda.</returns>
+ public new TDelegate Compile() {
+ return (TDelegate)(object)LambdaCompiler.Compile(this, null);
+ }
+
+ /// <summary>
+ /// Produces a delegate that represents the lambda expression.
+ /// </summary>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ /// <returns>A delegate containing the compiled version of the lambda.</returns>
+ public new TDelegate Compile(DebugInfoGenerator debugInfoGenerator) {
+ ContractUtils.RequiresNotNull(debugInfoGenerator, "debugInfoGenerator");
+ return (TDelegate)(object)LambdaCompiler.Compile(this, debugInfoGenerator);
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitLambda(this);
+ }
+
+ internal override LambdaExpression Accept(StackSpiller spiller) {
+ return spiller.Rewrite(this);
+ }
+
+ internal static LambdaExpression Create(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters) {
+ return new Expression<TDelegate>(body, name, tailCall, parameters);
+ }
+ }
+
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates an Expression{T} given the delegate type. Caches the
+ /// factory method to speed up repeated creations for the same T.
+ /// </summary>
+ internal static LambdaExpression CreateLambda(Type delegateType, string name, Expression body, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters) {
+ // Get or create a delegate to the public Expression.Lambda<T>
+ // method and call that will be used for creating instances of this
+ // delegate type
+ LambdaFactory factory;
+
+ if (_LambdaFactories == null) {
+ // NOTE: this must be Interlocked assigment since we use _LambdaFactories for locking.
+ Interlocked.CompareExchange(ref _LambdaFactories, new CacheDict<Type, LambdaFactory>(50), null);
+ }
+
+ lock (_LambdaFactories) {
+ if (!_LambdaFactories.TryGetValue(delegateType, out factory)) {
+ _LambdaFactories[delegateType] = factory = (LambdaFactory)Delegate.CreateDelegate(
+ typeof(LambdaFactory),
+ typeof(Expression<>).MakeGenericType(delegateType).GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic)
+ );
+ }
+ }
+
+ return factory(body, name, tailCall, parameters);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time.
+ /// </summary>
+ /// <typeparam name="TDelegate">The delegate type. </typeparam>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static Expression<TDelegate> Lambda<TDelegate>(Expression body, params ParameterExpression[] parameters) {
+ return Lambda<TDelegate>(body, false, (IEnumerable<ParameterExpression>)parameters);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time.
+ /// </summary>
+ /// <typeparam name="TDelegate">The delegate type. </typeparam>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static Expression<TDelegate> Lambda<TDelegate>(Expression body, bool tailCall, params ParameterExpression[] parameters) {
+ return Lambda<TDelegate>(body, tailCall, (IEnumerable<ParameterExpression>)parameters);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time.
+ /// </summary>
+ /// <typeparam name="TDelegate">The delegate type. </typeparam>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static Expression<TDelegate> Lambda<TDelegate>(Expression body, IEnumerable<ParameterExpression> parameters) {
+ return Lambda<TDelegate>(body, null, false, parameters);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time.
+ /// </summary>
+ /// <typeparam name="TDelegate">The delegate type. </typeparam>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static Expression<TDelegate> Lambda<TDelegate>(Expression body, bool tailCall, IEnumerable<ParameterExpression> parameters) {
+ return Lambda<TDelegate>(body, null, tailCall, parameters);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time.
+ /// </summary>
+ /// <typeparam name="TDelegate">The delegate type. </typeparam>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="name">The name of the lambda. Used for generating debugging info.</param>
+ /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static Expression<TDelegate> Lambda<TDelegate>(Expression body, String name, IEnumerable<ParameterExpression> parameters) {
+ return Lambda<TDelegate>(body, name, false, parameters);
+ }
+
+ /// <summary>
+ /// Creates an <see cref="Expression{TDelegate}"/> where the delegate type is known at compile time.
+ /// </summary>
+ /// <typeparam name="TDelegate">The delegate type. </typeparam>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="name">The name of the lambda. Used for generating debugging info.</param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <returns>An <see cref="Expression{TDelegate}"/> that has the <see cref="P:NodeType"/> property equal to <see cref="P:Lambda"/> and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static Expression<TDelegate> Lambda<TDelegate>(Expression body, String name, bool tailCall, IEnumerable<ParameterExpression> parameters) {
+ var parameterList = parameters.ToReadOnly();
+ ValidateLambdaArgs(typeof(TDelegate), ref body, parameterList);
+ return new Expression<TDelegate>(body, name, tailCall, parameterList);
+ }
+
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Expression body, params ParameterExpression[] parameters) {
+ return Lambda(body, false, (IEnumerable<ParameterExpression>)parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Expression body, bool tailCall, params ParameterExpression[] parameters) {
+ return Lambda(body, tailCall, (IEnumerable<ParameterExpression>)parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Expression body, IEnumerable<ParameterExpression> parameters) {
+ return Lambda(body, null, false, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Expression body, bool tailCall, IEnumerable<ParameterExpression> parameters) {
+ return Lambda(body, null, tailCall, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Type delegateType, Expression body, params ParameterExpression[] parameters) {
+ return Lambda(delegateType, body, null, false, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An array that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, params ParameterExpression[] parameters) {
+ return Lambda(delegateType, body, null, tailCall, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Type delegateType, Expression body, IEnumerable<ParameterExpression> parameters) {
+ return Lambda(delegateType, body, null, false, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Type delegateType, Expression body, bool tailCall, IEnumerable<ParameterExpression> parameters) {
+ return Lambda(delegateType, body, null, tailCall, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Expression body, string name, IEnumerable<ParameterExpression> parameters) {
+ return Lambda(body, name, false, parameters);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Expression body, string name, bool tailCall, IEnumerable<ParameterExpression> parameters) {
+ ContractUtils.RequiresNotNull(body, "body");
+
+ var parameterList = parameters.ToReadOnly();
+
+ int paramCount = parameterList.Count;
+ Type[] typeArgs = new Type[paramCount + 1];
+ if (paramCount > 0) {
+ var set = new Set<ParameterExpression>(parameterList.Count);
+ for (int i = 0; i < paramCount; i++) {
+ var param = parameterList[i];
+ ContractUtils.RequiresNotNull(param, "parameter");
+ typeArgs[i] = param.IsByRef ? param.Type.MakeByRefType() : param.Type;
+ if (set.Contains(param)) {
+ throw Error.DuplicateVariable(param);
+ }
+ set.Add(param);
+ }
+ }
+ typeArgs[paramCount] = body.Type;
+
+ Type delegateType = DelegateHelpers.MakeDelegateType(typeArgs);
+
+ return CreateLambda(delegateType, name, body, tailCall, parameterList);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
+ /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Type delegateType, Expression body, string name, IEnumerable<ParameterExpression> parameters) {
+ var paramList = parameters.ToReadOnly();
+ ValidateLambdaArgs(delegateType, ref body, paramList);
+
+ return CreateLambda(delegateType, name, body, false, paramList);
+ }
+
+ /// <summary>
+ /// Creates a LambdaExpression by first constructing a delegate type.
+ /// </summary>
+ /// <param name="delegateType">A <see cref="Type"/> representing the delegate signature for the lambda.</param>
+ /// <param name="body">An <see cref="Expression"/> to set the <see cref="P:Body"/> property equal to. </param>
+ /// <param name="name">The name for the lambda. Used for emitting debug information.</param>
+ /// <param name="tailCall">A <see cref="Boolean"/> that indicates if tail call optimization will be applied when compiling the created expression. </param>
+ /// <param name="parameters">An <see cref="IEnumerable{T}"/> that contains <see cref="ParameterExpression"/> objects to use to populate the <see cref="P:Parameters"/> collection. </param>
+ /// <returns>A <see cref="LambdaExpression"/> that has the <see cref="P:NodeType"/> property equal to Lambda and the <see cref="P:Body"/> and <see cref="P:Parameters"/> properties set to the specified values.</returns>
+ public static LambdaExpression Lambda(Type delegateType, Expression body, string name, bool tailCall, IEnumerable<ParameterExpression> parameters) {
+ var paramList = parameters.ToReadOnly();
+ ValidateLambdaArgs(delegateType, ref body, paramList);
+
+ return CreateLambda(delegateType, name, body, tailCall, paramList);
+ }
+
+ private static void ValidateLambdaArgs(Type delegateType, ref Expression body, ReadOnlyCollection<ParameterExpression> parameters) {
+ ContractUtils.RequiresNotNull(delegateType, "delegateType");
+ RequiresCanRead(body, "body");
+
+ if (!typeof(Delegate).IsAssignableFrom(delegateType) || delegateType == typeof(Delegate)) {
+ throw Error.LambdaTypeMustBeDerivedFromSystemDelegate();
+ }
+
+ MethodInfo mi;
+ lock (_LambdaDelegateCache) {
+ if (!_LambdaDelegateCache.TryGetValue(delegateType, out mi)) {
+ _LambdaDelegateCache[delegateType] = mi = delegateType.GetMethod("Invoke");
+ }
+ }
+
+ ParameterInfo[] pis = mi.GetParametersCached();
+
+ if (pis.Length > 0) {
+ if (pis.Length != parameters.Count) {
+ throw Error.IncorrectNumberOfLambdaDeclarationParameters();
+ }
+ var set = new Set<ParameterExpression>(pis.Length);
+ for (int i = 0, n = pis.Length; i < n; i++) {
+ ParameterExpression pex = parameters[i];
+ ParameterInfo pi = pis[i];
+ RequiresCanRead(pex, "parameters");
+ Type pType = pi.ParameterType;
+ if (pex.IsByRef) {
+ if (!pType.IsByRef) {
+ //We cannot pass a parameter of T& to a delegate that takes T or any non-ByRef type.
+ throw Error.ParameterExpressionNotValidAsDelegate(pex.Type.MakeByRefType(), pType);
+ }
+ pType = pType.GetElementType();
+ }
+ if (!TypeUtils.AreReferenceAssignable(pex.Type, pType)) {
+ throw Error.ParameterExpressionNotValidAsDelegate(pex.Type, pType);
+ }
+ if (set.Contains(pex)) {
+ throw Error.DuplicateVariable(pex);
+ }
+ set.Add(pex);
+ }
+ } else if (parameters.Count > 0) {
+ throw Error.IncorrectNumberOfLambdaDeclarationParameters();
+ }
+ if (mi.ReturnType != typeof(void) && !TypeUtils.AreReferenceAssignable(mi.ReturnType, body.Type)) {
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), mi.ReturnType) && mi.ReturnType.IsAssignableFrom(body.GetType())) {
+ body = Expression.Quote(body);
+ } else {
+ throw Error.ExpressionTypeDoesNotMatchReturn(body.Type, mi.ReturnType);
+ }
+ }
+ }
+
+ private static bool ValidateTryGetFuncActionArgs(Type[] typeArgs) {
+ if (typeArgs == null) {
+ throw new ArgumentNullException("typeArgs");
+ }
+ for (int i = 0, n = typeArgs.Length; i < n; i++) {
+ var a = typeArgs[i];
+ if (a == null) {
+ throw new ArgumentNullException("typeArgs");
+ }
+ if (a.IsByRef) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Type"/> object that represents a generic System.Func delegate type that has specific type arguments.
+ /// The last type argument specifies the return type of the created delegate.
+ /// </summary>
+ /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Func delegate type.</param>
+ /// <returns>The type of a System.Func delegate that has the specified type arguments.</returns>
+ public static Type GetFuncType(params Type[] typeArgs) {
+ ContractUtils.Requires(ValidateTryGetFuncActionArgs(typeArgs), "typeArgs", Strings.TypeMustNotBeByRef);
+
+ Type result = DelegateHelpers.GetFuncType(typeArgs);
+ if (result == null) {
+ throw Error.IncorrectNumberOfTypeArgsForFunc();
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Type"/> object that represents a generic System.Func delegate type that has specific type arguments.
+ /// The last type argument specifies the return type of the created delegate.
+ /// </summary>
+ /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Func delegate type.</param>
+ /// <param name="funcType">When this method returns, contains the generic System.Func delegate type that has specific type arguments. Contains null if there is no generic System.Func delegate that matches the <paramref name="typeArgs"/>.This parameter is passed uninitialized.</param>
+ /// <returns>true if generic System.Func delegate type was created for specific <paramref name="typeArgs"/>; false otherwise.</returns>
+ public static bool TryGetFuncType(Type[] typeArgs, out Type funcType) {
+ if (ValidateTryGetFuncActionArgs(typeArgs)) {
+ return (funcType = DelegateHelpers.GetFuncType(typeArgs)) != null;
+ }
+ funcType = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Type"/> object that represents a generic System.Action delegate type that has specific type arguments.
+ /// </summary>
+ /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Action delegate type.</param>
+ /// <returns>The type of a System.Action delegate that has the specified type arguments.</returns>
+ public static Type GetActionType(params Type[] typeArgs) {
+ ContractUtils.Requires(ValidateTryGetFuncActionArgs(typeArgs), "typeArgs", Strings.TypeMustNotBeByRef);
+
+ Type result = DelegateHelpers.GetActionType(typeArgs);
+ if (result == null) {
+ throw Error.IncorrectNumberOfTypeArgsForAction();
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Type"/> object that represents a generic System.Action delegate type that has specific type arguments.
+ /// </summary>
+ /// <param name="typeArgs">An array of Type objects that specify the type arguments for the System.Action delegate type.</param>
+ /// <param name="actionType">When this method returns, contains the generic System.Action delegate type that has specific type arguments. Contains null if there is no generic System.Action delegate that matches the <paramref name="typeArgs"/>.This parameter is passed uninitialized.</param>
+ /// <returns>true if generic System.Action delegate type was created for specific <paramref name="typeArgs"/>; false otherwise.</returns>
+ public static bool TryGetActionType(Type[] typeArgs, out Type actionType) {
+ if (ValidateTryGetFuncActionArgs(typeArgs)) {
+ return (actionType = DelegateHelpers.GetActionType(typeArgs)) != null;
+ }
+ actionType = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a <see cref="Type"/> object that represents a generic System.Func or System.Action delegate type that has specific type arguments.
+ /// The last type argument determines the return type of the delegate. If no Func or Action is large enough, it will generate a custom
+ /// delegate type.
+ /// </summary>
+ /// <param name="typeArgs">The type arguments of the delegate.</param>
+ /// <returns>The delegate type.</returns>
+ /// <remarks>
+ /// As with Func, the last argument is the return type. It can be set
+ /// to System.Void to produce an Action.</remarks>
+ public static Type GetDelegateType(params Type[] typeArgs) {
+ ContractUtils.RequiresNotEmpty(typeArgs, "typeArgs");
+ ContractUtils.RequiresNotNullItems(typeArgs, "typeArgs");
+ return DelegateHelpers.MakeDelegateType(typeArgs);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListArgumentProvider.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListArgumentProvider.cs
new file mode 100644
index 00000000000..fefe4121f38
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListArgumentProvider.cs
@@ -0,0 +1,153 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Collections.Generic;
+using System.Text;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Provides a wrapper around an IArgumentProvider which exposes the argument providers
+ /// members out as an IList of Expression. This is used to avoid allocating an array
+ /// which needs to be stored inside of a ReadOnlyCollection. Instead this type has
+ /// the same amount of overhead as an array without duplicating the storage of the
+ /// elements. This ensures that internally we can avoid creating and copying arrays
+ /// while users of the Expression trees also don't pay a size penalty for this internal
+ /// optimization. See IArgumentProvider for more general information on the Expression
+ /// tree optimizations being used here.
+ /// </summary>
+ class ListArgumentProvider : IList<Expression> {
+ private readonly IArgumentProvider _provider;
+ private readonly Expression _arg0;
+
+ internal ListArgumentProvider(IArgumentProvider provider, Expression arg0) {
+ _provider = provider;
+ _arg0 = arg0;
+ }
+
+ #region IList<Expression> Members
+
+ public int IndexOf(Expression item) {
+ if (_arg0 == item) {
+ return 0;
+ }
+
+ for (int i = 1; i < _provider.ArgumentCount; i++) {
+ if (_provider.GetArgument(i) == item) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ public void Insert(int index, Expression item) {
+ throw ContractUtils.Unreachable;
+ }
+
+ public void RemoveAt(int index) {
+ throw ContractUtils.Unreachable;
+ }
+
+ public Expression this[int index] {
+ get {
+ if (index == 0) {
+ return _arg0;
+ }
+
+ return _provider.GetArgument(index);
+ }
+ set {
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ #endregion
+
+ #region ICollection<Expression> Members
+
+ public void Add(Expression item) {
+ throw ContractUtils.Unreachable;
+ }
+
+ public void Clear() {
+ throw ContractUtils.Unreachable;
+ }
+
+ public bool Contains(Expression item) {
+ return IndexOf(item) != -1;
+ }
+
+ public void CopyTo(Expression[] array, int arrayIndex) {
+ array[arrayIndex++] = _arg0;
+ for (int i = 1; i < _provider.ArgumentCount; i++) {
+ array[arrayIndex++] = _provider.GetArgument(i);
+ }
+ }
+
+ public int Count {
+ get { return _provider.ArgumentCount; }
+ }
+
+ public bool IsReadOnly {
+ get { return true; }
+ }
+
+ public bool Remove(Expression item) {
+ throw ContractUtils.Unreachable;
+ }
+
+ #endregion
+
+ #region IEnumerable<Expression> Members
+
+ public IEnumerator<Expression> GetEnumerator() {
+ yield return _arg0;
+
+ for (int i = 1; i < _provider.ArgumentCount; i++) {
+ yield return _provider.GetArgument(i);
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ yield return _arg0;
+
+ for (int i = 1; i < _provider.ArgumentCount; i++) {
+ yield return _provider.GetArgument(i);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListInitExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListInitExpression.cs
new file mode 100644
index 00000000000..5d9f18750a3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ListInitExpression.cs
@@ -0,0 +1,224 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a constructor call that has a collection initializer.
+ /// </summary>
+ /// <remarks>
+ /// Use the <see cref="M:ListInit"/> factory methods to create a ListInitExpression.
+ /// The value of the NodeType property of a ListInitExpression is ListInit.
+ /// </remarks>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.ListInitExpressionProxy))]
+#endif
+ public sealed class ListInitExpression : Expression {
+ private readonly NewExpression _newExpression;
+ private readonly ReadOnlyCollection<ElementInit> _initializers;
+
+ internal ListInitExpression(NewExpression newExpression, ReadOnlyCollection<ElementInit> initializers) {
+ _newExpression = newExpression;
+ _initializers = initializers;
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression"/>. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.ListInit; }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _newExpression.Type; }
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node can be reduced.
+ /// </summary>
+ public override bool CanReduce {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Gets the expression that contains a call to the constructor of a collection type.
+ /// </summary>
+ public NewExpression NewExpression {
+ get { return _newExpression; }
+ }
+
+ /// <summary>
+ /// Gets the element initializers that are used to initialize a collection.
+ /// </summary>
+ public ReadOnlyCollection<ElementInit> Initializers {
+ get { return _initializers; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitListInit(this);
+ }
+
+ /// <summary>
+ /// Reduces the binary expression node to a simpler expression.
+ /// If CanReduce returns true, this should return a valid expression.
+ /// This method is allowed to return another node which itself
+ /// must be reduced.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ public override Expression Reduce() {
+ return MemberInitExpression.ReduceListInit(_newExpression, _initializers, true);
+ }
+ }
+
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="ListInitExpression"/> that uses a method named "Add" to add elements to a collection.
+ /// </summary>
+ /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
+ /// <param name="initializers">An array of <see cref="Expression"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
+ /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
+ public static ListInitExpression ListInit(NewExpression newExpression, params Expression[] initializers) {
+ ContractUtils.RequiresNotNull(newExpression, "newExpression");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ return ListInit(newExpression, initializers as IEnumerable<Expression>);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ListInitExpression"/> that uses a method named "Add" to add elements to a collection.
+ /// </summary>
+ /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
+ /// <param name="initializers">An <see cref="IEnumerable{T}"/> that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
+ /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
+ public static ListInitExpression ListInit(NewExpression newExpression, IEnumerable<Expression> initializers) {
+ ContractUtils.RequiresNotNull(newExpression, "newExpression");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+
+ var initializerlist = initializers.ToReadOnly();
+ if (initializerlist.Count == 0) {
+ throw Error.ListInitializerWithZeroMembers();
+ }
+
+ MethodInfo addMethod = FindMethod(newExpression.Type, "Add", null, new Expression[] { initializerlist[0] }, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ return ListInit(newExpression, addMethod, initializers);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ListInitExpression"/> that uses a specified method to add elements to a collection.
+ /// </summary>
+ /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
+ /// <param name="addMethod">A <see cref="MethodInfo"/> that represents an instance method named "Add" (case insensitive), that adds an element to a collection. </param>
+ /// <param name="initializers">An array of <see cref="Expression"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
+ /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
+ public static ListInitExpression ListInit(NewExpression newExpression, MethodInfo addMethod, params Expression[] initializers) {
+ if (addMethod == null) {
+ return ListInit(newExpression, initializers as IEnumerable<Expression>);
+ }
+ ContractUtils.RequiresNotNull(newExpression, "newExpression");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ return ListInit(newExpression, addMethod, initializers as IEnumerable<Expression>);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ListInitExpression"/> that uses a specified method to add elements to a collection.
+ /// </summary>
+ /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
+ /// <param name="addMethod">A <see cref="MethodInfo"/> that represents an instance method named "Add" (case insensitive), that adds an element to a collection. </param>
+ /// <param name="initializers">An <see cref="IEnumerable{T}"/> that contains <see cref="Expression"/> objects to use to populate the Initializers collection.</param>
+ /// <returns>A <see cref="ListInitExpression"/> that has the <see cref="P:ListInitExpression.NodeType"/> property equal to ListInit and the <see cref="P:ListInitExpression.NewExpression"/> property set to the specified value.</returns>
+ public static ListInitExpression ListInit(NewExpression newExpression, MethodInfo addMethod, IEnumerable<Expression> initializers) {
+ if (addMethod == null) {
+ return ListInit(newExpression, initializers);
+ }
+ ContractUtils.RequiresNotNull(newExpression, "newExpression");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+
+ var initializerlist = initializers.ToReadOnly();
+ if (initializerlist.Count == 0) {
+ throw Error.ListInitializerWithZeroMembers();
+ }
+ ElementInit[] initList = new ElementInit[initializerlist.Count];
+ for (int i = 0; i < initializerlist.Count; i++) {
+ initList[i] = ElementInit(addMethod, initializerlist[i]);
+ }
+ return ListInit(newExpression, new TrueReadOnlyCollection<ElementInit>(initList));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ListInitExpression"/> that uses specified <see cref="M:ElementInit"/> objects to initialize a collection.
+ /// </summary>
+ /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
+ /// <param name="initializers">An array that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
+ /// <returns>
+ /// A <see cref="ListInitExpression"/> that has the <see cref="P:Expressions.NodeType"/> property equal to ListInit
+ /// and the <see cref="P:ListInitExpression.NewExpression"/> and <see cref="P:ListInitExpression.Initializers"/> properties set to the specified values.
+ /// </returns>
+ /// <remarks>
+ /// The <see cref="P:Expressions.Type"/> property of <paramref name="newExpression"/> must represent a type that implements <see cref="System.Collections.IEnumerable"/>.
+ /// The <see cref="P:Expressions.Type"/> property of the resulting <see cref="ListInitExpression"/> is equal to newExpression.Type.
+ /// </remarks>
+ public static ListInitExpression ListInit(NewExpression newExpression, params ElementInit[] initializers) {
+ return ListInit(newExpression, (IEnumerable<ElementInit>)initializers);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ListInitExpression"/> that uses specified <see cref="M:ElementInit"/> objects to initialize a collection.
+ /// </summary>
+ /// <param name="newExpression">A <see cref="NewExpression"/> to set the <see cref="P:ListInitExpression.NewExpression"/> property equal to.</param>
+ /// <param name="initializers">An <see cref="IEnumerable{T}"/> that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</param>
+ /// <returns>An <see cref="IEnumerable{T}"/> that contains <see cref="M:ElementInit"/> objects to use to populate the <see cref="ListInitExpression.Initializers"/> collection.</returns>
+ /// <remarks>
+ /// The <see cref="P:Expressions.Type"/> property of <paramref name="newExpression"/> must represent a type that implements <see cref="System.Collections.IEnumerable"/>.
+ /// The <see cref="P:Expressions.Type"/> property of the resulting <see cref="ListInitExpression"/> is equal to newExpression.Type.
+ /// </remarks>
+ public static ListInitExpression ListInit(NewExpression newExpression, IEnumerable<ElementInit> initializers) {
+ ContractUtils.RequiresNotNull(newExpression, "newExpression");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ var initializerlist = initializers.ToReadOnly();
+ if (initializerlist.Count == 0) {
+ throw Error.ListInitializerWithZeroMembers();
+ }
+ ValidateListInitArgs(newExpression.Type, initializerlist);
+ return new ListInitExpression(newExpression, initializerlist);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LoopExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LoopExpression.cs
new file mode 100644
index 00000000000..13c9b43f480
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/LoopExpression.cs
@@ -0,0 +1,123 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents an infinite loop. It can be exited with "break".
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.LoopExpressionProxy))]
+#endif
+ public sealed class LoopExpression : Expression {
+ private readonly Expression _body;
+ private readonly LabelTarget _break;
+ private readonly LabelTarget _continue;
+
+ internal LoopExpression(Expression body, LabelTarget @break, LabelTarget @continue) {
+ _body = body;
+ _break = @break;
+ _continue = @continue;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _break == null ? typeof(void) : _break.Type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Loop; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Expression"/> that is the body of the loop.
+ /// </summary>
+ public Expression Body {
+ get { return _body; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="LabelTarget"/> that is used by the loop body as a break statement target.
+ /// </summary>
+ public LabelTarget BreakLabel {
+ get { return _break; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="LabelTarget"/> that is used by the loop body as a continue statement target.
+ /// </summary>
+ public LabelTarget ContinueLabel {
+ get { return _continue; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitLoop(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="LoopExpression"/> with the given body.
+ /// </summary>
+ /// <param name="body">The body of the loop.</param>
+ /// <returns>The created <see cref="LoopExpression"/>.</returns>
+ public static LoopExpression Loop(Expression body) {
+ return Loop(body, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="LoopExpression"/> with the given body and break target.
+ /// </summary>
+ /// <param name="body">The body of the loop.</param>
+ /// <param name="break">The break target used by the loop body.</param>
+ /// <returns>The created <see cref="LoopExpression"/>.</returns>
+ public static LoopExpression Loop(Expression body, LabelTarget @break) {
+ return Loop(body, @break, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="LoopExpression"/> with the given body.
+ /// </summary>
+ /// <param name="body">The body of the loop.</param>
+ /// <param name="break">The break target used by the loop body.</param>
+ /// <param name="continue">The continue target used by the loop body.</param>
+ /// <returns>The created <see cref="LoopExpression"/>.</returns>
+ public static LoopExpression Loop(Expression body, LabelTarget @break, LabelTarget @continue) {
+ RequiresCanRead(body, "body");
+ ContractUtils.Requires(@continue == null || @continue.Type == typeof(void), "continue", Strings.LabelTypeMustBeVoid);
+ return new LoopExpression(body, @break, @continue);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberAssignment.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberAssignment.cs
new file mode 100644
index 00000000000..c700b6e0524
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberAssignment.cs
@@ -0,0 +1,98 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents assignment to a member of an object.
+ /// </summary>
+ public sealed class MemberAssignment : MemberBinding {
+ Expression _expression;
+ internal MemberAssignment(MemberInfo member, Expression expression)
+#pragma warning disable 618
+ : base(MemberBindingType.Assignment, member) {
+#pragma warning restore 618
+ _expression = expression;
+ }
+ /// <summary>
+ /// Gets the <see cref="Expression"/> which represents the object whose member is being assigned to.
+ /// </summary>
+ public Expression Expression {
+ get { return _expression; }
+ }
+ }
+
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="MemberAssignment"/> binding the specified value to the given member.
+ /// </summary>
+ /// <param name="member">The <see cref="MemberInfo"/> for the member which is being assigned to.</param>
+ /// <param name="expression">The value to be assigned to <paramref name="member"/>.</param>
+ /// <returns>The created <see cref="MemberAssignment"/>.</returns>
+ public static MemberAssignment Bind(MemberInfo member, Expression expression) {
+ ContractUtils.RequiresNotNull(member, "member");
+ RequiresCanRead(expression, "expression");
+ Type memberType;
+ ValidateSettableFieldOrPropertyMember(member, out memberType);
+ if (!memberType.IsAssignableFrom(expression.Type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ return new MemberAssignment(member, expression);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberAssignment"/> binding the specified value to the given property.
+ /// </summary>
+ /// <param name="propertyAccessor">The <see cref="PropertyInfo"/> for the property which is being assigned to.</param>
+ /// <param name="expression">The value to be assigned to <paramref name="propertyAccessor"/>.</param>
+ /// <returns>The created <see cref="MemberAssignment"/>.</returns>
+ public static MemberAssignment Bind(MethodInfo propertyAccessor, Expression expression) {
+ ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
+ ContractUtils.RequiresNotNull(expression, "expression");
+ ValidateMethodInfo(propertyAccessor);
+ return Bind(GetProperty(propertyAccessor), expression);
+ }
+
+
+ private static void ValidateSettableFieldOrPropertyMember(MemberInfo member, out Type memberType) {
+ FieldInfo fi = member as FieldInfo;
+ if (fi == null) {
+ PropertyInfo pi = member as PropertyInfo;
+ if (pi == null) {
+ throw Error.ArgumentMustBeFieldInfoOrPropertInfo();
+ }
+ if (!pi.CanWrite) {
+ throw Error.PropertyDoesNotHaveSetter(pi);
+ }
+ memberType = pi.PropertyType;
+ } else {
+ memberType = fi.FieldType;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberBinding.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberBinding.cs
new file mode 100644
index 00000000000..7532f71515d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberBinding.cs
@@ -0,0 +1,83 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Describes the binding types that are used in MemberInitExpression objects.
+ /// </summary>
+ public enum MemberBindingType {
+ /// <summary>
+ /// A binding that represents initializing a member with the value of an expression.
+ /// </summary>
+ Assignment,
+ /// <summary>
+ /// A binding that represents recursively initializing members of a member.
+ /// </summary>
+ MemberBinding,
+ /// <summary>
+ /// A binding that represents initializing a member of type <see cref="System.Collections.IList"/> or <see cref="System.Collections.Generic.ICollection{T}"/> from a list of elements.
+ /// </summary>
+ ListBinding
+ }
+
+ /// <summary>
+ /// Provides the base class from which the classes that represent bindings that are used to initialize members of a newly created object derive.
+ /// </summary>
+ public abstract class MemberBinding {
+ MemberBindingType _type;
+ MemberInfo _member;
+
+ /// <summary>
+ /// Initializes an instance of <see cref="MemberBinding"/> class.
+ /// </summary>
+ /// <param name="type">The type of member binding.</param>
+ /// <param name="member">The field or property to be initialized.</param>
+ [Obsolete("Do not use this constructor. It will be removed in future releases.")]
+ protected MemberBinding(MemberBindingType type, MemberInfo member) {
+ _type = type;
+ _member = member;
+ }
+
+ /// <summary>
+ /// Gets the type of binding that is represented.
+ /// </summary>
+ public MemberBindingType BindingType {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Gets the field or property to be initialized.
+ /// </summary>
+ public MemberInfo Member {
+ get { return _member; }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="String"/> that represents the current <see cref="Object"/>.
+ /// </summary>
+ /// <returns>A <see cref="String"/> that represents the current <see cref="Object"/>. </returns>
+ public override string ToString() {
+ return ExpressionStringBuilder.MemberBindingToString(this);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberExpression.cs
new file mode 100644
index 00000000000..7f4ac52f81e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberExpression.cs
@@ -0,0 +1,352 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents accessing a field or property.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.MemberExpressionProxy))]
+#endif
+ public class MemberExpression : Expression {
+ private readonly Expression _expression;
+
+ /// <summary>
+ /// Gets the field or property to be accessed.
+ /// </summary>
+ public MemberInfo Member {
+ get { return GetMember(); }
+ }
+
+ /// <summary>
+ /// Gets the containing object of the field or property.
+ /// </summary>
+ public Expression Expression {
+ get { return _expression; }
+ }
+
+ // param order: factories args in order, then other args
+ internal MemberExpression(Expression expression) {
+
+ _expression = expression;
+ }
+
+ internal static MemberExpression Make(Expression expression, MemberInfo member) {
+ if (member.MemberType == MemberTypes.Field) {
+ FieldInfo fi = (FieldInfo)member;
+ return new FieldExpression(expression, fi);
+ } else {
+ PropertyInfo pi = (PropertyInfo)member;
+ return new PropertyExpression(expression, pi);
+ }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.MemberAccess; }
+ }
+
+ internal virtual MemberInfo GetMember() {
+ throw ContractUtils.Unreachable;
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitMember(this);
+ }
+ }
+
+ internal class FieldExpression : MemberExpression {
+ private readonly FieldInfo _field;
+
+ public FieldExpression(Expression expression, FieldInfo member)
+ : base(expression) {
+ _field = member;
+ }
+
+ internal override MemberInfo GetMember() {
+ return _field;
+ }
+
+ public sealed override Type Type {
+ get { return _field.FieldType; }
+ }
+ }
+
+ internal class PropertyExpression : MemberExpression {
+ private readonly PropertyInfo _property;
+ public PropertyExpression(Expression expression, PropertyInfo member)
+ : base(expression) {
+ _property = member;
+ }
+
+ internal override MemberInfo GetMember() {
+ return _property;
+ }
+
+ public sealed override Type Type {
+ get { return _property.PropertyType; }
+ }
+ }
+
+ public partial class Expression {
+
+ #region Field
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a field.
+ /// </summary>
+ /// <param name="expression">The containing object of the field. This can be null for static fields.</param>
+ /// <param name="field">The field to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames")]
+ public static MemberExpression Field(Expression expression, FieldInfo field) {
+ ContractUtils.RequiresNotNull(field, "field");
+
+ if (field.IsStatic) {
+ ContractUtils.Requires(expression == null, "expression", Strings.OnlyStaticFieldsHaveNullInstance);
+ } else {
+ ContractUtils.Requires(expression != null, "field", Strings.OnlyStaticFieldsHaveNullInstance);
+ RequiresCanRead(expression, "expression");
+ if (!TypeUtils.AreReferenceAssignable(field.DeclaringType, expression.Type)) {
+ throw Error.FieldInfoNotDefinedForType(field.DeclaringType, field.Name, expression.Type);
+ }
+ }
+ return MemberExpression.Make(expression, field);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a field.
+ /// </summary>
+ /// <param name="expression">The containing object of the field. This can be null for static fields.</param>
+ /// <param name="fieldName">The field to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ public static MemberExpression Field(Expression expression, string fieldName) {
+ RequiresCanRead(expression, "expression");
+
+ // bind to public names first
+ FieldInfo fi = expression.Type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (fi == null) {
+ fi = expression.Type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ }
+ if (fi == null) {
+ throw Error.InstanceFieldNotDefinedForType(fieldName, expression.Type);
+ }
+ return Expression.Field(expression, fi);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a field.
+ /// </summary>
+ /// <param name="expression">The containing object of the field. This can be null for static fields.</param>
+ /// <param name="type">The <see cref="Type"/> containing the field.</param>
+ /// <param name="fieldName">The field to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames")]
+ public static MemberExpression Field(Expression expression, Type type, string fieldName) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ // bind to public names first
+ FieldInfo fi = type.GetField(fieldName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (fi == null) {
+ fi = type.GetField(fieldName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ }
+
+ if (fi == null) {
+ throw Error.FieldNotDefinedForType(fieldName, type);
+ }
+ return Expression.Field(expression, fi);
+ }
+ #endregion
+
+ #region Property
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a property.
+ /// </summary>
+ /// <param name="expression">The containing object of the property. This can be null for static properties.</param>
+ /// <param name="propertyName">The property to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ public static MemberExpression Property(Expression expression, string propertyName) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(propertyName, "propertyName");
+ // bind to public names first
+ PropertyInfo pi = expression.Type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (pi == null) {
+ pi = expression.Type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ }
+ if (pi == null) {
+ throw Error.InstancePropertyNotDefinedForType(propertyName, expression.Type);
+ }
+ return Property(expression, pi);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a property.
+ /// </summary>
+ /// <param name="expression">The containing object of the property. This can be null for static properties.</param>
+ /// <param name="type">The <see cref="Type"/> containing the property.</param>
+ /// <param name="propertyName">The property to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ public static MemberExpression Property(Expression expression, Type type, string propertyName) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(propertyName, "propertyName");
+ // bind to public names first
+ PropertyInfo pi = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (pi == null) {
+ pi = type.GetProperty(propertyName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ }
+ if (pi == null) {
+ throw Error.PropertyNotDefinedForType(propertyName, type);
+ }
+ return Property(expression, pi);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a property.
+ /// </summary>
+ /// <param name="expression">The containing object of the property. This can be null for static properties.</param>
+ /// <param name="property">The property to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames")]
+ public static MemberExpression Property(Expression expression, PropertyInfo property) {
+ ContractUtils.RequiresNotNull(property, "property");
+
+ MethodInfo mi = property.GetGetMethod(true) ?? property.GetSetMethod(true);
+
+ if (mi == null) {
+ throw Error.PropertyDoesNotHaveAccessor(property);
+ }
+
+ if (mi.IsStatic) {
+ ContractUtils.Requires(expression == null, "expression", Strings.OnlyStaticPropertiesHaveNullInstance);
+ } else {
+ ContractUtils.Requires(expression != null, "property", Strings.OnlyStaticPropertiesHaveNullInstance);
+ RequiresCanRead(expression, "expression");
+ if (!TypeUtils.IsValidInstanceType(property, expression.Type)) {
+ throw Error.PropertyNotDefinedForType(property, expression.Type);
+ }
+ }
+ return MemberExpression.Make(expression, property);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a property.
+ /// </summary>
+ /// <param name="expression">The containing object of the property. This can be null for static properties.</param>
+ /// <param name="propertyAccessor">An accessor method of the property to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ public static MemberExpression Property(Expression expression, MethodInfo propertyAccessor) {
+ ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
+ ValidateMethodInfo(propertyAccessor);
+ return Property(expression, GetProperty(propertyAccessor));
+ }
+
+ private static PropertyInfo GetProperty(MethodInfo mi) {
+ Type type = mi.DeclaringType;
+ BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic;
+ flags |= (mi.IsStatic) ? BindingFlags.Static : BindingFlags.Instance;
+ PropertyInfo[] props = type.GetProperties(flags);
+ foreach (PropertyInfo pi in props) {
+ if (pi.CanRead && CheckMethod(mi, pi.GetGetMethod(true))) {
+ return pi;
+ }
+ if (pi.CanWrite && CheckMethod(mi, pi.GetSetMethod(true))) {
+ return pi;
+ }
+ }
+ throw Error.MethodNotPropertyAccessor(mi.DeclaringType, mi.Name);
+ }
+
+ private static bool CheckMethod(MethodInfo method, MethodInfo propertyMethod) {
+ if (method == propertyMethod) {
+ return true;
+ }
+ // If the type is an interface then the handle for the method got by the compiler will not be the
+ // same as that returned by reflection.
+ // Check for this condition and try and get the method from reflection.
+ Type type = method.DeclaringType;
+ if (type.IsInterface && method.Name == propertyMethod.Name && type.GetMethod(method.Name) == propertyMethod) {
+ return true;
+ }
+ return false;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a property or field.
+ /// </summary>
+ /// <param name="expression">The containing object of the member. This can be null for static members.</param>
+ /// <param name="propertyOrFieldName">The member to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ public static MemberExpression PropertyOrField(Expression expression, string propertyOrFieldName) {
+ RequiresCanRead(expression, "expression");
+ // bind to public names first
+ PropertyInfo pi = expression.Type.GetProperty(propertyOrFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (pi != null)
+ return Property(expression, pi);
+ FieldInfo fi = expression.Type.GetField(propertyOrFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (fi != null)
+ return Field(expression, fi);
+ pi = expression.Type.GetProperty(propertyOrFieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (pi != null)
+ return Property(expression, pi);
+ fi = expression.Type.GetField(propertyOrFieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
+ if (fi != null)
+ return Field(expression, fi);
+
+ throw Error.NotAMemberOfType(propertyOrFieldName, expression.Type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberExpression"/> accessing a property or field.
+ /// </summary>
+ /// <param name="expression">The containing object of the member. This can be null for static members.</param>
+ /// <param name="member">The member to be accessed.</param>
+ /// <returns>The created <see cref="MemberExpression"/>.</returns>
+ public static MemberExpression MakeMemberAccess(Expression expression, MemberInfo member) {
+ ContractUtils.RequiresNotNull(member, "member");
+
+ FieldInfo fi = member as FieldInfo;
+ if (fi != null) {
+ return Expression.Field(expression, fi);
+ }
+ PropertyInfo pi = member as PropertyInfo;
+ if (pi != null) {
+ return Expression.Property(expression, pi);
+ }
+ throw Error.MemberNotFieldOrProperty(member);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberInitExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberInitExpression.cs
new file mode 100644
index 00000000000..3481b59d2db
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberInitExpression.cs
@@ -0,0 +1,171 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents calling a constructor and initializing one or more members of the new object.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.MemberInitExpressionProxy))]
+#endif
+ public sealed class MemberInitExpression : Expression {
+ private readonly NewExpression _newExpression;
+ private readonly ReadOnlyCollection<MemberBinding> _bindings;
+
+ internal MemberInitExpression(NewExpression newExpression, ReadOnlyCollection<MemberBinding> bindings) {
+ _newExpression = newExpression;
+ _bindings = bindings;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _newExpression.Type; }
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node can be reduced.
+ /// </summary>
+ public override bool CanReduce {
+ get {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.MemberInit; }
+ }
+
+ ///<summary>Gets the expression that represents the constructor call.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.NewExpression" /> that represents the constructor call.</returns>
+ public NewExpression NewExpression {
+ get { return _newExpression; }
+ }
+
+ ///<summary>Gets the bindings that describe how to initialize the members of the newly created object.</summary>
+ ///<returns>A <see cref="T:System.Collections.ObjectModel.ReadOnlyCollection`1" /> of <see cref="T:Microsoft.Linq.Expressions.MemberBinding" /> objects which describe how to initialize the members.</returns>
+ public ReadOnlyCollection<MemberBinding> Bindings {
+ get { return _bindings; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitMemberInit(this);
+ }
+
+ /// <summary>
+ /// Reduces the <see cref="MemberInitExpression"/> to a simpler expression.
+ /// If CanReduce returns true, this should return a valid expression.
+ /// This method is allowed to return another node which itself
+ /// must be reduced.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ public override Expression Reduce() {
+ return ReduceMemberInit(_newExpression, _bindings, true);
+ }
+
+ internal static Expression ReduceMemberInit(Expression objExpression, ReadOnlyCollection<MemberBinding> bindings, bool keepOnStack) {
+ var objVar = Expression.Variable(objExpression.Type, null);
+ int count = bindings.Count;
+ var block = new Expression[count + 2];
+ block[0] = Expression.Assign(objVar, objExpression);
+ for (int i = 0; i < count; i++) {
+ block[i + 1] = ReduceMemberBinding(objVar, bindings[i]);
+ }
+ block[count + 1] = keepOnStack ? (Expression)objVar : Expression.Empty();
+ return Expression.Block(new TrueReadOnlyCollection<Expression>(block));
+ }
+
+ internal static Expression ReduceListInit(Expression listExpression, ReadOnlyCollection<ElementInit> initializers, bool keepOnStack) {
+ var listVar = Expression.Variable(listExpression.Type, null);
+ int count = initializers.Count;
+ var block = new Expression[count + 2];
+ block[0] = Expression.Assign(listVar, listExpression);
+ for (int i = 0; i < count; i++) {
+ ElementInit element = initializers[i];
+ block[i + 1] = Expression.Call(listVar, element.AddMethod, element.Arguments);
+ }
+ block[count + 1] = keepOnStack ? (Expression)listVar : Expression.Empty();
+ return Expression.Block(new TrueReadOnlyCollection<Expression>(block));
+ }
+
+ internal static Expression ReduceMemberBinding(ParameterExpression objVar, MemberBinding binding) {
+ MemberExpression member = Expression.MakeMemberAccess(objVar, binding.Member);
+ switch (binding.BindingType) {
+ case MemberBindingType.Assignment:
+ return Expression.Assign(member, ((MemberAssignment)binding).Expression);
+ case MemberBindingType.ListBinding:
+ return ReduceListInit(member, ((MemberListBinding)binding).Initializers, false);
+ case MemberBindingType.MemberBinding:
+ return ReduceMemberInit(member, ((MemberMemberBinding)binding).Bindings, false);
+ default: throw ContractUtils.Unreachable;
+ }
+ }
+ }
+
+ public partial class Expression {
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MemberInitExpression" />.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MemberInitExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.MemberInit" /> and the <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.NewExpression" /> and <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.Bindings" /> properties set to the specified values.</returns>
+ ///<param name="newExpression">A <see cref="T:Microsoft.Linq.Expressions.NewExpression" /> to set the <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.NewExpression" /> property equal to.</param>
+ ///<param name="bindings">An array of <see cref="T:Microsoft.Linq.Expressions.MemberBinding" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.Bindings" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="newExpression" /> or <paramref name="bindings" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">The <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> property of an element of <paramref name="bindings" /> does not represent a member of the type that <paramref name="newExpression" />.Type represents.</exception>
+ public static MemberInitExpression MemberInit(NewExpression newExpression, params MemberBinding[] bindings) {
+ return MemberInit(newExpression, (IEnumerable<MemberBinding>)bindings);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MemberInitExpression" />.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MemberInitExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.MemberInit" /> and the <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.NewExpression" /> and <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.Bindings" /> properties set to the specified values.</returns>
+ ///<param name="newExpression">A <see cref="T:Microsoft.Linq.Expressions.NewExpression" /> to set the <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.NewExpression" /> property equal to.</param>
+ ///<param name="bindings">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:Microsoft.Linq.Expressions.MemberBinding" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MemberInitExpression.Bindings" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="newExpression" /> or <paramref name="bindings" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">The <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> property of an element of <paramref name="bindings" /> does not represent a member of the type that <paramref name="newExpression" />.Type represents.</exception>
+ public static MemberInitExpression MemberInit(NewExpression newExpression, IEnumerable<MemberBinding> bindings) {
+ ContractUtils.RequiresNotNull(newExpression, "newExpression");
+ ContractUtils.RequiresNotNull(bindings, "bindings");
+ var roBindings = bindings.ToReadOnly();
+ ValidateMemberInitArgs(newExpression.Type, roBindings);
+ return new MemberInitExpression(newExpression, roBindings);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberListBinding.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberListBinding.cs
new file mode 100644
index 00000000000..e46e58ac9b2
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberListBinding.cs
@@ -0,0 +1,128 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents initializing the elements of a collection member of a newly created object.
+ /// </summary>
+ public sealed class MemberListBinding : MemberBinding {
+ ReadOnlyCollection<ElementInit> _initializers;
+ internal MemberListBinding(MemberInfo member, ReadOnlyCollection<ElementInit> initializers)
+#pragma warning disable 618
+ : base(MemberBindingType.ListBinding, member) {
+#pragma warning restore 618
+ _initializers = initializers;
+ }
+
+ /// <summary>
+ /// Gets the element initializers for initializing a collection member of a newly created object.
+ /// </summary>
+ public ReadOnlyCollection<ElementInit> Initializers {
+ get { return _initializers; }
+ }
+ }
+
+
+ public partial class Expression {
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> where the member is a field or property.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.MemberBindingType.ListBinding" /> and the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> and <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> properties set to the specified values.</returns>
+ ///<param name="member">A <see cref="T:System.Reflection.MemberInfo" /> that represents a field or property to set the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> property equal to.</param>
+ ///<param name="initializers">An array of <see cref="T:Microsoft.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="member" /> is null. -or-One or more elements of <paramref name="initializers" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="member" /> does not represent a field or property.-or-The <see cref="P:System.Reflection.FieldInfo.FieldType" /> or <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the field or property that <paramref name="member" /> represents does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>
+ public static MemberListBinding ListBind(MemberInfo member, params ElementInit[] initializers) {
+ ContractUtils.RequiresNotNull(member, "member");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ return ListBind(member, (IEnumerable<ElementInit>)initializers);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> where the member is a field or property.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.MemberBindingType.ListBinding" /> and the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> and <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> properties set to the specified values.</returns>
+ ///<param name="member">A <see cref="T:System.Reflection.MemberInfo" /> that represents a field or property to set the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> property equal to.</param>
+ ///<param name="initializers">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:Microsoft.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="member" /> is null. -or-One or more elements of <paramref name="initializers" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="member" /> does not represent a field or property.-or-The <see cref="P:System.Reflection.FieldInfo.FieldType" /> or <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the field or property that <paramref name="member" /> represents does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>
+ public static MemberListBinding ListBind(MemberInfo member, IEnumerable<ElementInit> initializers) {
+ ContractUtils.RequiresNotNull(member, "member");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ Type memberType;
+ ValidateGettableFieldOrPropertyMember(member, out memberType);
+ var initList = initializers.ToReadOnly();
+ ValidateListInitArgs(memberType, initList);
+ return new MemberListBinding(member, initList);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> object based on a specified property accessor method.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.MemberBindingType.ListBinding" />, the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> property set to the <see cref="T:System.Reflection.MemberInfo" /> that represents the property accessed in <paramref name="propertyAccessor" />, and <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> populated with the elements of <paramref name="initializers" />.</returns>
+ ///<param name="propertyAccessor">A <see cref="T:System.Reflection.MethodInfo" /> that represents a property accessor method.</param>
+ ///<param name="initializers">An array of <see cref="T:Microsoft.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="propertyAccessor" /> is null. -or-One or more elements of <paramref name="initializers" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="propertyAccessor" /> does not represent a property accessor method.-or-The <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the property that the method represented by <paramref name="propertyAccessor" /> accesses does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>
+ public static MemberListBinding ListBind(MethodInfo propertyAccessor, params ElementInit[] initializers) {
+ ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ return ListBind(propertyAccessor, (IEnumerable<ElementInit>)initializers);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> based on a specified property accessor method.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.MemberBindingType.ListBinding" />, the <see cref="P:Microsoft.Linq.Expressions.MemberBinding.Member" /> property set to the <see cref="T:System.Reflection.MemberInfo" /> that represents the property accessed in <paramref name="propertyAccessor" />, and <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> populated with the elements of <paramref name="initializers" />.</returns>
+ ///<param name="propertyAccessor">A <see cref="T:System.Reflection.MethodInfo" /> that represents a property accessor method.</param>
+ ///<param name="initializers">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:Microsoft.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="propertyAccessor" /> is null. -or-One or more elements of <paramref name="initializers" /> are null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="propertyAccessor" /> does not represent a property accessor method.-or-The <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the property that the method represented by <paramref name="propertyAccessor" /> accesses does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>
+ public static MemberListBinding ListBind(MethodInfo propertyAccessor, IEnumerable<ElementInit> initializers) {
+ ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ return ListBind(GetProperty(propertyAccessor), initializers);
+ }
+
+ private static void ValidateListInitArgs(Type listType, ReadOnlyCollection<ElementInit> initializers) {
+ if (!typeof(IEnumerable).IsAssignableFrom(listType)) {
+ throw Error.TypeNotIEnumerable(listType);
+ }
+ for (int i = 0, n = initializers.Count; i < n; i++) {
+ ElementInit element = initializers[i];
+ ContractUtils.RequiresNotNull(element, "initializers");
+ ValidateCallInstanceType(listType, element.AddMethod);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberMemberBinding.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberMemberBinding.cs
new file mode 100644
index 00000000000..58308c31da7
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MemberMemberBinding.cs
@@ -0,0 +1,142 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents initializing members of a member of a newly created object.
+ /// </summary>
+ /// <remarks>
+ /// Use the <see cref="M:MemberBind"/> factory methods to create a <see cref="MemberMemberBinding"/>.
+ /// The value of the <see cref="P:MemberBinding.BindingType"/> property of a <see cref="MemberMemberBinding"/> object is <see cref="MemberBinding"/>.
+ /// </remarks>
+ public sealed class MemberMemberBinding : MemberBinding {
+ ReadOnlyCollection<MemberBinding> _bindings;
+ internal MemberMemberBinding(MemberInfo member, ReadOnlyCollection<MemberBinding> bindings)
+#pragma warning disable 618
+ : base(MemberBindingType.MemberBinding, member) {
+#pragma warning restore 618
+ _bindings = bindings;
+ }
+
+ /// <summary>
+ /// Gets the bindings that describe how to initialize the members of a member.
+ /// </summary>
+ public ReadOnlyCollection<MemberBinding> Bindings {
+ get { return _bindings; }
+ }
+ }
+
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a field or property.
+ /// </summary>
+ /// <param name="member">The <see cref="MemberInfo"/> to set the <see cref="P:MemberBinding.Member"/> property equal to.</param>
+ /// <param name="bindings">An array of <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
+ /// <returns>A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/> and the <see cref="P:MemberBinding.Member"/> and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.</returns>
+ public static MemberMemberBinding MemberBind(MemberInfo member, params MemberBinding[] bindings) {
+ ContractUtils.RequiresNotNull(member, "member");
+ ContractUtils.RequiresNotNull(bindings, "bindings");
+ return MemberBind(member, (IEnumerable<MemberBinding>)bindings);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a field or property.
+ /// </summary>
+ /// <param name="member">The <see cref="MemberInfo"/> to set the <see cref="P:MemberBinding.Member"/> property equal to.</param>
+ /// <param name="bindings">An <see cref="IEnumerable{T}"/> that contains <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
+ /// <returns>A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/> and the <see cref="P:MemberBinding.Member"/> and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.</returns>
+ public static MemberMemberBinding MemberBind(MemberInfo member, IEnumerable<MemberBinding> bindings) {
+ ContractUtils.RequiresNotNull(member, "member");
+ ContractUtils.RequiresNotNull(bindings, "bindings");
+ ReadOnlyCollection<MemberBinding> roBindings = bindings.ToReadOnly();
+ Type memberType;
+ ValidateGettableFieldOrPropertyMember(member, out memberType);
+ ValidateMemberInitArgs(memberType, roBindings);
+ return new MemberMemberBinding(member, roBindings);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a member that is accessed by using a property accessor method.
+ /// </summary>
+ /// <param name="propertyAccessor">The <see cref="MemberInfo"/> that represents a property accessor method.</param>
+ /// <param name="bindings">An <see cref="IEnumerable{T}"/> that contains <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
+ /// <returns>
+ /// A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/>,
+ /// the Member property set to the <see cref="PropertyInfo"/> that represents the property accessed in <paramref name="propertyAccessor"/>,
+ /// and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.
+ /// </returns>
+ public static MemberMemberBinding MemberBind(MethodInfo propertyAccessor, params MemberBinding[] bindings) {
+ ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
+ return MemberBind(GetProperty(propertyAccessor), bindings);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a member that is accessed by using a property accessor method.
+ /// </summary>
+ /// <param name="propertyAccessor">The <see cref="MemberInfo"/> that represents a property accessor method.</param>
+ /// <param name="bindings">An <see cref="IEnumerable{T}"/> that contains <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
+ /// <returns>
+ /// A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/>,
+ /// the Member property set to the <see cref="PropertyInfo"/> that represents the property accessed in <paramref name="propertyAccessor"/>,
+ /// and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.
+ /// </returns>
+ public static MemberMemberBinding MemberBind(MethodInfo propertyAccessor, IEnumerable<MemberBinding> bindings) {
+ ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
+ return MemberBind(GetProperty(propertyAccessor), bindings);
+ }
+
+ private static void ValidateGettableFieldOrPropertyMember(MemberInfo member, out Type memberType) {
+ FieldInfo fi = member as FieldInfo;
+ if (fi == null) {
+ PropertyInfo pi = member as PropertyInfo;
+ if (pi == null) {
+ throw Error.ArgumentMustBeFieldInfoOrPropertInfo();
+ }
+ if (!pi.CanRead) {
+ throw Error.PropertyDoesNotHaveGetter(pi);
+ }
+ memberType = pi.PropertyType;
+ } else {
+ memberType = fi.FieldType;
+ }
+ }
+
+ private static void ValidateMemberInitArgs(Type type, ReadOnlyCollection<MemberBinding> bindings) {
+ for (int i = 0, n = bindings.Count; i < n; i++) {
+ MemberBinding b = bindings[i];
+ ContractUtils.RequiresNotNull(b, "bindings");
+ if (!b.Member.DeclaringType.IsAssignableFrom(type)) {
+ throw Error.NotAMemberOfType(b.Member.Name, type);
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MethodCallExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MethodCallExpression.cs
new file mode 100644
index 00000000000..1fc2f424b1c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/MethodCallExpression.cs
@@ -0,0 +1,1022 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a call to either static or an instance method.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.MethodCallExpressionProxy))]
+#endif
+ public class MethodCallExpression : Expression, IArgumentProvider {
+ private readonly MethodInfo _method;
+
+ internal MethodCallExpression(MethodInfo method) {
+
+ _method = method;
+ }
+
+ internal virtual Expression GetInstance() {
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Call; }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _method.ReturnType; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="MethodInfo" /> for the method to be called.
+ /// </summary>
+ public MethodInfo Method {
+ get { return _method; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Expression" /> that represents the instance
+ /// for instance method calls or null for static method cals.
+ /// </summary>
+ public Expression Object {
+ get { return GetInstance(); }
+ }
+
+ /// <summary>
+ /// Gets a collection of expressions that represent arguments to the method call.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Arguments {
+ get { return GetOrMakeArguments(); }
+ }
+
+ internal virtual ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ throw ContractUtils.Unreachable;
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitMethodCall(this);
+ }
+
+ /// <summary>
+ /// Returns a new MethodCallExpression replacing the existing instance/args with the
+ /// newly provided instance and args. Arguments can be null to use the existing
+ /// arguments.
+ ///
+ /// This helper is provided to allow re-writing of nodes to not depend on the specific optimized
+ /// subclass of MethodCallExpression which is being used.
+ /// </summary>
+ internal virtual MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ throw ContractUtils.Unreachable;
+ }
+
+ #region IArgumentProvider Members
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ throw ContractUtils.Unreachable;
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get { throw ContractUtils.Unreachable; }
+ }
+
+ #endregion
+ }
+
+ #region Specialized Subclasses
+
+ internal class MethodCallExpressionN : MethodCallExpression, IArgumentProvider {
+ private IList<Expression> _arguments;
+
+ public MethodCallExpressionN(MethodInfo method, IList<Expression> args)
+ : base(method) {
+ _arguments = args;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(ref _arguments);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance == null);
+ Debug.Assert(args == null || args.Count == _arguments.Count);
+
+ return Expression.Call(Method, args ?? _arguments);
+ }
+ }
+
+ internal class InstanceMethodCallExpressionN : MethodCallExpression, IArgumentProvider {
+ private IList<Expression> _arguments;
+ private readonly Expression _instance;
+
+ public InstanceMethodCallExpressionN(MethodInfo method, Expression instance, IList<Expression> args)
+ : base(method) {
+ _instance = instance;
+ _arguments = args;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ internal override Expression GetInstance() {
+ return _instance;
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(ref _arguments);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance != null);
+ Debug.Assert(args == null || args.Count == _arguments.Count);
+
+ return Expression.Call(instance, Method, args ?? _arguments);
+ }
+ }
+
+ internal class MethodCallExpression1 : MethodCallExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+
+ public MethodCallExpression1(MethodInfo method, Expression arg0)
+ : base(method) {
+ _arg0 = arg0;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 1;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance == null);
+ Debug.Assert(args == null || args.Count == 1);
+
+ if (args != null) {
+ return Expression.Call(Method, args[0]);
+ }
+
+ return Expression.Call(Method, ReturnObject<Expression>(_arg0));
+ }
+ }
+
+ internal class MethodCallExpression2 : MethodCallExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1; // storage for the 2nd arg
+
+ public MethodCallExpression2(MethodInfo method, Expression arg0, Expression arg1)
+ : base(method) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 2;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance == null);
+ Debug.Assert(args == null || args.Count == 2);
+
+ if (args != null) {
+ return Expression.Call(Method, args[0], args[1]);
+ }
+ return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1);
+ }
+ }
+
+ internal class MethodCallExpression3 : MethodCallExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2; // storage for the 2nd - 3rd args.
+
+ public MethodCallExpression3(MethodInfo method, Expression arg0, Expression arg1, Expression arg2)
+ : base(method) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 3;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance == null);
+ Debug.Assert(args == null || args.Count == 3);
+
+ if (args != null) {
+ return Expression.Call(Method, args[0], args[1], args[2]);
+ }
+ return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1, _arg2);
+ }
+ }
+
+ internal class MethodCallExpression4 : MethodCallExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2, _arg3; // storage for the 2nd - 4th args.
+
+ public MethodCallExpression4(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3)
+ : base(method) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ _arg3 = arg3;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ case 3: return _arg3;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 4;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance == null);
+ Debug.Assert(args == null || args.Count == 4);
+
+ if (args != null) {
+ return Expression.Call(Method, args[0], args[1], args[2], args[3]);
+ }
+ return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1, _arg2, _arg3);
+ }
+ }
+
+ internal class MethodCallExpression5 : MethodCallExpression, IArgumentProvider {
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2, _arg3, _arg4; // storage for the 2nd - 5th args.
+
+ public MethodCallExpression5(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4)
+ : base(method) {
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ _arg3 = arg3;
+ _arg4 = arg4;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ case 3: return _arg3;
+ case 4: return _arg4;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 5;
+ }
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance == null);
+ Debug.Assert(args == null || args.Count == 5);
+
+ if (args != null) {
+ return Expression.Call(Method, args[0], args[1], args[2], args[3], args[4]);
+ }
+
+ return Expression.Call(Method, ReturnObject<Expression>(_arg0), _arg1, _arg2, _arg3, _arg4);
+ }
+ }
+
+ internal class InstanceMethodCallExpression2 : MethodCallExpression, IArgumentProvider {
+ private readonly Expression _instance;
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1; // storage for the 2nd argument
+
+ public InstanceMethodCallExpression2(MethodInfo method, Expression instance, Expression arg0, Expression arg1)
+ : base(method) {
+ Debug.Assert(instance != null);
+
+ _instance = instance;
+ _arg0 = arg0;
+ _arg1 = arg1;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 2;
+ }
+ }
+
+ internal override Expression GetInstance() {
+ return _instance;
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance != null);
+ Debug.Assert(args == null || args.Count == 2);
+
+ if (args != null) {
+ return Expression.Call(instance, Method, args[0], args[1]);
+ }
+ return Expression.Call(instance, Method, ReturnObject<Expression>(_arg0), _arg1);
+ }
+ }
+
+ internal class InstanceMethodCallExpression3 : MethodCallExpression, IArgumentProvider {
+ private readonly Expression _instance;
+ private object _arg0; // storage for the 1st argument or a readonly collection. See IArgumentProvider
+ private readonly Expression _arg1, _arg2; // storage for the 2nd - 3rd argument
+
+ public InstanceMethodCallExpression3(MethodInfo method, Expression instance, Expression arg0, Expression arg1, Expression arg2)
+ : base(method) {
+ Debug.Assert(instance != null);
+
+ _instance = instance;
+ _arg0 = arg0;
+ _arg1 = arg1;
+ _arg2 = arg2;
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ switch (index) {
+ case 0: return ReturnObject<Expression>(_arg0);
+ case 1: return _arg1;
+ case 2: return _arg2;
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return 3;
+ }
+ }
+
+ internal override Expression GetInstance() {
+ return _instance;
+ }
+
+ internal override ReadOnlyCollection<Expression> GetOrMakeArguments() {
+ return ReturnReadOnly(this, ref _arg0);
+ }
+
+ internal override MethodCallExpression Rewrite(Expression instance, IList<Expression> args) {
+ Debug.Assert(instance != null);
+ Debug.Assert(args == null || args.Count == 3);
+
+ if (args != null) {
+ return Expression.Call(instance, Method, args[0], args[1], args[2]);
+ }
+ return Expression.Call(instance, Method, ReturnObject<Expression>(_arg0), _arg1, _arg2);
+ }
+ }
+
+ #endregion
+
+ public partial class Expression {
+
+ #region Call
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes one argument.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
+ ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="method" /> is null.</exception>
+ public static MethodCallExpression Call(MethodInfo method, Expression arg0) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 1, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+
+ return new MethodCallExpression1(method, arg0);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes two arguments.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
+ ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="method" /> is null.</exception>
+ public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+ ContractUtils.RequiresNotNull(arg1, "arg1");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 2, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+ arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
+
+ return new MethodCallExpression2(method, arg0, arg1);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes three arguments.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
+ ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
+ ///<param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="method" /> is null.</exception>
+ public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+ ContractUtils.RequiresNotNull(arg1, "arg1");
+ ContractUtils.RequiresNotNull(arg2, "arg2");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 3, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+ arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
+ arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
+
+ return new MethodCallExpression3(method, arg0, arg1, arg2);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes four arguments.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
+ ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
+ ///<param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
+ ///<param name="arg3">The <see cref="Expression" /> that represents the fourth argument.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="method" /> is null.</exception>
+ public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+ ContractUtils.RequiresNotNull(arg1, "arg1");
+ ContractUtils.RequiresNotNull(arg2, "arg2");
+ ContractUtils.RequiresNotNull(arg3, "arg3");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 4, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+ arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
+ arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
+ arg3 = ValidateOneArgument(method, ExpressionType.Call, arg3, pis[3]);
+
+ return new MethodCallExpression4(method, arg0, arg1, arg2, arg3);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to a static method that takes five arguments.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
+ ///<param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ ///<param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
+ ///<param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
+ ///<param name="arg3">The <see cref="Expression" /> that represents the fourth argument.</param>
+ ///<param name="arg4">The <see cref="Expression" /> that represents the fifth argument.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="method" /> is null.</exception>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+ ContractUtils.RequiresNotNull(arg1, "arg1");
+ ContractUtils.RequiresNotNull(arg2, "arg2");
+ ContractUtils.RequiresNotNull(arg3, "arg3");
+ ContractUtils.RequiresNotNull(arg4, "arg4");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(null, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 5, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+ arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
+ arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
+ arg3 = ValidateOneArgument(method, ExpressionType.Call, arg3, pis[3]);
+ arg4 = ValidateOneArgument(method, ExpressionType.Call, arg4, pis[4]);
+
+ return new MethodCallExpression5(method, arg0, arg1, arg2, arg3, arg4);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MethodCallExpression" /> that represents a call to a static (Shared in Visual Basic) method.
+ /// </summary>
+ /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
+ /// <param name="arguments">The array of one or more of <see cref="Expression" /> that represents the call arguments.</param>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(MethodInfo method, params Expression[] arguments) {
+ return Call(null, method, arguments);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MethodCallExpression" /> that represents a call to a static (Shared in Visual Basic) method.
+ /// </summary>
+ /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
+ /// <param name="arguments">A collection of <see cref="Expression" /> that represents the call arguments.</param>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(MethodInfo method, IEnumerable<Expression> arguments) {
+ return Call(null, method, arguments);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MethodCallExpression" /> that represents a call to a method that takes no arguments.
+ /// </summary>
+ /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
+ /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(Expression instance, MethodInfo method) {
+ return Call(instance, method, EmptyReadOnlyCollection<Expression>.Instance);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MethodCallExpression" /> that represents a method call.
+ /// </summary>
+ /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
+ /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
+ /// <param name="arguments">An array of one or more of <see cref="Expression" /> that represents the call arguments.</param>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(Expression instance, MethodInfo method, params Expression[] arguments) {
+ return Call(instance, method, (IEnumerable<Expression>)arguments);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MethodCallExpression" /> that represents a call to a method that takes two arguments.
+ /// </summary>
+ /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
+ /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
+ /// <param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ /// <param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+ ContractUtils.RequiresNotNull(arg1, "arg1");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(instance, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 2, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+ arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
+
+ if (instance != null) {
+ return new InstanceMethodCallExpression2(method, instance, arg0, arg1);
+ }
+
+ return new MethodCallExpression2(method, arg0, arg1);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="MethodCallExpression" /> that represents a call to a method that takes three arguments.
+ /// </summary>
+ /// <param name="instance">An <see cref="Expression" /> that specifies the instance for an instance call. (pass null for a static (Shared in Visual Basic) method).</param>
+ /// <param name="method">The <see cref="MethodInfo" /> that represents the target method.</param>
+ /// <param name="arg0">The <see cref="Expression" /> that represents the first argument.</param>
+ /// <param name="arg1">The <see cref="Expression" /> that represents the second argument.</param>
+ /// <param name="arg2">The <see cref="Expression" /> that represents the third argument.</param>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> properties set to the specified values.</returns>
+ public static MethodCallExpression Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1, Expression arg2) {
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(arg0, "arg0");
+ ContractUtils.RequiresNotNull(arg1, "arg1");
+ ContractUtils.RequiresNotNull(arg2, "arg2");
+
+ ParameterInfo[] pis = ValidateMethodAndGetParameters(instance, method);
+
+ ValidateArgumentCount(method, ExpressionType.Call, 3, pis);
+
+ arg0 = ValidateOneArgument(method, ExpressionType.Call, arg0, pis[0]);
+ arg1 = ValidateOneArgument(method, ExpressionType.Call, arg1, pis[1]);
+ arg2 = ValidateOneArgument(method, ExpressionType.Call, arg2, pis[2]);
+
+ if (instance != null) {
+ return new InstanceMethodCallExpression3(method, instance, arg0, arg1, arg2);
+ }
+ return new MethodCallExpression3(method, arg0, arg1, arg2);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to an instance method by calling the appropriate factory method.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" />, the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> property equal to <paramref name="instance" />, <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> set to the <see cref="T:System.Reflection.MethodInfo" /> that represents the specified instance method, and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> set to the specified arguments.</returns>
+ ///<param name="instance">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> whose <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property value will be searched for a specific method.</param>
+ ///<param name="methodName">The name of the method.</param>
+ ///<param name="typeArguments">
+ ///An array of <see cref="T:System.Type" /> objects that specify the type parameters of the generic method.
+ ///This argument should be null when <paramref name="methodName" /> specifies a non-generic method.
+ ///</param>
+ ///<param name="arguments">An array of <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects that represents the arguments to the method.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="instance" /> or <paramref name="methodName" /> is null.</exception>
+ ///<exception cref="T:System.InvalidOperationException">No method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="instance" />.Type or its base types.-or-More than one method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="instance" />.Type or its base types.</exception>
+ public static MethodCallExpression Call(Expression instance, string methodName, Type[] typeArguments, params Expression[] arguments) {
+ ContractUtils.RequiresNotNull(instance, "instance");
+ ContractUtils.RequiresNotNull(methodName, "methodName");
+ if (arguments == null) {
+ arguments = new Expression[0];
+ }
+
+ BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
+ return Expression.Call(instance, FindMethod(instance.Type, methodName, typeArguments, arguments, flags), arguments);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a call to a static (Shared in Visual Basic) method by calling the appropriate factory method.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" />, the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property set to the <see cref="T:System.Reflection.MethodInfo" /> that represents the specified static (Shared in Visual Basic) method, and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> property set to the specified arguments.</returns>
+ ///<param name="type">The <see cref="T:System.Type" /> that specifies the type that contains the specified static (Shared in Visual Basic) method.</param>
+ ///<param name="methodName">The name of the method.</param>
+ ///<param name="typeArguments">
+ ///An array of <see cref="T:System.Type" /> objects that specify the type parameters of the generic method.
+ ///This argument should be null when <paramref name="methodName" /> specifies a non-generic method.
+ ///</param>
+ ///<param name="arguments">An array of <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects that represent the arguments to the method.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="type" /> or <paramref name="methodName" /> is null.</exception>
+ ///<exception cref="T:System.InvalidOperationException">No method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="type" /> or its base types.-or-More than one method whose name is <paramref name="methodName" />, whose type parameters match <paramref name="typeArguments" />, and whose parameter types match <paramref name="arguments" /> is found in <paramref name="type" /> or its base types.</exception>
+ public static MethodCallExpression Call(Type type, string methodName, Type[] typeArguments, params Expression[] arguments) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(methodName, "methodName");
+
+ if (arguments == null) arguments = new Expression[] { };
+ BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
+ return Expression.Call(null, FindMethod(type, methodName, typeArguments, arguments, flags), arguments);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents a method call.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" />, <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" />, and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> properties set to the specified values.</returns>
+ ///<param name="instance">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> property equal to (pass null for a static (Shared in Visual Basic) method).</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Method" /> property equal to.</param>
+ ///<param name="arguments">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="method" /> is null.-or-<paramref name="instance" /> is null and <paramref name="method" /> represents an instance method.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="instance" />.Type is not assignable to the declaring type of the method represented by <paramref name="method" />.-or-The number of elements in <paramref name="arguments" /> does not equal the number of parameters for the method represented by <paramref name="method" />.-or-One or more of the elements of <paramref name="arguments" /> is not assignable to the corresponding parameter for the method represented by <paramref name="method" />.</exception>
+ public static MethodCallExpression Call(Expression instance, MethodInfo method, IEnumerable<Expression> arguments) {
+ ContractUtils.RequiresNotNull(method, "method");
+
+ ReadOnlyCollection<Expression> argList = arguments.ToReadOnly();
+
+ ValidateMethodInfo(method);
+ ValidateStaticOrInstanceMethod(instance, method);
+ ValidateArgumentTypes(method, ExpressionType.Call, ref argList);
+
+ if (instance == null) {
+ return new MethodCallExpressionN(method, argList);
+ } else {
+ return new InstanceMethodCallExpressionN(method, instance, argList);
+ }
+ }
+
+ private static ParameterInfo[] ValidateMethodAndGetParameters(Expression instance, MethodInfo method) {
+ ValidateMethodInfo(method);
+ ValidateStaticOrInstanceMethod(instance, method);
+
+ return GetParametersForValidation(method, ExpressionType.Call);
+ }
+
+ private static void ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method) {
+ if (method.IsStatic) {
+ ContractUtils.Requires(instance == null, "instance", Strings.OnlyStaticMethodsHaveNullInstance);
+ } else {
+ ContractUtils.Requires(instance != null, "method", Strings.OnlyStaticMethodsHaveNullInstance);
+ RequiresCanRead(instance, "instance");
+ ValidateCallInstanceType(instance.Type, method);
+ }
+ }
+
+ private static void ValidateCallInstanceType(Type instanceType, MethodInfo method) {
+ if (!TypeUtils.IsValidInstanceType(method, instanceType)) {
+ throw Error.InstanceAndMethodTypeMismatch(method, method.DeclaringType, instanceType);
+ }
+ }
+
+ private static void ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection<Expression> arguments) {
+ Debug.Assert(nodeKind == ExpressionType.Invoke || nodeKind == ExpressionType.Call || nodeKind == ExpressionType.Dynamic || nodeKind == ExpressionType.New);
+
+ ParameterInfo[] pis = GetParametersForValidation(method, nodeKind);
+
+ ValidateArgumentCount(method, nodeKind, arguments.Count, pis);
+
+ Expression[] newArgs = null;
+ for (int i = 0, n = pis.Length; i < n; i++) {
+ Expression arg = arguments[i];
+ ParameterInfo pi = pis[i];
+ arg = ValidateOneArgument(method, nodeKind, arg, pi);
+
+ if (newArgs == null && arg != arguments[i]) {
+ newArgs = new Expression[arguments.Count];
+ for (int j = 0; j < i; j++) {
+ newArgs[j] = arguments[j];
+ }
+ }
+ if (newArgs != null) {
+ newArgs[i] = arg;
+ }
+ }
+ if (newArgs != null) {
+ arguments = new TrueReadOnlyCollection<Expression>(newArgs);
+ }
+ }
+
+ private static ParameterInfo[] GetParametersForValidation(MethodBase method, ExpressionType nodeKind) {
+ ParameterInfo[] pis = method.GetParametersCached();
+
+ if (nodeKind == ExpressionType.Dynamic) {
+ pis = pis.RemoveFirst(); // ignore CallSite argument
+ }
+ return pis;
+ }
+
+ private static void ValidateArgumentCount(MethodBase method, ExpressionType nodeKind, int count, ParameterInfo[] pis) {
+ if (pis.Length != count) {
+ // Throw the right error for the node we were given
+ switch (nodeKind) {
+ case ExpressionType.New:
+ throw Error.IncorrectNumberOfConstructorArguments();
+ case ExpressionType.Invoke:
+ throw Error.IncorrectNumberOfLambdaArguments();
+ case ExpressionType.Dynamic:
+ case ExpressionType.Call:
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ default:
+ throw ContractUtils.Unreachable;
+ }
+ }
+ }
+
+ private static Expression ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi) {
+ RequiresCanRead(arg, "arguments");
+ Type pType = pi.ParameterType;
+ if (pType.IsByRef) {
+ pType = pType.GetElementType();
+ }
+ TypeUtils.ValidateType(pType);
+ if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) {
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType())) {
+ arg = Expression.Quote(arg);
+ } else {
+ // Throw the right error for the node we were given
+ switch (nodeKind) {
+ case ExpressionType.New:
+ throw Error.ExpressionTypeDoesNotMatchConstructorParameter(arg.Type, pType);
+ case ExpressionType.Invoke:
+ throw Error.ExpressionTypeDoesNotMatchParameter(arg.Type, pType);
+ case ExpressionType.Dynamic:
+ case ExpressionType.Call:
+ throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method);
+ default:
+ throw ContractUtils.Unreachable;
+ }
+ }
+ }
+ return arg;
+ }
+
+ private static MethodInfo FindMethod(Type type, string methodName, Type[] typeArgs, Expression[] args, BindingFlags flags) {
+ MemberInfo[] members = type.FindMembers(MemberTypes.Method, flags, Type.FilterNameIgnoreCase, methodName);
+ if (members == null || members.Length == 0)
+ throw Error.MethodDoesNotExistOnType(methodName, type);
+
+ MethodInfo method;
+
+ var methodInfos = members.Map(t => (MethodInfo)t);
+ int count = FindBestMethod(methodInfos, typeArgs, args, out method);
+
+ if (count == 0) {
+ if (typeArgs != null && typeArgs.Length > 0) {
+ throw Error.GenericMethodWithArgsDoesNotExistOnType(methodName, type);
+ } else {
+ throw Error.MethodWithArgsDoesNotExistOnType(methodName, type);
+ }
+ }
+ if (count > 1)
+ throw Error.MethodWithMoreThanOneMatch(methodName, type);
+ return method;
+ }
+
+ private static int FindBestMethod(IEnumerable<MethodInfo> methods, Type[] typeArgs, Expression[] args, out MethodInfo method) {
+ int count = 0;
+ method = null;
+ foreach (MethodInfo mi in methods) {
+ MethodInfo moo = ApplyTypeArgs(mi, typeArgs);
+ if (moo != null && IsCompatible(moo, args)) {
+ // favor public over non-public methods
+ if (method == null || (!method.IsPublic && moo.IsPublic)) {
+ method = moo;
+ count = 1;
+ }
+ // only count it as additional method if they both public or both non-public
+ else if (method.IsPublic == moo.IsPublic) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
+ private static bool IsCompatible(MethodBase m, Expression[] args) {
+ ParameterInfo[] parms = m.GetParametersCached();
+ if (parms.Length != args.Length)
+ return false;
+ for (int i = 0; i < args.Length; i++) {
+ Expression arg = args[i];
+ ContractUtils.RequiresNotNull(arg, "argument");
+ Type argType = arg.Type;
+ Type pType = parms[i].ParameterType;
+ if (pType.IsByRef) {
+ pType = pType.GetElementType();
+ }
+ if (!TypeUtils.AreReferenceAssignable(pType, argType) &&
+ !(TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static MethodInfo ApplyTypeArgs(MethodInfo m, Type[] typeArgs) {
+ if (typeArgs == null || typeArgs.Length == 0) {
+ if (!m.IsGenericMethodDefinition)
+ return m;
+ } else {
+ if (m.IsGenericMethodDefinition && m.GetGenericArguments().Length == typeArgs.Length)
+ return m.MakeGenericMethod(typeArgs);
+ }
+ return null;
+ }
+
+
+ #endregion
+
+ #region ArrayIndex
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents applying an array index operator to a multi-dimensional array.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.BinaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ArrayIndex" /> and the <see cref="P:Microsoft.Linq.Expressions.BinaryExpression.Left" /> and <see cref="P:Microsoft.Linq.Expressions.BinaryExpression.Right" /> properties set to the specified values.</returns>
+ ///<param name="array">An array of <see cref="T:Microsoft.Linq.Expressions.Expression" /> instances - indexes for the array index operation.</param>
+ ///<param name="indexes">An array that contains <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> collection.</param>
+ public static MethodCallExpression ArrayIndex(Expression array, params Expression[] indexes) {
+ return ArrayIndex(array, (IEnumerable<Expression>)indexes);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that represents applying an array index operator to an array of rank more than one.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.MethodCallExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Call" /> and the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> and <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> properties set to the specified values.</returns>
+ ///<param name="array">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Object" /> property equal to.</param>
+ ///<param name="indexes">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:Microsoft.Linq.Expressions.Expression" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.MethodCallExpression.Arguments" /> collection.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="array" /> or <paramref name="indexes" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="array" />.Type does not represent an array type.-or-The rank of <paramref name="array" />.Type does not match the number of elements in <paramref name="indexes" />.-or-The <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property of one or more elements of <paramref name="indexes" /> does not represent the <see cref="T:System.Int32" /> type.</exception>
+ public static MethodCallExpression ArrayIndex(Expression array, IEnumerable<Expression> indexes) {
+ RequiresCanRead(array, "array");
+ ContractUtils.RequiresNotNull(indexes, "indexes");
+
+ Type arrayType = array.Type;
+ if (!arrayType.IsArray) {
+ throw Error.ArgumentMustBeArray();
+ }
+
+ ReadOnlyCollection<Expression> indexList = indexes.ToReadOnly();
+ if (arrayType.GetArrayRank() != indexList.Count) {
+ throw Error.IncorrectNumberOfIndexes();
+ }
+
+ foreach (Expression e in indexList) {
+ RequiresCanRead(e, "indexes");
+ if (e.Type != typeof(int)) {
+ throw Error.ArgumentMustBeArrayIndexType();
+ }
+ }
+
+ MethodInfo mi = array.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance);
+ return Call(array, mi, indexList);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewArrayExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewArrayExpression.cs
new file mode 100644
index 00000000000..abf7394cca3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewArrayExpression.cs
@@ -0,0 +1,227 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents creating a new array and possibly initializing the elements of the new array.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.NewArrayExpressionProxy))]
+#endif
+ public class NewArrayExpression : Expression {
+ private readonly ReadOnlyCollection<Expression> _expressions;
+ private readonly Type _type;
+
+ internal NewArrayExpression(Type type, ReadOnlyCollection<Expression> expressions) {
+ _expressions = expressions;
+ _type = type;
+ }
+
+ internal static NewArrayExpression Make(ExpressionType nodeType, Type type, ReadOnlyCollection<Expression> expressions) {
+ if (nodeType == ExpressionType.NewArrayInit) {
+ return new NewArrayInitExpression(type, expressions);
+ } else {
+ return new NewArrayBoundsExpression(type, expressions);
+ }
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Gets the bounds of the array if the value of the <see cref="P:NodeType"/> property is NewArrayBounds, or the values to initialize the elements of the new array if the value of the <see cref="P:NodeType"/> property is NewArrayInit.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Expressions {
+ get { return _expressions; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitNewArray(this);
+ }
+ }
+
+ internal sealed class NewArrayInitExpression : NewArrayExpression {
+ internal NewArrayInitExpression(Type type, ReadOnlyCollection<Expression> expressions)
+ : base(type, expressions) {
+ }
+
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.NewArrayInit; }
+ }
+ }
+
+ internal sealed class NewArrayBoundsExpression : NewArrayExpression {
+ internal NewArrayBoundsExpression(Type type, ReadOnlyCollection<Expression> expressions)
+ : base(type, expressions) {
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.NewArrayBounds; }
+ }
+ }
+
+ public partial class Expression {
+
+ #region NewArrayInit
+
+
+ /// <summary>
+ /// Creates a new array expression of the specified type from the provided initializers.
+ /// </summary>
+ /// <param name="type">A Type that represents the element type of the array.</param>
+ /// <param name="initializers">The expressions used to create the array elements.</param>
+ /// <returns>An instance of the <see cref="NewArrayExpression"/>.</returns>
+ public static NewArrayExpression NewArrayInit(Type type, params Expression[] initializers) {
+ return NewArrayInit(type, (IEnumerable<Expression>)initializers);
+ }
+
+ /// <summary>
+ /// Creates a new array expression of the specified type from the provided initializers.
+ /// </summary>
+ /// <param name="type">A Type that represents the element type of the array.</param>
+ /// <param name="initializers">The expressions used to create the array elements.</param>
+ /// <returns>An instance of the <see cref="NewArrayExpression"/>.</returns>
+ public static NewArrayExpression NewArrayInit(Type type, IEnumerable<Expression> initializers) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(initializers, "initializers");
+ if (type.Equals(typeof(void))) {
+ throw Error.ArgumentCannotBeOfTypeVoid();
+ }
+
+ ReadOnlyCollection<Expression> initializerList = initializers.ToReadOnly();
+
+ Expression[] newList = null;
+ for (int i = 0, n = initializerList.Count; i < n; i++) {
+ Expression expr = initializerList[i];
+ RequiresCanRead(expr, "initializers");
+
+ if (!TypeUtils.AreReferenceAssignable(type, expr.Type)) {
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), type) && type.IsAssignableFrom(expr.GetType())) {
+ expr = Expression.Quote(expr);
+ } else {
+ throw Error.ExpressionTypeCannotInitializeArrayType(expr.Type, type);
+ }
+ if (newList == null) {
+ newList = new Expression[initializerList.Count];
+ for (int j = 0; j < i; j++) {
+ newList[j] = initializerList[j];
+ }
+ }
+ }
+ if (newList != null) {
+ newList[i] = expr;
+ }
+ }
+ if (newList != null) {
+ initializerList = new TrueReadOnlyCollection<Expression>(newList);
+ }
+
+ return NewArrayExpression.Make(ExpressionType.NewArrayInit, type.MakeArrayType(), initializerList);
+ }
+
+ #endregion
+
+ #region NewArrayBounds
+
+
+ /// <summary>
+ /// Creates a <see cref="NewArrayExpression"/> that represents creating an array that has a specified rank.
+ /// </summary>
+ /// <param name="type">A <see cref="Type"/> that represents the element type of the array.</param>
+ /// <param name="bounds">An array that contains Expression objects to use to populate the Expressions collection.</param>
+ /// <returns>A <see cref="NewArrayExpression"/> that has the <see cref="P:NodeType"/> property equal to type and the <see cref="P:Expressions"/> property set to the specified value.</returns>
+ public static NewArrayExpression NewArrayBounds(Type type, params Expression[] bounds) {
+ return NewArrayBounds(type, (IEnumerable<Expression>)bounds);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="NewArrayExpression"/> that represents creating an array that has a specified rank.
+ /// </summary>
+ /// <param name="type">A <see cref="Type"/> that represents the element type of the array.</param>
+ /// <param name="bounds">An IEnumerable{T} that contains Expression objects to use to populate the Expressions collection.</param>
+ /// <returns>A <see cref="NewArrayExpression"/> that has the <see cref="P:NodeType"/> property equal to type and the <see cref="P:Expressions"/> property set to the specified value.</returns>
+ public static NewArrayExpression NewArrayBounds(Type type, IEnumerable<Expression> bounds) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(bounds, "bounds");
+
+ if (type.Equals(typeof(void))) {
+ throw Error.ArgumentCannotBeOfTypeVoid();
+ }
+
+ ReadOnlyCollection<Expression> boundsList = bounds.ToReadOnly();
+
+ int dimensions = boundsList.Count;
+ ContractUtils.Requires(dimensions > 0, "bounds", Strings.BoundsCannotBeLessThanOne);
+
+ for (int i = 0; i < dimensions; i++) {
+ Expression expr = boundsList[i];
+ RequiresCanRead(expr, "bounds");
+ if (!TypeUtils.IsInteger(expr.Type)) {
+ throw Error.ArgumentMustBeInteger();
+ }
+ }
+
+ Type arrayType;
+ if (dimensions == 1) {
+ //To get a vector, need call Type.MakeArrayType().
+ //Type.MakeArrayType(1) gives a non-vector array, which will cause type check error.
+ arrayType = type.MakeArrayType();
+ } else {
+ arrayType = type.MakeArrayType(dimensions);
+ }
+
+ return NewArrayExpression.Make(ExpressionType.NewArrayBounds, arrayType, bounds.ToReadOnly());
+ }
+
+ #endregion
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs
new file mode 100644
index 00000000000..a9e607ce966
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/NewExpression.cs
@@ -0,0 +1,321 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents a constructor call.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.NewExpressionProxy))]
+#endif
+ public class NewExpression : Expression, IArgumentProvider {
+ private readonly ConstructorInfo _constructor;
+ private IList<Expression> _arguments;
+ private readonly ReadOnlyCollection<MemberInfo> _members;
+
+ internal NewExpression(ConstructorInfo constructor, IList<Expression> arguments, ReadOnlyCollection<MemberInfo> members) {
+ _constructor = constructor;
+ _arguments = arguments;
+ _members = members;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public override Type Type {
+ get { return _constructor.DeclaringType; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.New; }
+ }
+
+ /// <summary>
+ /// Gets the called constructor.
+ /// </summary>
+ public ConstructorInfo Constructor {
+ get { return _constructor; }
+ }
+
+ /// <summary>
+ /// Gets the arguments to the constructor.
+ /// </summary>
+ public ReadOnlyCollection<Expression> Arguments {
+ get { return ReturnReadOnly(ref _arguments); }
+ }
+
+ Expression IArgumentProvider.GetArgument(int index) {
+ return _arguments[index];
+ }
+
+ int IArgumentProvider.ArgumentCount {
+ get {
+ return _arguments.Count;
+ }
+ }
+
+ /// <summary>
+ /// Gets the members that can retrieve the values of the fields that were initialized with constructor arguments.
+ /// </summary>
+ public ReadOnlyCollection<MemberInfo> Members {
+ get { return _members; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitNew(this);
+ }
+ }
+
+ internal class NewValueTypeExpression : NewExpression {
+ private readonly Type _valueType;
+
+ internal NewValueTypeExpression(Type type, ReadOnlyCollection<Expression> arguments, ReadOnlyCollection<MemberInfo> members)
+ : base(null, arguments, members) {
+ _valueType = type;
+ }
+
+ public sealed override Type Type {
+ get { return _valueType; }
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a new <see cref="NewExpression"/> that represents calling the specified constructor that takes no arguments.
+ /// </summary>
+ /// <param name="constructor">The <see cref="ConstructorInfo"/> to set the <see cref="P:Constructor"/> property equal to.</param>
+ /// <returns>A <see cref="NewExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="P:New"/> and the <see cref="P:Constructor"/> property set to the specified value.</returns>
+ public static NewExpression New(ConstructorInfo constructor) {
+ return New(constructor, (IEnumerable<Expression>)null);
+ }
+
+
+ /// <summary>
+ /// Creates a new <see cref="NewExpression"/> that represents calling the specified constructor that takes no arguments.
+ /// </summary>
+ /// <param name="constructor">The <see cref="ConstructorInfo"/> to set the <see cref="P:Constructor"/> property equal to.</param>
+ /// <param name="arguments">An array of <see cref="Expression"/> objects to use to populate the Arguments collection.</param>
+ /// <returns>A <see cref="NewExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="P:New"/> and the <see cref="P:Constructor"/> and <see cref="P:Arguments"/> properties set to the specified value.</returns>
+ public static NewExpression New(ConstructorInfo constructor, params Expression[] arguments) {
+ return New(constructor, (IEnumerable<Expression>)arguments);
+ }
+
+
+ /// <summary>
+ /// Creates a new <see cref="NewExpression"/> that represents calling the specified constructor that takes no arguments.
+ /// </summary>
+ /// <param name="constructor">The <see cref="ConstructorInfo"/> to set the <see cref="P:Constructor"/> property equal to.</param>
+ /// <param name="arguments">An <see cref="IEnumerable{T}"/> of <see cref="Expression"/> objects to use to populate the Arguments collection.</param>
+ /// <returns>A <see cref="NewExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="P:New"/> and the <see cref="P:Constructor"/> and <see cref="P:Arguments"/> properties set to the specified value.</returns>
+ public static NewExpression New(ConstructorInfo constructor, IEnumerable<Expression> arguments) {
+ ContractUtils.RequiresNotNull(constructor, "constructor");
+ ContractUtils.RequiresNotNull(constructor.DeclaringType, "constructor.DeclaringType");
+ TypeUtils.ValidateType(constructor.DeclaringType);
+ var argList = arguments.ToReadOnly();
+ ValidateArgumentTypes(constructor, ExpressionType.New, ref argList);
+
+ return new NewExpression(constructor, argList, null);
+ }
+
+
+ /// <summary>
+ /// Creates a new <see cref="NewExpression"/> that represents calling the specified constructor with the specified arguments. The members that access the constructor initialized fields are specified.
+ /// </summary>
+ /// <param name="constructor">The <see cref="ConstructorInfo"/> to set the <see cref="P:Constructor"/> property equal to.</param>
+ /// <param name="arguments">An <see cref="IEnumerable{T}"/> of <see cref="Expression"/> objects to use to populate the Arguments collection.</param>
+ /// <param name="members">An <see cref="IEnumerable{T}"/> of <see cref="MemberInfo"/> objects to use to populate the Members collection.</param>
+ /// <returns>A <see cref="NewExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="P:New"/> and the <see cref="P:Constructor"/>, <see cref="P:Arguments"/> and <see cref="P:Members"/> properties set to the specified value.</returns>
+ public static NewExpression New(ConstructorInfo constructor, IEnumerable<Expression> arguments, IEnumerable<MemberInfo> members) {
+ ContractUtils.RequiresNotNull(constructor, "constructor");
+ var memberList = members.ToReadOnly();
+ var argList = arguments.ToReadOnly();
+ ValidateNewArgs(constructor, ref argList, ref memberList);
+ return new NewExpression(constructor, argList, memberList);
+ }
+
+
+ /// <summary>
+ /// Creates a new <see cref="NewExpression"/> that represents calling the specified constructor with the specified arguments. The members that access the constructor initialized fields are specified.
+ /// </summary>
+ /// <param name="constructor">The <see cref="ConstructorInfo"/> to set the <see cref="P:Constructor"/> property equal to.</param>
+ /// <param name="arguments">An <see cref="IEnumerable{T}"/> of <see cref="Expression"/> objects to use to populate the Arguments collection.</param>
+ /// <param name="members">An Array of <see cref="MemberInfo"/> objects to use to populate the Members collection.</param>
+ /// <returns>A <see cref="NewExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="P:New"/> and the <see cref="P:Constructor"/>, <see cref="P:Arguments"/> and <see cref="P:Members"/> properties set to the specified value.</returns>
+ public static NewExpression New(ConstructorInfo constructor, IEnumerable<Expression> arguments, params MemberInfo[] members) {
+ return New(constructor, arguments, (IEnumerable<MemberInfo>)members);
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="NewExpression"/> that represents calling the parameterless constructor of the specified type.
+ /// </summary>
+ /// <param name="type">A <see cref="Type"/> that has a constructor that takes no arguments. </param>
+ /// <returns>A <see cref="NewExpression"/> that has the <see cref="NodeType"/> property equal to New and the Constructor property set to the ConstructorInfo that represents the parameterless constructor of the specified type.</returns>
+ public static NewExpression New(Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+ if (type == typeof(void)) {
+ throw Error.ArgumentCannotBeOfTypeVoid();
+ }
+ ConstructorInfo ci = null;
+ if (!type.IsValueType) {
+ ci = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, System.Type.EmptyTypes, null);
+ if (ci == null) {
+ throw Error.TypeMissingDefaultConstructor(type);
+ }
+ return New(ci);
+ }
+ return new NewValueTypeExpression(type, EmptyReadOnlyCollection<Expression>.Instance, null);
+ }
+
+
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static void ValidateNewArgs(ConstructorInfo constructor, ref ReadOnlyCollection<Expression> arguments, ref ReadOnlyCollection<MemberInfo> members) {
+ ParameterInfo[] pis;
+ if ((pis = constructor.GetParametersCached()).Length > 0) {
+ if (arguments.Count != pis.Length) {
+ throw Error.IncorrectNumberOfConstructorArguments();
+ }
+ if (arguments.Count != members.Count) {
+ throw Error.IncorrectNumberOfArgumentsForMembers();
+ }
+ Expression[] newArguments = null;
+ MemberInfo[] newMembers = null;
+ for (int i = 0, n = arguments.Count; i < n; i++) {
+ Expression arg = arguments[i];
+ RequiresCanRead(arg, "argument");
+ MemberInfo member = members[i];
+ ContractUtils.RequiresNotNull(member, "member");
+ if (!TypeUtils.AreEquivalent(member.DeclaringType, constructor.DeclaringType)) {
+ throw Error.ArgumentMemberNotDeclOnType(member.Name, constructor.DeclaringType.Name);
+ }
+ Type memberType;
+ ValidateAnonymousTypeMember(ref member, out memberType);
+ if (!TypeUtils.AreReferenceAssignable(memberType, arg.Type)) {
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), memberType) && memberType.IsAssignableFrom(arg.GetType())) {
+ arg = Expression.Quote(arg);
+ } else {
+ throw Error.ArgumentTypeDoesNotMatchMember(arg.Type, memberType);
+ }
+ }
+ ParameterInfo pi = pis[i];
+ Type pType = pi.ParameterType;
+ if (pType.IsByRef) {
+ pType = pType.GetElementType();
+ }
+ if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) {
+ if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.Type)) {
+ arg = Expression.Quote(arg);
+ } else {
+ throw Error.ExpressionTypeDoesNotMatchConstructorParameter(arg.Type, pType);
+ }
+ }
+ if (newArguments == null && arg != arguments[i]) {
+ newArguments = new Expression[arguments.Count];
+ for (int j = 0; j < i; j++) {
+ newArguments[j] = arguments[j];
+ }
+ }
+ if (newArguments != null) {
+ newArguments[i] = arg;
+ }
+
+ if (newMembers == null && member != members[i]) {
+ newMembers = new MemberInfo[members.Count];
+ for (int j = 0; j < i; j++) {
+ newMembers[j] = members[j];
+ }
+ }
+ if (newMembers != null) {
+ newMembers[i] = member;
+ }
+ }
+ if (newArguments != null) {
+ arguments = new TrueReadOnlyCollection<Expression>(newArguments);
+ }
+ if (newMembers != null) {
+ members = new TrueReadOnlyCollection<MemberInfo>(newMembers);
+ }
+ } else if (arguments != null && arguments.Count > 0) {
+ throw Error.IncorrectNumberOfConstructorArguments();
+ } else if (members != null && members.Count > 0) {
+ throw Error.IncorrectNumberOfMembersForGivenConstructor();
+ }
+ }
+
+
+ private static void ValidateAnonymousTypeMember(ref MemberInfo member, out Type memberType) {
+ switch (member.MemberType) {
+ case MemberTypes.Field:
+ FieldInfo field = member as FieldInfo;
+ if (field.IsStatic) {
+ throw Error.ArgumentMustBeInstanceMember();
+ }
+ memberType = field.FieldType;
+ break;
+ case MemberTypes.Property:
+ PropertyInfo pi = member as PropertyInfo;
+ if (!pi.CanRead) {
+ throw Error.PropertyDoesNotHaveGetter(pi);
+ }
+ if (pi.GetGetMethod().IsStatic) {
+ throw Error.ArgumentMustBeInstanceMember();
+ }
+ memberType = pi.PropertyType;
+ break;
+ case MemberTypes.Method:
+ MethodInfo method = member as MethodInfo;
+ if (method.IsStatic) {
+ throw Error.ArgumentMustBeInstanceMember();
+ }
+
+ PropertyInfo prop = GetProperty(method);
+ member = prop;
+ memberType = prop.PropertyType;
+ break;
+ default:
+ throw Error.ArgumentMustBeFieldInfoOrPropertInfoOrMethod();
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ParameterExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ParameterExpression.cs
new file mode 100644
index 00000000000..7ab0ce553d3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/ParameterExpression.cs
@@ -0,0 +1,226 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents a named parameter expression.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.ParameterExpressionProxy))]
+#endif
+ public class ParameterExpression : Expression {
+ private readonly string _name;
+
+ internal ParameterExpression(string name) {
+ _name = name;
+ }
+
+ internal static ParameterExpression Make(Type type, string name, bool isByRef) {
+ if (isByRef) {
+ return new ByRefParameterExpression(type, name);
+ } else {
+ if (!type.IsEnum) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Boolean: return new PrimitiveParameterExpression<Boolean>(name);
+ case TypeCode.Byte: return new PrimitiveParameterExpression<Byte>(name);
+ case TypeCode.Char: return new PrimitiveParameterExpression<Char>(name);
+ case TypeCode.DateTime: return new PrimitiveParameterExpression<DateTime>(name);
+ case TypeCode.DBNull: return new PrimitiveParameterExpression<DBNull>(name);
+ case TypeCode.Decimal: return new PrimitiveParameterExpression<Decimal>(name);
+ case TypeCode.Double: return new PrimitiveParameterExpression<Double>(name);
+ case TypeCode.Int16: return new PrimitiveParameterExpression<Int16>(name);
+ case TypeCode.Int32: return new PrimitiveParameterExpression<Int32>(name);
+ case TypeCode.Int64: return new PrimitiveParameterExpression<Int64>(name);
+ case TypeCode.Object:
+ // common reference types which we optimize go here. Of course object is in
+ // the list, the others are driven by profiling of various workloads. This list
+ // should be kept short.
+ if (type == typeof(object)) {
+ return new ParameterExpression(name);
+ } else if (type == typeof(Exception)) {
+ return new PrimitiveParameterExpression<Exception>(name);
+ } else if (type == typeof(object[])) {
+ return new PrimitiveParameterExpression<object[]>(name);
+ }
+ break;
+ case TypeCode.SByte: return new PrimitiveParameterExpression<SByte>(name);
+ case TypeCode.Single: return new PrimitiveParameterExpression<Single>(name);
+ case TypeCode.String: return new PrimitiveParameterExpression<String>(name);
+ case TypeCode.UInt16: return new PrimitiveParameterExpression<UInt16>(name);
+ case TypeCode.UInt32: return new PrimitiveParameterExpression<UInt32>(name);
+ case TypeCode.UInt64: return new PrimitiveParameterExpression<UInt64>(name);
+ }
+ }
+ }
+
+ return new TypedParameterExpression(type, name);
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public override Type Type {
+ get { return typeof(object); }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Parameter; }
+ }
+
+ /// <summary>
+ /// The Name of the parameter or variable.
+ /// </summary>
+ public string Name {
+ get { return _name; }
+ }
+
+ /// <summary>
+ /// Indicates that this ParameterExpression is to be treated as a ByRef parameter.
+ /// </summary>
+ public bool IsByRef {
+ get {
+ return GetIsByRef();
+ }
+ }
+
+ internal virtual bool GetIsByRef() {
+ return false;
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitParameter(this);
+ }
+ }
+
+ /// <summary>
+ /// Specialized subclass to avoid holding onto the byref flag in a
+ /// parameter expression. This version always holds onto the expression
+ /// type explicitly and therefore derives from TypedParameterExpression.
+ /// </summary>
+ internal sealed class ByRefParameterExpression : TypedParameterExpression {
+ internal ByRefParameterExpression(Type type, string name)
+ : base(type, name) {
+ }
+
+ internal override bool GetIsByRef() {
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Specialized subclass which holds onto the type of the expression for
+ /// uncommon types.
+ /// </summary>
+ internal class TypedParameterExpression : ParameterExpression {
+ private readonly Type _paramType;
+
+ internal TypedParameterExpression(Type type, string name)
+ : base(name) {
+ _paramType = type;
+ }
+
+ public sealed override Type Type {
+ get { return _paramType; }
+ }
+ }
+
+ /// <summary>
+ /// Generic type to avoid needing explicit storage for primitive data types
+ /// which are commonly used.
+ /// </summary>
+ internal sealed class PrimitiveParameterExpression<T> : ParameterExpression {
+ internal PrimitiveParameterExpression(string name)
+ : base(name) {
+ }
+
+ public sealed override Type Type {
+ get { return typeof(T); }
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
+ /// </summary>
+ /// <param name="type">The type of the parameter or variable.</param>
+ /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
+ public static ParameterExpression Parameter(Type type) {
+ return Parameter(type, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
+ /// </summary>
+ /// <param name="type">The type of the parameter or variable.</param>
+ /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
+ public static ParameterExpression Variable(Type type) {
+ return Variable(type, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
+ /// </summary>
+ /// <param name="type">The type of the parameter or variable.</param>
+ /// <param name="name">The name of the parameter or variable, used for debugging or pretty printing purpose only.</param>
+ /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
+ public static ParameterExpression Parameter(Type type, string name) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (type == typeof(void)) {
+ throw Error.ArgumentCannotBeOfTypeVoid();
+ }
+
+ bool byref = type.IsByRef;
+ if (byref) {
+ type = type.GetElementType();
+ }
+
+ return ParameterExpression.Make(type, name, byref);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ParameterExpression" /> node that can be used to identify a parameter or a variable in an expression tree.
+ /// </summary>
+ /// <param name="type">The type of the parameter or variable.</param>
+ /// <param name="name">The name of the parameter or variable, used for debugging or pretty printing purpose only.</param>
+ /// <returns>A <see cref="ParameterExpression" /> node with the specified name and type.</returns>
+ public static ParameterExpression Variable(Type type, string name) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.Requires(type != typeof(void), "type", Strings.ArgumentCannotBeOfTypeVoid);
+ ContractUtils.Requires(!type.IsByRef, "type", Strings.TypeMustNotBeByRef);
+ return ParameterExpression.Make(type, name, false);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/RuntimeVariablesExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/RuntimeVariablesExpression.cs
new file mode 100644
index 00000000000..9a2af5f8765
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/RuntimeVariablesExpression.cs
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// An expression that provides runtime read/write access to variables.
+ /// Needed to implement "eval" in some dynamic languages.
+ /// Evaluates to an instance of <see cref="IList{IStrongBox}" /> when executed.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.RuntimeVariablesExpressionProxy))]
+#endif
+ public sealed class RuntimeVariablesExpression : Expression {
+ private readonly ReadOnlyCollection<ParameterExpression> _variables;
+
+ internal RuntimeVariablesExpression(ReadOnlyCollection<ParameterExpression> variables) {
+ _variables = variables;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return typeof(IRuntimeVariables); }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.RuntimeVariables; }
+ }
+
+ /// <summary>
+ /// The variables or parameters to which to provide runtime access.
+ /// </summary>
+ public ReadOnlyCollection<ParameterExpression> Variables {
+ get { return _variables; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitRuntimeVariables(this);
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates an instance of <see cref="T:Microsoft.Linq.Expressions.RuntimeVariablesExpression" />.
+ /// </summary>
+ /// <param name="variables">An array of <see cref="T:Microsoft.Linq.Expressions.ParameterExpression" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.RuntimeVariablesExpression.Variables" /> collection.</param>
+ /// <returns>An instance of <see cref="T:Microsoft.Linq.Expressions.RuntimeVariablesExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.RuntimeVariables" /> and the <see cref="P:Microsoft.Linq.Expressions.RuntimeVariablesExpression.Variables" /> property set to the specified value.</returns>
+ public static RuntimeVariablesExpression RuntimeVariables(params ParameterExpression[] variables) {
+ return RuntimeVariables((IEnumerable<ParameterExpression>)variables);
+ }
+
+ /// <summary>
+ /// Creates an instance of <see cref="T:Microsoft.Linq.Expressions.RuntimeVariablesExpression" />.
+ /// </summary>
+ /// <param name="variables">A collection of <see cref="T:Microsoft.Linq.Expressions.ParameterExpression" /> objects to use to populate the <see cref="P:Microsoft.Linq.Expressions.RuntimeVariablesExpression.Variables" /> collection.</param>
+ /// <returns>An instance of <see cref="T:Microsoft.Linq.Expressions.RuntimeVariablesExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.RuntimeVariables" /> and the <see cref="P:Microsoft.Linq.Expressions.RuntimeVariablesExpression.Variables" /> property set to the specified value.</returns>
+ public static RuntimeVariablesExpression RuntimeVariables(IEnumerable<ParameterExpression> variables) {
+ ContractUtils.RequiresNotNull(variables, "variables");
+
+ var vars = variables.ToReadOnly();
+ for (int i = 0; i < vars.Count; i++) {
+ Expression v = vars[i];
+ if (v == null) {
+ throw new ArgumentNullException("variables[" + i + "]");
+ }
+ }
+
+ return new RuntimeVariablesExpression(vars);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchCase.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchCase.cs
new file mode 100644
index 00000000000..e40bc23895f
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchCase.cs
@@ -0,0 +1,97 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents one case of a <see cref="SwitchExpression"/>.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.SwitchCaseProxy))]
+#endif
+ public sealed class SwitchCase {
+ private readonly ReadOnlyCollection<Expression> _testValues;
+ private readonly Expression _body;
+
+ internal SwitchCase(Expression body, ReadOnlyCollection<Expression> testValues) {
+ _body = body;
+ _testValues = testValues;
+ }
+
+ /// <summary>
+ /// Gets the values of this case. This case is selected for execution when the <see cref="SwitchExpression.SwitchValue"/> matches any of these values.
+ /// </summary>
+ public ReadOnlyCollection<Expression> TestValues {
+ get { return _testValues; }
+ }
+
+ /// <summary>
+ /// Gets the body of this case.
+ /// </summary>
+ public Expression Body {
+ get { return _body; }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="String"/> that represents the current <see cref="Object"/>.
+ /// </summary>
+ /// <returns>A <see cref="String"/> that represents the current <see cref="Object"/>. </returns>
+ public override string ToString() {
+ return ExpressionStringBuilder.SwitchCaseToString(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="Microsoft.Linq.Expressions.SwitchCase">SwitchCase</see> for use in a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="body">The body of the case.</param>
+ /// <param name="testValues">The test values of the case.</param>
+ /// <returns>The created <see cref="Microsoft.Linq.Expressions.SwitchCase">SwitchCase</see>.</returns>
+ public static SwitchCase SwitchCase(Expression body, params Expression[] testValues) {
+ return SwitchCase(body, (IEnumerable<Expression>)testValues);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="Microsoft.Linq.Expressions.SwitchCase">SwitchCase</see> for use in a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="body">The body of the case.</param>
+ /// <param name="testValues">The test values of the case.</param>
+ /// <returns>The created <see cref="Microsoft.Linq.Expressions.SwitchCase">SwitchCase</see>.</returns>
+ public static SwitchCase SwitchCase(Expression body, IEnumerable<Expression> testValues) {
+ RequiresCanRead(body, "body");
+
+ var values = testValues.ToReadOnly();
+ RequiresCanRead(values, "testValues");
+ ContractUtils.RequiresNotEmpty(values, "testValues");
+
+ return new SwitchCase(body, values);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchExpression.cs
new file mode 100644
index 00000000000..bbf4c68265c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SwitchExpression.cs
@@ -0,0 +1,286 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a control expression that handles multiple selections by passing control to a <see cref="SwitchCase"/>.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.SwitchExpressionProxy))]
+#endif
+ public sealed class SwitchExpression : Expression {
+ private readonly Type _type;
+ private readonly Expression _switchValue;
+ private readonly ReadOnlyCollection<SwitchCase> _cases;
+ private readonly Expression _defaultBody;
+ private readonly MethodInfo _comparison;
+
+ internal SwitchExpression(Type type, Expression switchValue, Expression defaultBody, MethodInfo comparison, ReadOnlyCollection<SwitchCase> cases) {
+ _type = type;
+ _switchValue = switchValue;
+ _defaultBody = defaultBody;
+ _comparison = comparison;
+ _cases = cases;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Switch; }
+ }
+
+ /// <summary>
+ /// Gets the test for the switch.
+ /// </summary>
+ public Expression SwitchValue {
+ get { return _switchValue; }
+ }
+
+ /// <summary>
+ /// Gets the collection of <see cref="SwitchCase"/> objects for the switch.
+ /// </summary>
+ public ReadOnlyCollection<SwitchCase> Cases {
+ get { return _cases; }
+ }
+
+ /// <summary>
+ /// Gets the test for the switch.
+ /// </summary>
+ public Expression DefaultBody {
+ get { return _defaultBody; }
+ }
+
+ /// <summary>
+ /// Gets the equality comparison method, if any.
+ /// </summary>
+ public MethodInfo Comparison {
+ get { return _comparison; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitSwitch(this);
+ }
+
+ internal bool IsLifted {
+ get {
+ if (_switchValue.Type.IsNullableType()) {
+ return (_comparison == null) ||
+ !TypeUtils.AreEquivalent(_switchValue.Type, _comparison.GetParametersCached()[0].ParameterType.GetNonRefType());
+ }
+ return false;
+ }
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="switchValue">The value to be tested against each case.</param>
+ /// <param name="cases">The valid cases for this switch.</param>
+ /// <returns>The created <see cref="SwitchExpression"/>.</returns>
+ public static SwitchExpression Switch(Expression switchValue, params SwitchCase[] cases) {
+ return Switch(switchValue, null, null, (IEnumerable<SwitchCase>)cases);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="switchValue">The value to be tested against each case.</param>
+ /// <param name="defaultBody">The result of the switch if no cases are matched.</param>
+ /// <param name="cases">The valid cases for this switch.</param>
+ /// <returns>The created <see cref="SwitchExpression"/>.</returns>
+ public static SwitchExpression Switch(Expression switchValue, Expression defaultBody, params SwitchCase[] cases) {
+ return Switch(switchValue, defaultBody, null, (IEnumerable<SwitchCase>)cases);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="switchValue">The value to be tested against each case.</param>
+ /// <param name="defaultBody">The result of the switch if no cases are matched.</param>
+ /// <param name="comparison">The equality comparison method to use.</param>
+ /// <param name="cases">The valid cases for this switch.</param>
+ /// <returns>The created <see cref="SwitchExpression"/>.</returns>
+ public static SwitchExpression Switch(Expression switchValue, Expression defaultBody, MethodInfo comparison, params SwitchCase[] cases) {
+ return Switch(switchValue, defaultBody, comparison, (IEnumerable<SwitchCase>)cases);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="type">The result type of the switch.</param>
+ /// <param name="switchValue">The value to be tested against each case.</param>
+ /// <param name="defaultBody">The result of the switch if no cases are matched.</param>
+ /// <param name="comparison">The equality comparison method to use.</param>
+ /// <param name="cases">The valid cases for this switch.</param>
+ /// <returns>The created <see cref="SwitchExpression"/>.</returns>
+ public static SwitchExpression Switch(Type type, Expression switchValue, Expression defaultBody, MethodInfo comparison, params SwitchCase[] cases) {
+ return Switch(type, switchValue, defaultBody, comparison, (IEnumerable<SwitchCase>)cases);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="switchValue">The value to be tested against each case.</param>
+ /// <param name="defaultBody">The result of the switch if no cases are matched.</param>
+ /// <param name="comparison">The equality comparison method to use.</param>
+ /// <param name="cases">The valid cases for this switch.</param>
+ /// <returns>The created <see cref="SwitchExpression"/>.</returns>
+ public static SwitchExpression Switch(Expression switchValue, Expression defaultBody, MethodInfo comparison, IEnumerable<SwitchCase> cases) {
+ return Switch(null, switchValue, defaultBody, comparison, cases);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="SwitchExpression"/>.
+ /// </summary>
+ /// <param name="type">The result type of the switch.</param>
+ /// <param name="switchValue">The value to be tested against each case.</param>
+ /// <param name="defaultBody">The result of the switch if no cases are matched.</param>
+ /// <param name="comparison">The equality comparison method to use.</param>
+ /// <param name="cases">The valid cases for this switch.</param>
+ /// <returns>The created <see cref="SwitchExpression"/>.</returns>
+ public static SwitchExpression Switch(Type type, Expression switchValue, Expression defaultBody, MethodInfo comparison, IEnumerable<SwitchCase> cases) {
+ RequiresCanRead(switchValue, "switchValue");
+ ContractUtils.Requires(switchValue.Type != typeof(void), "switchValue", Strings.ArgumentCannotBeOfTypeVoid);
+
+ var caseList = cases.ToReadOnly();
+ ContractUtils.RequiresNotEmpty(caseList, "cases");
+ ContractUtils.RequiresNotNullItems(caseList, "cases");
+
+ // Type of the result. Either provided, or it is type of the branches.
+ Type resultType = type ?? caseList[0].Body.Type;
+ bool customType = type != null;
+
+ if (comparison != null) {
+ var pms = comparison.GetParametersCached();
+ if (pms.Length != 2) {
+ throw Error.IncorrectNumberOfMethodCallArguments(comparison);
+ }
+ // Validate that the switch value's type matches the comparison method's
+ // left hand side parameter type.
+ var leftParam = pms[0];
+ bool liftedCall = false;
+ if (!ParameterIsAssignable(leftParam, switchValue.Type)) {
+ liftedCall = ParameterIsAssignable(leftParam, switchValue.Type.GetNonNullableType());
+ if (!liftedCall) {
+ throw Error.SwitchValueTypeDoesNotMatchComparisonMethodParameter(switchValue.Type, leftParam.ParameterType);
+ }
+ }
+
+ var rightParam = pms[1];
+ foreach (var c in caseList) {
+ ContractUtils.RequiresNotNull(c, "cases");
+ ValidateSwitchCaseType(c.Body, customType, resultType, "cases");
+ for (int i = 0; i < c.TestValues.Count; i++) {
+ // When a comparison method is provided, test values can have different type but have to
+ // be reference assignable to the right hand side parameter of the method.
+ Type rightOperandType = c.TestValues[i].Type;
+ if (liftedCall) {
+ if (!rightOperandType.IsNullableType()) {
+ throw Error.TestValueTypeDoesNotMatchComparisonMethodParameter(rightOperandType, rightParam.ParameterType);
+ }
+ rightOperandType = rightOperandType.GetNonNullableType();
+ }
+ if (!ParameterIsAssignable(rightParam, rightOperandType)) {
+ throw Error.TestValueTypeDoesNotMatchComparisonMethodParameter(rightOperandType, rightParam.ParameterType);
+ }
+ }
+ }
+ } else {
+ // When comparison method is not present, all the test values must have
+ // the same type. Use the first test value's type as the baseline.
+ var firstTestValue = caseList[0].TestValues[0];
+ foreach (var c in caseList) {
+ ContractUtils.RequiresNotNull(c, "cases");
+ ValidateSwitchCaseType(c.Body, customType, resultType, "cases");
+ // When no comparison method is provided, require all test values to have the same type.
+ for (int i = 0; i < c.TestValues.Count; i++) {
+ if (!TypeUtils.AreEquivalent(firstTestValue.Type, c.TestValues[i].Type)) {
+ throw new ArgumentException(Strings.AllTestValuesMustHaveSameType, "cases");
+ }
+ }
+ }
+
+ // Now we need to validate that switchValue.Type and testValueType
+ // make sense in an Equal node. Fortunately, Equal throws a
+ // reasonable error, so just call it.
+ var equal = Equal(switchValue, firstTestValue, false, comparison);
+
+ // Get the comparison function from equals node.
+ comparison = equal.Method;
+ }
+
+ if (defaultBody == null) {
+ ContractUtils.Requires(resultType == typeof(void), "defaultBody", Strings.DefaultBodyMustBeSupplied);
+ } else {
+ ValidateSwitchCaseType(defaultBody, customType, resultType, "defaultBody");
+ }
+
+ // if we have a non-boolean userdefined equals, we don't want it.
+ if (comparison != null && comparison.ReturnType != typeof(bool)) {
+ throw Error.EqualityMustReturnBoolean(comparison);
+ }
+
+ return new SwitchExpression(resultType, switchValue, defaultBody, comparison, caseList);
+ }
+
+
+ /// <summary>
+ /// If custom type is provided, all branches must be reference assignable to the result type.
+ /// If no custom type is provided, all branches must have the same type - resultType.
+ /// </summary>
+ private static void ValidateSwitchCaseType(Expression @case, bool customType, Type resultType, string parameterName) {
+ if (customType) {
+ if (resultType != typeof(void)) {
+ if (!TypeUtils.AreReferenceAssignable(resultType, @case.Type)) {
+ throw new ArgumentException(Strings.ArgumentTypesMustMatch, parameterName);
+ }
+ }
+ } else {
+ if (!TypeUtils.AreEquivalent(resultType, @case.Type)) {
+ throw new ArgumentException(Strings.AllCaseBodiesMustHaveSameType, parameterName);
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SymbolDocumentInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SymbolDocumentInfo.cs
new file mode 100644
index 00000000000..71c23c2043d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/SymbolDocumentInfo.cs
@@ -0,0 +1,158 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Stores information needed to emit debugging symbol information for a
+ /// source file, in particular the file name and unique language identifier.
+ /// </summary>
+ public class SymbolDocumentInfo {
+ private readonly string _fileName;
+
+ internal SymbolDocumentInfo(string fileName) {
+ ContractUtils.RequiresNotNull(fileName, "fileName");
+ _fileName = fileName;
+ }
+
+ /// <summary>
+ /// The source file name.
+ /// </summary>
+ public string FileName {
+ get { return _fileName; }
+ }
+
+ /// <summary>
+ /// Returns the language's unique identifier, if any.
+ /// </summary>
+ public virtual Guid Language {
+ get { return Guid.Empty; }
+ }
+
+ /// <summary>
+ /// Returns the language vendor's unique identifier, if any.
+ /// </summary>
+ public virtual Guid LanguageVendor {
+ get { return Guid.Empty; }
+ }
+
+ /// <summary>
+ /// Returns the document type's unique identifier, if any.
+ /// Defaults to the guid for a text file.
+ /// </summary>
+ public virtual Guid DocumentType {
+ get { return Compiler.SymbolGuids.DocumentType_Text; }
+ }
+ }
+
+ internal sealed class SymbolDocumentWithGuids : SymbolDocumentInfo {
+ private readonly Guid _language;
+ private readonly Guid _vendor;
+ private readonly Guid _documentType;
+
+ internal SymbolDocumentWithGuids(string fileName, ref Guid language)
+ : base(fileName) {
+ _language = language;
+ _documentType = Compiler.SymbolGuids.DocumentType_Text;
+ }
+
+ internal SymbolDocumentWithGuids(string fileName, ref Guid language, ref Guid vendor)
+ : base(fileName) {
+ _language = language;
+ _vendor = vendor;
+ _documentType = Compiler.SymbolGuids.DocumentType_Text;
+ }
+
+ internal SymbolDocumentWithGuids(string fileName, ref Guid language, ref Guid vendor, ref Guid documentType)
+ : base(fileName) {
+ _language = language;
+ _vendor = vendor;
+ _documentType = documentType;
+ }
+
+ public override Guid Language {
+ get { return _language; }
+ }
+
+ public override Guid LanguageVendor {
+ get { return _vendor; }
+ }
+
+ public override Guid DocumentType {
+ get { return _documentType; }
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates an instance of <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" />.
+ /// </summary>
+ /// <param name="fileName">A <see cref="T:System.String" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" /> equal to.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" /> that has the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" /> property set to the specified value.</returns>
+ public static SymbolDocumentInfo SymbolDocument(string fileName) {
+ return new SymbolDocumentInfo(fileName);
+ }
+
+ /// <summary>
+ /// Creates an instance of <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" />.
+ /// </summary>
+ /// <param name="fileName">A <see cref="T:System.String" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" /> equal to.</param>
+ /// <param name="language">A <see cref="T:System.Guid" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.Language" /> equal to.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" /> that has the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" />
+ /// and <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.Language" /> properties set to the specified value.</returns>
+ public static SymbolDocumentInfo SymbolDocument(string fileName, Guid language) {
+ return new SymbolDocumentWithGuids(fileName, ref language);
+ }
+
+ /// <summary>
+ /// Creates an instance of <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" />.
+ /// </summary>
+ /// <param name="fileName">A <see cref="T:System.String" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" /> equal to.</param>
+ /// <param name="language">A <see cref="T:System.Guid" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.Language" /> equal to.</param>
+ /// <param name="languageVendor">A <see cref="T:System.Guid" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.LanguageVendor" /> equal to.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" /> that has the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" />
+ /// and <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.Language" />
+ /// and <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.LanguageVendor" /> properties set to the specified value.</returns>
+ public static SymbolDocumentInfo SymbolDocument(string fileName, Guid language, Guid languageVendor) {
+ return new SymbolDocumentWithGuids(fileName, ref language, ref languageVendor);
+ }
+
+ /// <summary>
+ /// Creates an instance of <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" />.
+ /// </summary>
+ /// <param name="fileName">A <see cref="T:System.String" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" /> equal to.</param>
+ /// <param name="language">A <see cref="T:System.Guid" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.Language" /> equal to.</param>
+ /// <param name="languageVendor">A <see cref="T:System.Guid" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.LanguageVendor" /> equal to.</param>
+ /// <param name="documentType">A <see cref="T:System.Guid" /> to set the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.DocumentType" /> equal to.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.SymbolDocumentInfo" /> that has the <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.FileName" />
+ /// and <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.Language" />
+ /// and <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.LanguageVendor" />
+ /// and <see cref="P:Microsoft.Linq.Expressions.SymbolDocumentInfo.DocumentType" /> properties set to the specified value.</returns>
+ public static SymbolDocumentInfo SymbolDocument(string fileName, Guid language, Guid languageVendor, Guid documentType) {
+ return new SymbolDocumentWithGuids(fileName, ref language, ref languageVendor, ref documentType);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TryExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TryExpression.cs
new file mode 100644
index 00000000000..e38aa9e601e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TryExpression.cs
@@ -0,0 +1,215 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents a try/catch/finally/fault block.
+ ///
+ /// The body is protected by the try block.
+ /// The handlers consist of a set of <see cref="CatchBlock"/>s that can either be catch or filters.
+ /// The fault runs if an exception is thrown.
+ /// The finally runs regardless of how control exits the body.
+ /// Only one of fault or finally can be supplied.
+ /// The return type of the try block must match the return type of any associated catch statements.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.TryExpressionProxy))]
+#endif
+ public sealed class TryExpression : Expression {
+ private readonly Type _type;
+ private readonly Expression _body;
+ private readonly ReadOnlyCollection<CatchBlock> _handlers;
+ private readonly Expression _finally;
+ private readonly Expression _fault;
+
+ internal TryExpression(Type type, Expression body, Expression @finally, Expression fault, ReadOnlyCollection<CatchBlock> handlers) {
+ _type = type;
+ _body = body;
+ _handlers = handlers;
+ _finally = @finally;
+ _fault = fault;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return ExpressionType.Try; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Expression"/> representing the body of the try block.
+ /// </summary>
+ public Expression Body {
+ get { return _body; }
+ }
+
+ /// <summary>
+ /// Gets the collection of <see cref="CatchBlock"/>s associated with the try block.
+ /// </summary>
+ public ReadOnlyCollection<CatchBlock> Handlers {
+ get { return _handlers; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Expression"/> representing the finally block.
+ /// </summary>
+ public Expression Finally {
+ get { return _finally; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Expression"/> representing the fault block.
+ /// </summary>
+ public Expression Fault {
+ get { return _fault; }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitTry(this);
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a <see cref="TryExpression"/> representing a try block with a fault block and no catch statements.
+ /// </summary>
+ /// <param name="body">The body of the try block.</param>
+ /// <param name="fault">The body of the fault block.</param>
+ /// <returns>The created <see cref="TryExpression"/>.</returns>
+ public static TryExpression TryFault(Expression body, Expression fault) {
+ return MakeTry(null, body, null, fault, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TryExpression"/> representing a try block with a finally block and no catch statements.
+ /// </summary>
+ /// <param name="body">The body of the try block.</param>
+ /// <param name="finally">The body of the finally block.</param>
+ /// <returns>The created <see cref="TryExpression"/>.</returns>
+ public static TryExpression TryFinally(Expression body, Expression @finally) {
+ return MakeTry(null, body, @finally, null, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TryExpression"/> representing a try block with any number of catch statements and neither a fault nor finally block.
+ /// </summary>
+ /// <param name="body">The body of the try block.</param>
+ /// <param name="handlers">The array of zero or more <see cref="CatchBlock"/>s representing the catch statements to be associated with the try block.</param>
+ /// <returns>The created <see cref="TryExpression"/>.</returns>
+ public static TryExpression TryCatch(Expression body, params CatchBlock[] handlers) {
+ return MakeTry(null, body, null, null, handlers);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TryExpression"/> representing a try block with any number of catch statements and a finally block.
+ /// </summary>
+ /// <param name="body">The body of the try block.</param>
+ /// <param name="finally">The body of the finally block.</param>
+ /// <param name="handlers">The array of zero or more <see cref="CatchBlock"/>s representing the catch statements to be associated with the try block.</param>
+ /// <returns>The created <see cref="TryExpression"/>.</returns>
+ public static TryExpression TryCatchFinally(Expression body, Expression @finally, params CatchBlock[] handlers) {
+ return MakeTry(null, body, @finally, null, handlers);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TryExpression"/> representing a try block with the specified elements.
+ /// </summary>
+ /// <param name="type">The result type of the try expression. If null, bodh and all handlers must have identical type.</param>
+ /// <param name="body">The body of the try block.</param>
+ /// <param name="finally">The body of the finally block. Pass null if the try block has no finally block associated with it.</param>
+ /// <param name="fault">The body of the t block. Pass null if the try block has no fault block associated with it.</param>
+ /// <param name="handlers">A collection of <see cref="CatchBlock"/>s representing the catch statements to be associated with the try block.</param>
+ /// <returns>The created <see cref="TryExpression"/>.</returns>
+ public static TryExpression MakeTry(Type type, Expression body, Expression @finally, Expression fault, IEnumerable<CatchBlock> handlers) {
+ RequiresCanRead(body, "body");
+
+ var @catch = handlers.ToReadOnly();
+ ContractUtils.RequiresNotNullItems(@catch, "handlers");
+ ValidateTryAndCatchHaveSameType(type, body, @catch);
+
+ if (fault != null) {
+ if (@finally != null || @catch.Count > 0) {
+ throw Error.FaultCannotHaveCatchOrFinally();
+ }
+ RequiresCanRead(fault, "fault");
+ } else if (@finally != null) {
+ RequiresCanRead(@finally, "finally");
+ } else if (@catch.Count == 0) {
+ throw Error.TryMustHaveCatchFinallyOrFault();
+ }
+
+ return new TryExpression(type ?? body.Type, body, @finally, fault, @catch);
+ }
+
+ //Validate that the body of the try expression must have the same type as the body of every try block.
+ private static void ValidateTryAndCatchHaveSameType(Type type, Expression tryBody, ReadOnlyCollection<CatchBlock> handlers) {
+ // Type unification ... all parts must be reference assignable to "type"
+ if (type != null) {
+ if (type != typeof(void)) {
+ if (!TypeUtils.AreReferenceAssignable(type, tryBody.Type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ foreach (var cb in handlers) {
+ if (!TypeUtils.AreReferenceAssignable(type, cb.Body.Type)) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ }
+ }
+ } else if (tryBody == null || tryBody.Type == typeof(void)) {
+ //The body of every try block must be null or have void type.
+ foreach (CatchBlock cb in handlers) {
+ if (cb.Body != null && cb.Body.Type != typeof(void)) {
+ throw Error.BodyOfCatchMustHaveSameTypeAsBodyOfTry();
+ }
+ }
+ } else {
+ //Body of every catch must have the same type of body of try.
+ type = tryBody.Type;
+ foreach (CatchBlock cb in handlers) {
+ if (cb.Body == null || !TypeUtils.AreEquivalent(cb.Body.Type, type)) {
+ throw Error.BodyOfCatchMustHaveSameTypeAsBodyOfTry();
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeBinaryExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeBinaryExpression.cs
new file mode 100644
index 00000000000..101591c9c0c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeBinaryExpression.cs
@@ -0,0 +1,198 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ /// <summary>
+ /// Represents an operation between an expression and a type.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.TypeBinaryExpressionProxy))]
+#endif
+ public sealed class TypeBinaryExpression : Expression {
+ private readonly Expression _expression;
+ private readonly Type _typeOperand;
+ private readonly ExpressionType _nodeKind;
+
+ internal TypeBinaryExpression(Expression expression, Type typeOperand, ExpressionType nodeKind) {
+ _expression = expression;
+ _typeOperand = typeOperand;
+ _nodeKind = nodeKind;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents.
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return typeof(bool); }
+ }
+
+ /// <summary>
+ /// Returns the node type of this Expression. Extension nodes should return
+ /// ExpressionType.Extension when overriding this method.
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return _nodeKind; }
+ }
+
+ /// <summary>
+ /// Gets the expression operand of a type test operation.
+ /// </summary>
+ public Expression Expression {
+ get { return _expression; }
+ }
+
+ /// <summary>
+ /// Gets the type operand of a type test operation.
+ /// </summary>
+ public Type TypeOperand {
+ get { return _typeOperand; }
+ }
+
+ #region Reduce TypeEqual
+
+ internal Expression ReduceTypeEqual() {
+ Type cType = Expression.Type;
+
+ // For value types (including Void, but not nullables), we can
+ // determine the result now
+ if (cType.IsValueType && !cType.IsNullableType()) {
+ return Expression.Block(Expression, Expression.Constant(cType == _typeOperand.GetNonNullableType()));
+ }
+
+ // Can check the value right now for constants.
+ if (Expression.NodeType == ExpressionType.Constant) {
+ return ReduceConstantTypeEqual();
+ }
+
+ // If the operand type is a sealed reference type or a nullable
+ // type, it will match if value is not null
+ if (cType.IsSealed && (cType == _typeOperand)) {
+ if (cType.IsNullableType()) {
+ return Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type));
+ } else {
+ return Expression.ReferenceNotEqual(Expression, Expression.Constant(null, Expression.Type));
+ }
+ }
+
+ // expression is a ByVal parameter. Can safely reevaluate.
+ var parameter = Expression as ParameterExpression;
+ if (parameter != null && !parameter.IsByRef) {
+ return ByValParameterTypeEqual(parameter);
+ }
+
+ // Create a temp so we only evaluate the left side once
+ parameter = Expression.Parameter(typeof(object));
+
+ // Convert to object if necessary
+ var expression = Expression;
+ if (!TypeUtils.AreReferenceAssignable(typeof(object), expression.Type)) {
+ expression = Expression.Convert(expression, typeof(object));
+ }
+
+ return Expression.Block(
+ new[] { parameter },
+ Expression.Assign(parameter, expression),
+ ByValParameterTypeEqual(parameter)
+ );
+ }
+
+ // Helper that is used when re-eval of LHS is safe.
+ private Expression ByValParameterTypeEqual(ParameterExpression value) {
+ Expression getType = Expression.Call(value, typeof(object).GetMethod("GetType"));
+
+ // In remoting scenarios, obj.GetType() can return an interface.
+ // But there's a bug in the JIT32's optimized "obj.GetType() ==
+ // typeof(ISomething)" codegen, causing it to always return false.
+ // We workaround the bug by generating different, less optimal IL
+ // if TypeOperand is an interface.
+ if (_typeOperand.IsInterface) {
+ var temp = Expression.Parameter(typeof(Type));
+ getType = Expression.Block(new[] { temp }, Expression.Assign(temp, getType), temp);
+ }
+
+ // We use reference equality when comparing to null for correctness
+ // (don't invoke a user defined operator), and reference equality
+ // on types for performance (so the JIT can optimize the IL).
+ return Expression.AndAlso(
+ Expression.ReferenceNotEqual(value, Expression.Constant(null)),
+ Expression.ReferenceEqual(
+ getType,
+ Expression.Constant(_typeOperand.GetNonNullableType(), typeof(Type))
+ )
+ );
+ }
+
+ private Expression ReduceConstantTypeEqual() {
+ ConstantExpression ce = Expression as ConstantExpression;
+ //TypeEqual(null, T) always returns false.
+ if (ce.Value == null) {
+ return Expression.Constant(false);
+ } else {
+ return Expression.Constant(_typeOperand.GetNonNullableType() == ce.Value.GetType());
+ }
+ }
+
+ #endregion
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitTypeBinary(this);
+ }
+ }
+
+ public partial class Expression {
+ /// <summary>
+ /// Creates a <see cref="TypeBinaryExpression"/>.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"/> to set the <see cref="Expression"/> property equal to.</param>
+ /// <param name="type">A <see cref="Type"/> to set the <see cref="TypeBinaryExpression.TypeOperand"/> property equal to.</param>
+ /// <returns>A <see cref="TypeBinaryExpression"/> for which the <see cref="NodeType"/> property is equal to <see cref="TypeIs"/> and for which the <see cref="Expression"/> and <see cref="TypeBinaryExpression.TypeOperand"/> properties are set to the specified values.</returns>
+ public static TypeBinaryExpression TypeIs(Expression expression, Type type) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.Requires(!type.IsByRef, "type", Strings.TypeMustNotBeByRef);
+
+ return new TypeBinaryExpression(expression, type, ExpressionType.TypeIs);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TypeBinaryExpression"/> that compares run-time type identity.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"/> to set the <see cref="Expression"/> property equal to.</param>
+ /// <param name="type">A <see cref="Type"/> to set the <see cref="TypeBinaryExpression.TypeOperand"/> property equal to.</param>
+ /// <returns>A <see cref="TypeBinaryExpression"/> for which the <see cref="NodeType"/> property is equal to <see cref="TypeEqual"/> and for which the <see cref="Expression"/> and <see cref="TypeBinaryExpression.TypeOperand"/> properties are set to the specified values.</returns>
+ public static TypeBinaryExpression TypeEqual(Expression expression, Type type) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.Requires(!type.IsByRef, "type", Strings.TypeMustNotBeByRef);
+
+ return new TypeBinaryExpression(expression, type, ExpressionType.TypeEqual);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeUtils.cs
new file mode 100644
index 00000000000..d154ecdb386
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/TypeUtils.cs
@@ -0,0 +1,585 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+using System.Reflection;
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+
+ internal static class TypeUtils {
+ private const BindingFlags AnyStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+ internal const MethodAttributes PublicStatic = MethodAttributes.Public | MethodAttributes.Static;
+
+ internal static Type GetNonNullableType(this Type type) {
+ if (IsNullableType(type)) {
+ return type.GetGenericArguments()[0];
+ }
+ return type;
+ }
+
+ internal static Type GetNullableType(Type type) {
+ Debug.Assert(type != null, "type cannot be null");
+ if (type.IsValueType && !IsNullableType(type)) {
+ return typeof(Nullable<>).MakeGenericType(type);
+ }
+ return type;
+ }
+
+ internal static bool IsNullableType(this Type type) {
+ return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+ internal static bool IsBool(Type type) {
+ return GetNonNullableType(type) == typeof(bool);
+ }
+
+ internal static bool IsNumeric(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Char:
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Double:
+ case TypeCode.Single:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool IsInteger(Type type) {
+ type = GetNonNullableType(type);
+ if (type.IsEnum) {
+ return false;
+ }
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+
+ internal static bool IsArithmetic(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Double:
+ case TypeCode.Single:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool IsUnsignedInt(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool IsIntegerOrBool(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Int64:
+ case TypeCode.Int32:
+ case TypeCode.Int16:
+ case TypeCode.UInt64:
+ case TypeCode.UInt32:
+ case TypeCode.UInt16:
+ case TypeCode.Boolean:
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool AreEquivalent(Type t1, Type t2) {
+#if MICROSOFT_SCRIPTING_CORE
+ return t1 == t2;
+#else
+ return t1 == t2 || t1.IsEquivalentTo(t2);
+#endif
+ }
+
+ internal static bool AreReferenceAssignable(Type dest, Type src) {
+ // WARNING: This actually implements "Is this identity assignable and/or reference assignable?"
+ if (AreEquivalent(dest, src)) {
+ return true;
+ }
+ if (!dest.IsValueType && !src.IsValueType && dest.IsAssignableFrom(src)) {
+ return true;
+ }
+ return false;
+ }
+
+ // Checks if the type is a valid target for an instance call
+ internal static bool IsValidInstanceType(MemberInfo member, Type instanceType) {
+ Type targetType = member.DeclaringType;
+ if (AreReferenceAssignable(targetType, instanceType)) {
+ return true;
+ }
+ if (instanceType.IsValueType) {
+ if (AreReferenceAssignable(targetType, typeof(System.Object))) {
+ return true;
+ }
+ if (AreReferenceAssignable(targetType, typeof(System.ValueType))) {
+ return true;
+ }
+ if (instanceType.IsEnum && AreReferenceAssignable(targetType, typeof(System.Enum))) {
+ return true;
+ }
+ // A call to an interface implemented by a struct is legal whether the struct has
+ // been boxed or not.
+ if (targetType.IsInterface) {
+ foreach (Type interfaceType in instanceType.GetInterfaces()) {
+ if (AreReferenceAssignable(targetType, interfaceType)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ internal static bool HasIdentityPrimitiveOrNullableConversion(Type source, Type dest) {
+ Debug.Assert(source != null && dest != null);
+
+ // Identity conversion
+ if (AreEquivalent(source, dest)) {
+ return true;
+ }
+
+ // Nullable conversions
+ if (IsNullableType(source) && AreEquivalent(dest, GetNonNullableType(source))) {
+ return true;
+ }
+ if (IsNullableType(dest) && AreEquivalent(source, GetNonNullableType(dest))) {
+ return true;
+ }
+ // Primitive runtime conversions
+ // All conversions amongst enum, bool, char, integer and float types
+ // (and their corresponding nullable types) are legal except for
+ // nonbool==>bool and nonbool==>bool?
+ // Since we have already covered bool==>bool, bool==>bool?, etc, above,
+ // we can just disallow having a bool or bool? destination type here.
+ if (IsConvertible(source) && IsConvertible(dest) && GetNonNullableType(dest) != typeof(bool)) {
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool HasReferenceConversion(Type source, Type dest) {
+ Debug.Assert(source != null && dest != null);
+
+ // void -> void conversion is handled elsewhere
+ // (it's an identity conversion)
+ // All other void conversions are disallowed.
+ if (source == typeof(void) || dest == typeof(void)) {
+ return false;
+ }
+
+ Type nnSourceType = TypeUtils.GetNonNullableType(source);
+ Type nnDestType = TypeUtils.GetNonNullableType(dest);
+
+ // Down conversion
+ if (nnSourceType.IsAssignableFrom(nnDestType)) {
+ return true;
+ }
+ // Up conversion
+ if (nnDestType.IsAssignableFrom(nnSourceType)) {
+ return true;
+ }
+ // Interface conversion
+ if (source.IsInterface || dest.IsInterface) {
+ return true;
+ }
+ // Object conversion
+ if (source == typeof(object) || dest == typeof(object)) {
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool IsConvertible(Type type) {
+ type = GetNonNullableType(type);
+ if (type.IsEnum) {
+ return true;
+ }
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Boolean:
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Char:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ internal static bool HasReferenceEquality(Type left, Type right) {
+ if (left.IsValueType || right.IsValueType) {
+ return false;
+ }
+
+ // If we have an interface and a reference type then we can do
+ // reference equality.
+
+ // If we have two reference types and one is assignable to the
+ // other then we can do reference equality.
+
+ return left.IsInterface || right.IsInterface ||
+ AreReferenceAssignable(left, right) ||
+ AreReferenceAssignable(right, left);
+ }
+
+ internal static bool HasBuiltInEqualityOperator(Type left, Type right) {
+ // If we have an interface and a reference type then we can do
+ // reference equality.
+ if (left.IsInterface && !right.IsValueType) {
+ return true;
+ }
+ if (right.IsInterface && !left.IsValueType) {
+ return true;
+ }
+ // If we have two reference types and one is assignable to the
+ // other then we can do reference equality.
+ if (!left.IsValueType && !right.IsValueType) {
+ if (AreReferenceAssignable(left, right) || AreReferenceAssignable(right, left)) {
+ return true;
+ }
+ }
+ // Otherwise, if the types are not the same then we definitely
+ // do not have a built-in equality operator.
+ if (!AreEquivalent(left, right)) {
+ return false;
+ }
+ // We have two identical value types, modulo nullability. (If they were both the
+ // same reference type then we would have returned true earlier.)
+ Debug.Assert(left.IsValueType);
+ // Equality between struct types is only defined for numerics, bools, enums,
+ // and their nullable equivalents.
+ Type nnType = GetNonNullableType(left);
+ if (nnType == typeof(bool) || IsNumeric(nnType) || nnType.IsEnum) {
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool IsImplicitlyConvertible(Type source, Type destination) {
+ return AreEquivalent(source, destination) || // identity conversion
+ IsImplicitNumericConversion(source, destination) ||
+ IsImplicitReferenceConversion(source, destination) ||
+ IsImplicitBoxingConversion(source, destination) ||
+ IsImplicitNullableConversion(source, destination);
+ }
+
+
+ internal static MethodInfo GetUserDefinedCoercionMethod(Type convertFrom, Type convertToType, bool implicitOnly) {
+ // check for implicit coercions first
+ Type nnExprType = TypeUtils.GetNonNullableType(convertFrom);
+ Type nnConvType = TypeUtils.GetNonNullableType(convertToType);
+ // try exact match on types
+ MethodInfo[] eMethods = nnExprType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ MethodInfo method = FindConversionOperator(eMethods, convertFrom, convertToType, implicitOnly);
+ if (method != null) {
+ return method;
+ }
+ MethodInfo[] cMethods = nnConvType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ method = FindConversionOperator(cMethods, convertFrom, convertToType, implicitOnly);
+ if (method != null) {
+ return method;
+ }
+ // try lifted conversion
+ if (!TypeUtils.AreEquivalent(nnExprType, convertFrom) ||
+ !TypeUtils.AreEquivalent(nnConvType, convertToType)) {
+ method = FindConversionOperator(eMethods, nnExprType, nnConvType, implicitOnly);
+ if (method == null) {
+ method = FindConversionOperator(cMethods, nnExprType, nnConvType, implicitOnly);
+ }
+ if (method != null) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ internal static MethodInfo FindConversionOperator(MethodInfo[] methods, Type typeFrom, Type typeTo, bool implicitOnly) {
+ foreach (MethodInfo mi in methods) {
+ if (mi.Name != "op_Implicit" && (implicitOnly || mi.Name != "op_Explicit")) {
+ continue;
+ }
+ if (!TypeUtils.AreEquivalent(mi.ReturnType, typeTo)) {
+ continue;
+ }
+ ParameterInfo[] pis = mi.GetParametersCached();
+ if (!TypeUtils.AreEquivalent(pis[0].ParameterType, typeFrom)) {
+ continue;
+ }
+ return mi;
+ }
+ return null;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static bool IsImplicitNumericConversion(Type source, Type destination) {
+ TypeCode tcSource = Type.GetTypeCode(source);
+ TypeCode tcDest = Type.GetTypeCode(destination);
+
+ switch (tcSource) {
+ case TypeCode.SByte:
+ switch (tcDest) {
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Byte:
+ switch (tcDest) {
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Int16:
+ switch (tcDest) {
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.UInt16:
+ switch (tcDest) {
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Int32:
+ switch (tcDest) {
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.UInt32:
+ switch (tcDest) {
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ switch (tcDest) {
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Char:
+ switch (tcDest) {
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
+ }
+ return false;
+ case TypeCode.Single:
+ return (tcDest == TypeCode.Double);
+ }
+ return false;
+ }
+
+ private static bool IsImplicitReferenceConversion(Type source, Type destination) {
+ return destination.IsAssignableFrom(source);
+ }
+
+ private static bool IsImplicitBoxingConversion(Type source, Type destination) {
+ if (source.IsValueType && (destination == typeof(object) || destination == typeof(System.ValueType)))
+ return true;
+ if (source.IsEnum && destination == typeof(System.Enum))
+ return true;
+ return false;
+ }
+
+ private static bool IsImplicitNullableConversion(Type source, Type destination) {
+ if (IsNullableType(destination))
+ return IsImplicitlyConvertible(GetNonNullableType(source), GetNonNullableType(destination));
+ return false;
+ }
+
+ internal static bool IsSameOrSubclass(Type type, Type subType) {
+ return AreEquivalent(type, subType) || subType.IsSubclassOf(type);
+ }
+
+ internal static void ValidateType(Type type) {
+ if (type.IsGenericTypeDefinition) {
+ throw Error.TypeIsGeneric(type);
+ }
+ if (type.ContainsGenericParameters) {
+ throw Error.TypeContainsGenericParameters(type);
+ }
+ }
+
+ //from TypeHelper
+ internal static Type FindGenericType(Type definition, Type type) {
+ while (type != null && type != typeof(object)) {
+ if (type.IsGenericType && AreEquivalent(type.GetGenericTypeDefinition(), definition)) {
+ return type;
+ }
+ if (definition.IsInterface) {
+ foreach (Type itype in type.GetInterfaces()) {
+ Type found = FindGenericType(definition, itype);
+ if (found != null)
+ return found;
+ }
+ }
+ type = type.BaseType;
+ }
+ return null;
+ }
+
+ internal static bool IsUnsigned(Type type) {
+ type = GetNonNullableType(type);
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Byte:
+ case TypeCode.UInt16:
+ case TypeCode.Char:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ internal static bool IsFloatingPoint(Type type) {
+ type = GetNonNullableType(type);
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Searches for an operator method on the type. The method must have
+ /// the specified signature, no generic arguments, and have the
+ /// SpecialName bit set. Also searches inherited operator methods.
+ ///
+ /// NOTE: This was designed to satisfy the needs of op_True and
+ /// op_False, because we have to do runtime lookup for those. It may
+ /// not work right for unary operators in general.
+ /// </summary>
+ internal static MethodInfo GetBooleanOperator(Type type, string name) {
+ do {
+ MethodInfo result = type.GetMethodValidated(name, AnyStatic, null, new Type[] { type }, null);
+ if (result != null && result.IsSpecialName && !result.ContainsGenericParameters) {
+ return result;
+ }
+ type = type.BaseType;
+ } while (type != null);
+ return null;
+ }
+
+ internal static Type GetNonRefType(this Type type) {
+ return type.IsByRef ? type.GetElementType() : type;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/UnaryExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/UnaryExpression.cs
new file mode 100644
index 00000000000..dbdc26c57ea
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Ast/UnaryExpression.cs
@@ -0,0 +1,989 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// Represents an expression that has a unary operator.
+ /// </summary>
+#if !SILVERLIGHT
+ [DebuggerTypeProxy(typeof(Expression.UnaryExpressionProxy))]
+#endif
+ public sealed class UnaryExpression : Expression {
+ private readonly Expression _operand;
+ private readonly MethodInfo _method;
+ private readonly ExpressionType _nodeType;
+ private readonly Type _type;
+
+ internal UnaryExpression(ExpressionType nodeType, Expression expression, Type type, MethodInfo method) {
+ _operand = expression;
+ _method = method;
+ _nodeType = nodeType;
+ _type = type;
+ }
+
+ /// <summary>
+ /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
+ /// </summary>
+ /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
+ public sealed override Type Type {
+ get { return _type; }
+ }
+
+ /// <summary>
+ /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
+ /// </summary>
+ /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
+ public sealed override ExpressionType NodeType {
+ get { return _nodeType; }
+ }
+
+ /// <summary>
+ /// Gets the operand of the unary operation.
+ /// </summary>
+ /// <returns> An <see cref="ExpressionType"/> that represents the operand of the unary operation.</returns>
+ public Expression Operand {
+ get { return _operand; }
+ }
+
+ /// <summary>
+ /// Gets the implementing method for the unary operation.
+ /// </summary>
+ /// <returns>The <see cref="MethodInfo"/> that represents the implementing method.</returns>
+ public MethodInfo Method {
+ get { return _method; }
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator.
+ /// </summary>
+ /// <returns>true if the node represents a lifted call; otherwise, false.</returns>
+ public bool IsLifted {
+ get {
+ if (NodeType == ExpressionType.TypeAs || NodeType == ExpressionType.Quote || NodeType == ExpressionType.Throw) {
+ return false;
+ }
+ bool operandIsNullable = TypeUtils.IsNullableType(_operand.Type);
+ bool resultIsNullable = TypeUtils.IsNullableType(this.Type);
+ if (_method != null) {
+ return (operandIsNullable && !TypeUtils.AreEquivalent(_method.GetParametersCached()[0].ParameterType, _operand.Type)) ||
+ (resultIsNullable && !TypeUtils.AreEquivalent(_method.ReturnType, this.Type));
+ }
+ return operandIsNullable || resultIsNullable;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node represents a lifted call to an operator whose return type is lifted to a nullable type.
+ /// </summary>
+ /// <returns>true if the operator's return type is lifted to a nullable type; otherwise, false.</returns>
+ public bool IsLiftedToNull {
+ get {
+ return IsLifted && TypeUtils.IsNullableType(this.Type);
+ }
+ }
+
+ internal override Expression Accept(ExpressionVisitor visitor) {
+ return visitor.VisitUnary(this);
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the expression tree node can be reduced.
+ /// </summary>
+ public override bool CanReduce {
+ get {
+ switch (_nodeType) {
+ case ExpressionType.PreIncrementAssign:
+ case ExpressionType.PreDecrementAssign:
+ case ExpressionType.PostIncrementAssign:
+ case ExpressionType.PostDecrementAssign:
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Reduces the expression node to a simpler expression.
+ /// If CanReduce returns true, this should return a valid expression.
+ /// This method is allowed to return another node which itself
+ /// must be reduced.
+ /// </summary>
+ /// <returns>The reduced expression.</returns>
+ public override Expression Reduce() {
+ if (CanReduce) {
+ switch (_operand.NodeType) {
+ case ExpressionType.Index:
+ return ReduceIndex();
+ case ExpressionType.MemberAccess:
+ return ReduceMember();
+ default:
+ return ReduceVariable();
+ }
+ }
+ return this;
+ }
+
+ private bool IsPrefix {
+ get { return _nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PreDecrementAssign; }
+ }
+
+ private UnaryExpression FunctionalOp(Expression operand) {
+ ExpressionType functional;
+ if (_nodeType == ExpressionType.PreIncrementAssign || _nodeType == ExpressionType.PostIncrementAssign) {
+ functional = ExpressionType.Increment;
+ } else {
+ functional = ExpressionType.Decrement;
+ }
+ return new UnaryExpression(functional, operand, operand.Type, _method);
+ }
+
+ private Expression ReduceVariable() {
+ if (IsPrefix) {
+ // (op) var
+ // ... is reduced into ...
+ // var = op(var)
+ return Assign(_operand, FunctionalOp(_operand));
+ }
+ // var (op)
+ // ... is reduced into ...
+ // temp = var
+ // var = op(var)
+ // temp
+ var temp = Parameter(_operand.Type, null);
+ return Block(
+ new[] { temp },
+ Assign(temp, _operand),
+ Assign(_operand, FunctionalOp(temp)),
+ temp
+ );
+ }
+
+ private Expression ReduceMember() {
+ var member = (MemberExpression)_operand;
+ if (member.Expression == null) {
+ //static member, reduce the same as variable
+ return ReduceVariable();
+ } else {
+ var temp1 = Parameter(member.Expression.Type, null);
+ var initTemp1 = Assign(temp1, member.Expression);
+ member = MakeMemberAccess(temp1, member.Member);
+
+ if (IsPrefix) {
+ // (op) value.member
+ // ... is reduced into ...
+ // temp1 = value
+ // temp1.member = op(temp1.member)
+ return Block(
+ new[] { temp1 },
+ initTemp1,
+ Assign(member, FunctionalOp(member))
+ );
+ }
+
+ // value.member (op)
+ // ... is reduced into ...
+ // temp1 = value
+ // temp2 = temp1.member
+ // temp1.member = op(temp2)
+ // temp2
+ var temp2 = Parameter(member.Type, null);
+ return Block(
+ new[] { temp1, temp2 },
+ initTemp1,
+ Assign(temp2, member),
+ Assign(member, FunctionalOp(temp2)),
+ temp2
+ );
+ }
+ }
+
+ private Expression ReduceIndex() {
+ // left[a0, a1, ... aN] (op)
+ //
+ // ... is reduced into ...
+ //
+ // tempObj = left
+ // tempArg0 = a0
+ // ...
+ // tempArgN = aN
+ // tempValue = tempObj[tempArg0, ... tempArgN]
+ // tempObj[tempArg0, ... tempArgN] = op(tempValue)
+ // tempValue
+
+ bool prefix = IsPrefix;
+ var index = (IndexExpression)_operand;
+ int count = index.Arguments.Count;
+ var block = new Expression[count + (prefix ? 2 : 4)];
+ var temps = new ParameterExpression[count + (prefix ? 1 : 2)];
+ var args = new ParameterExpression[count];
+
+ int i = 0;
+ temps[i] = Parameter(index.Object.Type, null);
+ block[i] = Assign(temps[i], index.Object);
+ i++;
+ while (i <= count) {
+ var arg = index.Arguments[i - 1];
+ args[i - 1] = temps[i] = Parameter(arg.Type, null);
+ block[i] = Assign(temps[i], arg);
+ i++;
+ }
+ index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
+ if (!prefix) {
+ var lastTemp = temps[i] = Parameter(index.Type, null);
+ block[i] = Assign(temps[i], index);
+ i++;
+ Debug.Assert(i == temps.Length);
+ block[i++] = Assign(index, FunctionalOp(lastTemp));
+ block[i++] = lastTemp;
+ } else {
+ Debug.Assert(i == temps.Length);
+ block[i++] = Assign(index, FunctionalOp(index));
+ }
+ Debug.Assert(i == block.Length);
+ return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
+ }
+ }
+
+ public partial class Expression {
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"></see>, given an operand, by calling the appropriate factory method.
+ /// </summary>
+ /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
+ /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
+ /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
+ /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
+ public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type) {
+ return MakeUnary(unaryType, operand, type, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"></see>, given an operand and implementing method, by calling the appropriate factory method.
+ /// </summary>
+ /// <param name="unaryType">The <see cref="ExpressionType"></see> that specifies the type of unary operation.</param>
+ /// <param name="operand">An <see cref="Expression"></see> that represents the operand.</param>
+ /// <param name="type">The <see cref="Type"></see> that specifies the type to be converted to (pass null if not applicable).</param>
+ /// <param name="method">The <see cref="MethodInfo"></see> that represents the implementing method.</param>
+ /// <returns>The <see cref="UnaryExpression"></see> that results from calling the appropriate factory method.</returns>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="unaryType"/> does not correspond to a unary expression.</exception>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="operand"/> is null.</exception>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ public static UnaryExpression MakeUnary(ExpressionType unaryType, Expression operand, Type type, MethodInfo method) {
+ switch (unaryType) {
+ case ExpressionType.Negate:
+ return Negate(operand, method);
+ case ExpressionType.NegateChecked:
+ return NegateChecked(operand, method);
+ case ExpressionType.Not:
+ return Not(operand, method);
+ case ExpressionType.IsFalse:
+ return IsFalse(operand, method);
+ case ExpressionType.IsTrue:
+ return IsTrue(operand, method);
+ case ExpressionType.OnesComplement:
+ return OnesComplement(operand, method);
+ case ExpressionType.ArrayLength:
+ return ArrayLength(operand);
+ case ExpressionType.Convert:
+ return Convert(operand, type, method);
+ case ExpressionType.ConvertChecked:
+ return ConvertChecked(operand, type, method);
+ case ExpressionType.Throw:
+ return Throw(operand, type);
+ case ExpressionType.TypeAs:
+ return TypeAs(operand, type);
+ case ExpressionType.Quote:
+ return Quote(operand);
+ case ExpressionType.UnaryPlus:
+ return UnaryPlus(operand, method);
+ case ExpressionType.Unbox:
+ return Unbox(operand, type);
+ case ExpressionType.Increment:
+ return Increment(operand, method);
+ case ExpressionType.Decrement:
+ return Decrement(operand, method);
+ case ExpressionType.PreIncrementAssign:
+ return PreIncrementAssign(operand, method);
+ case ExpressionType.PostIncrementAssign:
+ return PostIncrementAssign(operand, method);
+ case ExpressionType.PreDecrementAssign:
+ return PreDecrementAssign(operand, method);
+ case ExpressionType.PostDecrementAssign:
+ return PostDecrementAssign(operand, method);
+ default:
+ throw Error.UnhandledUnary(unaryType);
+ }
+ }
+
+ private static UnaryExpression GetUserDefinedUnaryOperatorOrThrow(ExpressionType unaryType, string name, Expression operand) {
+ UnaryExpression u = GetUserDefinedUnaryOperator(unaryType, name, operand);
+ if (u != null) {
+ ValidateParamswithOperandsOrThrow(u.Method.GetParametersCached()[0].ParameterType, operand.Type, unaryType, name);
+ return u;
+ }
+ throw Error.UnaryOperatorNotDefined(unaryType, operand.Type);
+ }
+
+ private static UnaryExpression GetUserDefinedUnaryOperator(ExpressionType unaryType, string name, Expression operand) {
+ Type operandType = operand.Type;
+ Type[] types = new Type[] { operandType };
+ Type nnOperandType = TypeUtils.GetNonNullableType(operandType);
+ BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+ MethodInfo method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
+ if (method != null) {
+ return new UnaryExpression(unaryType, operand, method.ReturnType, method);
+ }
+ // try lifted call
+ if (TypeUtils.IsNullableType(operandType)) {
+ types[0] = nnOperandType;
+ method = nnOperandType.GetMethodValidated(name, flags, null, types, null);
+ if (method != null && method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
+ return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
+ }
+ }
+ return null;
+ }
+
+ private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method) {
+ System.Diagnostics.Debug.Assert(method != null);
+ ValidateOperator(method);
+ ParameterInfo[] pms = method.GetParametersCached();
+ if (pms.Length != 1)
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ if (ParameterIsAssignable(pms[0], operand.Type)) {
+ ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name);
+ return new UnaryExpression(unaryType, operand, method.ReturnType, method);
+ }
+ // check for lifted call
+ if (TypeUtils.IsNullableType(operand.Type) &&
+ ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
+ method.ReturnType.IsValueType && !TypeUtils.IsNullableType(method.ReturnType)) {
+ return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
+ }
+
+ throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
+ }
+
+ private static UnaryExpression GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType) {
+ UnaryExpression u = GetUserDefinedCoercion(coercionType, expression, convertToType);
+ if (u != null) {
+ return u;
+ }
+ throw Error.CoercionOperatorNotDefined(expression.Type, convertToType);
+ }
+
+ private static UnaryExpression GetUserDefinedCoercion(ExpressionType coercionType, Expression expression, Type convertToType) {
+ MethodInfo method = TypeUtils.GetUserDefinedCoercionMethod(expression.Type, convertToType, false);
+ if (method != null) {
+ return new UnaryExpression(coercionType, expression, convertToType, method);
+ } else {
+ return null;
+ }
+ }
+
+ private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method) {
+ System.Diagnostics.Debug.Assert(method != null);
+ ValidateOperator(method);
+ ParameterInfo[] pms = method.GetParametersCached();
+ if (pms.Length != 1) {
+ throw Error.IncorrectNumberOfMethodCallArguments(method);
+ }
+ if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType)) {
+ return new UnaryExpression(unaryType, operand, method.ReturnType, method);
+ }
+ // check for lifted call
+ if ((TypeUtils.IsNullableType(operand.Type) || TypeUtils.IsNullableType(convertToType)) &&
+ ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
+ TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(convertToType))) {
+ return new UnaryExpression(unaryType, operand, convertToType, method);
+ }
+ throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
+ /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> properties set to the specified value.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
+ /// <exception cref="InvalidOperationException">Thrown when the unary minus operator is not defined for <see cref="P:Expression.Type"></see></exception>
+ public static UnaryExpression Negate(Expression expression) {
+ return Negate(expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"></see> that represents an arithmetic negation operation.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="P:UnaryExpression.Operand"></see> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="P:UnaryExpression.Method"></see> property equal to.</param>
+ /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="P:Expression.NodeType"></see> property equal to <see cref="P:ExpressionType.Negate"></see> and the <see cref="P:UnaryExpression.Operand"></see> and <see cref="P:UnaryExpression.Method"></see> properties set to the specified value.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
+ /// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception>
+ public static UnaryExpression Negate(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
+ return new UnaryExpression(ExpressionType.Negate, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Negate, "op_UnaryNegation", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.Negate, expression, method);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
+ /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> property set to the specified value.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
+ /// <exception cref="InvalidOperationException">Thown when the unary minus operator is not defined for expression.Type.</exception>
+ public static UnaryExpression UnaryPlus(Expression expression) {
+ return UnaryPlus(expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"></see> that represents a unary plus operation.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"></see> to set the <see cref="UnaryExpression.Operand"></see> property equal to.</param>
+ /// <param name="method">A <see cref="MethodInfo"></see> to set the <see cref="UnaryExpression.Method"></see> property equal to.</param>
+ /// <returns>A <see cref="UnaryExpression"></see> that has the <see cref="Expression.NodeType"></see> property equal to <see cref="ExpressionType.UnaryPlus"></see> and the <see cref="UnaryExpression.Operand"></see> and <see cref="UnaryExpression.Method"></see>property set to the specified value.</returns>
+ /// <exception cref="ArgumentNullException">Thrown when <paramref name="expression"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown when <paramref name="method"/> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
+ /// <exception cref="InvalidOperationException">Thown when <paramref name="method"/> is null and the unary minus operator is not defined for expression.Type or expression.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by method.</exception>
+ public static UnaryExpression UnaryPlus(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsArithmetic(expression.Type)) {
+ return new UnaryExpression(ExpressionType.UnaryPlus, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.UnaryPlus, "op_UnaryPlus", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.UnaryPlus, expression, method);
+ }
+
+ /// <summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking.</summary>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// Thrown when <paramref name="expression" /> is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">Thrown when the unary minus operator is not defined for <paramref name="expression" />.Type.</exception>
+ public static UnaryExpression NegateChecked(Expression expression) {
+ return NegateChecked(expression, null);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an arithmetic negation operation that has overflow checking. The implementing method can be specified.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.NegateChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
+ ///<exception cref="T:System.InvalidOperationException">
+ ///<paramref name="method" /> is null and the unary minus operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception>
+ public static UnaryExpression NegateChecked(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsArithmetic(expression.Type) && !TypeUtils.IsUnsignedInt(expression.Type)) {
+ return new UnaryExpression(ExpressionType.NegateChecked, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.NegateChecked, "op_UnaryNegation", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.NegateChecked, expression, method);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> is null.</exception>
+ ///<exception cref="T:System.InvalidOperationException">The unary not operator is not defined for <paramref name="expression" />.Type.</exception>
+ public static UnaryExpression Not(Expression expression) {
+ return Not(expression, null);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a bitwise complement operation. The implementing method can be specified.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Not" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
+ ///<exception cref="T:System.InvalidOperationException">
+ ///<paramref name="method" /> is null and the unary not operator is not defined for <paramref name="expression" />.Type.-or-<paramref name="expression" />.Type (or its corresponding non-nullable type if it is a nullable value type) is not assignable to the argument type of the method represented by <paramref name="method" />.</exception>
+ public static UnaryExpression Not(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsIntegerOrBool(expression.Type)) {
+ return new UnaryExpression(ExpressionType.Not, expression, expression.Type, null);
+ }
+ UnaryExpression u = GetUserDefinedUnaryOperator(ExpressionType.Not, "op_LogicalNot", expression);
+ if (u != null) {
+ return u;
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Not, "op_OnesComplement", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.Not, expression, method);
+ }
+
+ /// <summary>
+ /// Returns whether the expression evaluates to false.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression IsFalse(Expression expression) {
+ return IsFalse(expression, null);
+ }
+
+ /// <summary>
+ /// Returns whether the expression evaluates to false.
+ /// </summary>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression IsFalse(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsBool(expression.Type)) {
+ return new UnaryExpression(ExpressionType.IsFalse, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsFalse, "op_False", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.IsFalse, expression, method);
+ }
+
+ /// <summary>
+ /// Returns whether the expression evaluates to true.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression IsTrue(Expression expression) {
+ return IsTrue(expression, null);
+ }
+
+ /// <summary>
+ /// Returns whether the expression evaluates to true.
+ /// </summary>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to evaluate.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression IsTrue(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsBool(expression.Type)) {
+ return new UnaryExpression(ExpressionType.IsTrue, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.IsTrue, "op_True", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.IsTrue, expression, method);
+ }
+
+ /// <summary>
+ /// Returns the expression representing the ones complement.
+ /// </summary>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression OnesComplement(Expression expression) {
+ return OnesComplement(expression, null);
+ }
+
+ /// <summary>
+ /// Returns the expression representing the ones complement.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
+ /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression OnesComplement(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsInteger(expression.Type)) {
+ return new UnaryExpression(ExpressionType.OnesComplement, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.OnesComplement, "op_OnesComplement", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.OnesComplement, expression, method);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an explicit reference or boxing conversion where null is supplied if the conversion fails.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.TypeAs" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
+ public static UnaryExpression TypeAs(Expression expression, Type type) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+ TypeUtils.ValidateType(type);
+
+ if (type.IsValueType && !TypeUtils.IsNullableType(type)) {
+ throw Error.IncorrectTypeForTypeAs(type);
+ }
+ return new UnaryExpression(ExpressionType.TypeAs, expression, type, null);
+ }
+
+ /// <summary>
+ /// <summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an explicit unboxing.</summary>
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to unbox.</param>
+ /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
+ /// <returns>An instance of <see cref="UnaryExpression"/>.</returns>
+ public static UnaryExpression Unbox(Expression expression, Type type) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.Requires(
+ expression.Type.IsInterface || expression.Type == typeof(object),
+ "expression", Strings.InvalidUnboxType
+ );
+ ContractUtils.Requires(type.IsValueType, "type", Strings.InvalidUnboxType);
+ TypeUtils.ValidateType(type);
+ return new UnaryExpression(ExpressionType.Unbox, expression, type, null);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
+ ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
+ public static UnaryExpression Convert(Expression expression, Type type) {
+ return Convert(expression, type, null);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation for which the implementing method is specified.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Convert" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:Microsoft.Linq.Expressions.Expression.Type" />, and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
+ ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
+ ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception>
+ public static UnaryExpression Convert(Expression expression, Type type, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+ TypeUtils.ValidateType(type);
+
+ if (method == null) {
+ if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type) ||
+ TypeUtils.HasReferenceConversion(expression.Type, type)) {
+ return new UnaryExpression(ExpressionType.Convert, expression, type, null);
+ }
+ return GetUserDefinedCoercionOrThrow(ExpressionType.Convert, expression, type);
+ }
+ return GetMethodBasedCoercionOperator(ExpressionType.Convert, expression, type, method);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
+ ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.</exception>
+ public static UnaryExpression ConvertChecked(Expression expression, Type type) {
+ return ConvertChecked(expression, type, null);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a conversion operation that throws an exception if the target type is overflowed and for which the implementing method is specified.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" />, <see cref="P:Microsoft.Linq.Expressions.Expression.Type" />, and <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> properties set to the specified values.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<param name="type">A <see cref="T:System.Type" /> to set the <see cref="P:Microsoft.Linq.Expressions.Expression.Type" /> property equal to.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Method" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> or <paramref name="type" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="method" /> is not null and the method it represents returns void, is not static (Shared in Visual Basic), or does not take exactly one argument.</exception>
+ ///<exception cref="T:System.Reflection.AmbiguousMatchException">More than one method that matches the <paramref name="method" /> description was found.</exception>
+ ///<exception cref="T:System.InvalidOperationException">No conversion operator is defined between <paramref name="expression" />.Type and <paramref name="type" />.-or-<paramref name="expression" />.Type is not assignable to the argument type of the method represented by <paramref name="method" />.-or-The return type of the method represented by <paramref name="method" /> is not assignable to <paramref name="type" />.-or-<paramref name="expression" />.Type or <paramref name="type" /> is a nullable value type and the corresponding non-nullable value type does not equal the argument type or the return type, respectively, of the method represented by <paramref name="method" />.</exception>
+ public static UnaryExpression ConvertChecked(Expression expression, Type type, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.RequiresNotNull(type, "type");
+ TypeUtils.ValidateType(type);
+
+ if (method == null) {
+ if (TypeUtils.HasIdentityPrimitiveOrNullableConversion(expression.Type, type)) {
+ return new UnaryExpression(ExpressionType.ConvertChecked, expression, type, null);
+ }
+ if (TypeUtils.HasReferenceConversion(expression.Type, type)) {
+ return new UnaryExpression(ExpressionType.Convert, expression, type, null);
+ }
+ return GetUserDefinedCoercionOrThrow(ExpressionType.ConvertChecked, expression, type);
+ }
+ return GetMethodBasedCoercionOperator(ExpressionType.ConvertChecked, expression, type, method);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents getting the length of a one-dimensional array.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.ArrayLength" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to <paramref name="array" />.</returns>
+ ///<param name="array">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="array" /> is null.</exception>
+ ///<exception cref="T:System.ArgumentException">
+ ///<paramref name="array" />.Type does not represent an array type.</exception>
+ public static UnaryExpression ArrayLength(Expression array) {
+ ContractUtils.RequiresNotNull(array, "array");
+ if (!array.Type.IsArray || !typeof(Array).IsAssignableFrom(array.Type)) {
+ throw Error.ArgumentMustBeArray();
+ }
+ if (array.Type.GetArrayRank() != 1) {
+ throw Error.ArgumentMustBeSingleDimensionalArrayType();
+ }
+ return new UnaryExpression(ExpressionType.ArrayLength, array, typeof(int), null);
+ }
+
+ ///<summary>Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents an expression that has a constant value of type <see cref="T:Microsoft.Linq.Expressions.Expression" />.</summary>
+ ///<returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that has the <see cref="P:Microsoft.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:Microsoft.Linq.Expressions.ExpressionType.Quote" /> and the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property set to the specified value.</returns>
+ ///<param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression" /> to set the <see cref="P:Microsoft.Linq.Expressions.UnaryExpression.Operand" /> property equal to.</param>
+ ///<exception cref="T:System.ArgumentNullException">
+ ///<paramref name="expression" /> is null.</exception>
+ public static UnaryExpression Quote(Expression expression) {
+ RequiresCanRead(expression, "expression");
+ ContractUtils.Requires(expression is LambdaExpression, Strings.QuotedExpressionMustBeLambda);
+ return new UnaryExpression(ExpressionType.Quote, expression, expression.GetType(), null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception.
+ /// </summary>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
+ public static UnaryExpression Rethrow() {
+ return Throw(null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a rethrowing of an exception with a given type.
+ /// </summary>
+ ///<param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents a rethrowing of an exception.</returns>
+ public static UnaryExpression Rethrow(Type type) {
+ return Throw(null, type);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a throwing of an exception.
+ /// </summary>
+ /// <param name="value">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
+ public static UnaryExpression Throw(Expression value) {
+ return Throw(value, typeof(void));
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents a throwing of a value with a given type.
+ /// </summary>
+ /// <param name="value">An <see cref="T:Microsoft.Linq.Expressions.Expression" />.</param>
+ /// <param name="type">The new <see cref="T:System.Type" /> of the expression.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the exception.</returns>
+ public static UnaryExpression Throw(Expression value, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+ TypeUtils.ValidateType(type);
+
+ if (value != null) {
+ RequiresCanRead(value, "value");
+ ContractUtils.Requires(!value.Type.IsValueType, "value", Strings.ArgumentMustNotHaveValueType);
+ }
+ return new UnaryExpression(ExpressionType.Throw, value, type, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to increment.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
+ public static UnaryExpression Increment(Expression expression) {
+ return Increment(expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the incrementing of the expression by 1.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to increment.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the incremented expression.</returns>
+ public static UnaryExpression Increment(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsArithmetic(expression.Type)) {
+ return new UnaryExpression(ExpressionType.Increment, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Increment, "op_Increment", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.Increment, expression, method);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to decrement.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
+ public static UnaryExpression Decrement(Expression expression) {
+ return Decrement(expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:Microsoft.Linq.Expressions.UnaryExpression" /> that represents the decrementing of the expression by 1.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to decrement.</param>
+ ///<param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the decremented expression.</returns>
+ public static UnaryExpression Decrement(Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ if (method == null) {
+ if (TypeUtils.IsArithmetic(expression.Type)) {
+ return new UnaryExpression(ExpressionType.Decrement, expression, expression.Type, null);
+ }
+ return GetUserDefinedUnaryOperatorOrThrow(ExpressionType.Decrement, "op_Decrement", expression);
+ }
+ return GetMethodBasedUnaryOperator(ExpressionType.Decrement, expression, method);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
+ /// and assigns the result back to the expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PreIncrementAssign(Expression expression) {
+ return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, null);
+
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that increments the expression by 1
+ /// and assigns the result back to the expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PreIncrementAssign(Expression expression, MethodInfo method) {
+ return MakeOpAssignUnary(ExpressionType.PreIncrementAssign, expression, method);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
+ /// and assigns the result back to the expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PreDecrementAssign(Expression expression) {
+ return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that decrements the expression by 1
+ /// and assigns the result back to the expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PreDecrementAssign(Expression expression, MethodInfo method) {
+ return MakeOpAssignUnary(ExpressionType.PreDecrementAssign, expression, method);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
+ /// followed by a subsequent increment by 1 of the original expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PostIncrementAssign(Expression expression) {
+ return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
+ /// followed by a subsequent increment by 1 of the original expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PostIncrementAssign(Expression expression, MethodInfo method) {
+ return MakeOpAssignUnary(ExpressionType.PostIncrementAssign, expression, method);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
+ /// followed by a subsequent decrement by 1 of the original expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PostDecrementAssign(Expression expression) {
+ return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, null);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="UnaryExpression"/> that represents the assignment of the expression
+ /// followed by a subsequent decrement by 1 of the original expression.
+ /// </summary>
+ /// <param name="expression">An <see cref="T:Microsoft.Linq.Expressions.Expression"></see> to apply the operations on.</param>
+ /// <param name="method">A <see cref="T:System.Reflection.MethodInfo" /> that represents the implementing method.</param>
+ /// <returns>A <see cref="T:Microsoft.Linq.Expressions.UnaryExpression"/> that represents the resultant expression.</returns>
+ public static UnaryExpression PostDecrementAssign(Expression expression, MethodInfo method) {
+ return MakeOpAssignUnary(ExpressionType.PostDecrementAssign, expression, method);
+ }
+
+ private static UnaryExpression MakeOpAssignUnary(ExpressionType kind, Expression expression, MethodInfo method) {
+ RequiresCanRead(expression, "expression");
+ RequiresCanWrite(expression, "expression");
+
+ UnaryExpression result;
+ if (method == null) {
+ if (TypeUtils.IsArithmetic(expression.Type)) {
+ return new UnaryExpression(kind, expression, expression.Type, null);
+ }
+ string name;
+ if (kind == ExpressionType.PreIncrementAssign || kind == ExpressionType.PostIncrementAssign) {
+ name = "op_Increment";
+ } else {
+ name = "op_Decrement";
+ }
+ result = GetUserDefinedUnaryOperatorOrThrow(kind, name, expression);
+ } else {
+ result = GetMethodBasedUnaryOperator(kind, expression, method);
+ }
+ // return type must be assignable back to the operand type
+ if (!TypeUtils.AreReferenceAssignable(expression.Type, result.Type)) {
+ throw Error.UserDefinedOpMustHaveValidReturnType(kind, method.Name);
+ }
+ return result;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AnalyzedTree.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AnalyzedTree.cs
new file mode 100644
index 00000000000..13a09fddbb7
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AnalyzedTree.cs
@@ -0,0 +1,47 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.SymbolStore;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ internal sealed class AnalyzedTree {
+ internal readonly Dictionary<object, CompilerScope> Scopes = new Dictionary<object, CompilerScope>();
+ internal readonly Dictionary<LambdaExpression, BoundConstants> Constants = new Dictionary<LambdaExpression, BoundConstants>();
+
+ internal DebugInfoGenerator DebugInfoGenerator { get; set; }
+
+ // Created by VariableBinder
+ internal AnalyzedTree() {
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AssemblyGen.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AssemblyGen.cs
new file mode 100644
index 00000000000..750425c21a9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/AssemblyGen.cs
@@ -0,0 +1,184 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Security;
+using System.Text;
+using System.Threading;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ internal sealed class AssemblyGen {
+ private static AssemblyGen _assembly;
+
+ // Testing options. Only ever set in MICROSOFT_SCRIPTING_CORE build
+ // configurations, see SetSaveAssemblies
+#if MICROSOFT_SCRIPTING_CORE
+ private static string _saveAssembliesPath;
+ private static bool _saveAssemblies;
+#endif
+
+ private readonly AssemblyBuilder _myAssembly;
+ private readonly ModuleBuilder _myModule;
+
+#if MICROSOFT_SCRIPTING_CORE && !SILVERLIGHT
+ private readonly string _outFileName; // can be null iff !SaveAndReloadAssemblies
+ private readonly string _outDir; // null means the current directory
+#endif
+ private int _index;
+
+ private static AssemblyGen Assembly {
+ get {
+ if (_assembly == null) {
+ Interlocked.CompareExchange(ref _assembly, new AssemblyGen(), null);
+ }
+ return _assembly;
+ }
+ }
+
+ private AssemblyGen() {
+ var name = new AssemblyName("Snippets");
+
+#if SILVERLIGHT // AssemblyBuilderAccess.RunAndSave, Environment.CurrentDirectory
+ _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
+ _myModule = _myAssembly.DefineDynamicModule(name.Name, false);
+#else
+
+ // mark the assembly transparent so that it works in partial trust:
+ var attributes = new[] {
+ new CustomAttributeBuilder(typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes), new object[0])
+ };
+
+#if MICROSOFT_SCRIPTING_CORE
+ if (_saveAssemblies) {
+ string outDir = _saveAssembliesPath ?? Directory.GetCurrentDirectory();
+ try {
+ outDir = Path.GetFullPath(outDir);
+ } catch (Exception) {
+ throw Error.InvalidOutputDir();
+ }
+ try {
+ Path.Combine(outDir, name.Name + ".dll");
+ } catch (ArgumentException) {
+ throw Error.InvalidAsmNameOrExtension();
+ }
+
+ _outFileName = name.Name + ".dll";
+ _outDir = outDir;
+ _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, outDir,
+ null, null, null, null, false, attributes);
+
+ _myModule = _myAssembly.DefineDynamicModule(name.Name, _outFileName, false);
+ } else
+#endif
+ {
+ _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run, attributes);
+ _myModule = _myAssembly.DefineDynamicModule(name.Name, false);
+ }
+
+ _myAssembly.DefineVersionInfoResource();
+#endif
+ }
+
+ private TypeBuilder DefineType(string name, Type parent, TypeAttributes attr) {
+ ContractUtils.RequiresNotNull(name, "name");
+ ContractUtils.RequiresNotNull(parent, "parent");
+
+ StringBuilder sb = new StringBuilder(name);
+
+ int index = Interlocked.Increment(ref _index);
+ sb.Append("$");
+ sb.Append(index);
+
+ // There is a bug in Reflection.Emit that leads to
+ // Unhandled Exception: System.Runtime.InteropServices.COMException (0x80131130): Record not found on lookup.
+ // if there is any of the characters []*&+,\ in the type name and a method defined on the type is called.
+ sb.Replace('+', '_').Replace('[', '_').Replace(']', '_').Replace('*', '_').Replace('&', '_').Replace(',', '_').Replace('\\', '_');
+
+ name = sb.ToString();
+
+ return _myModule.DefineType(name, attr, parent);
+ }
+
+ internal static TypeBuilder DefineDelegateType(string name) {
+ return Assembly.DefineType(
+ name,
+ typeof(MulticastDelegate),
+ TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass
+ );
+ }
+
+#if MICROSOFT_SCRIPTING_CORE
+ //Return the location of the saved assembly file.
+ //The file location is used by PE verification in Microsoft.Scripting.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal string SaveAssembly() {
+#if !SILVERLIGHT // AssemblyBuilder.Save
+ _myAssembly.Save(_outFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
+ return Path.Combine(_outDir, _outFileName);
+#else
+ return null;
+#endif
+ }
+
+ // NOTE: this method is called through reflection from Microsoft.Scripting
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal static void SetSaveAssemblies(bool enable, string directory) {
+ _saveAssemblies = enable;
+ _saveAssembliesPath = directory;
+ }
+
+ // NOTE: this method is called through reflection from Microsoft.Scripting
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal static string[] SaveAssembliesToDisk() {
+ if (!_saveAssemblies) {
+ return new string[0];
+ }
+
+ var assemlyLocations = new List<string>();
+
+ // first save all assemblies to disk:
+ if (_assembly != null) {
+ string assemblyLocation = _assembly.SaveAssembly();
+ if (assemblyLocation != null) {
+ assemlyLocations.Add(assemblyLocation);
+ }
+ _assembly = null;
+ }
+
+ return assemlyLocations.ToArray();
+ }
+#endif
+ }
+
+ internal static class SymbolGuids {
+ internal static readonly Guid DocumentType_Text =
+ new Guid(0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0, 0, 0xf8, 8, 0x49, 0xbd);
+ }
+}
+
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/BoundConstants.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/BoundConstants.cs
new file mode 100644
index 00000000000..9893c6ff726
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/BoundConstants.cs
@@ -0,0 +1,193 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ /// <summary>
+ /// This type tracks "runtime" constants--live objects that appear in
+ /// ConstantExpression nodes and must be bound to the delegate.
+ /// </summary>
+ internal sealed class BoundConstants {
+
+ /// <summary>
+ /// Constants can emit themselves as different types
+ /// For caching purposes, we need to treat each distinct Type as a
+ /// seperate thing to cache. (If we have to cast it on the way out, it
+ /// ends up using a JIT temp and defeats the purpose of caching the
+ /// value in a local)
+ /// </summary>
+ private struct TypedConstant : IEquatable<TypedConstant> {
+ internal readonly object Value;
+ internal readonly Type Type;
+
+ internal TypedConstant(object value, Type type) {
+ Value = value;
+ Type = type;
+ }
+
+ public override int GetHashCode() {
+ return RuntimeHelpers.GetHashCode(Value) ^ Type.GetHashCode();
+ }
+ public bool Equals(TypedConstant other) {
+ return object.ReferenceEquals(Value, other.Value) && Type.Equals(other.Type);
+ }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2231:OverloadOperatorEqualsOnOverridingValueTypeEquals")]
+ public override bool Equals(object obj) {
+ return (obj is TypedConstant) && Equals((TypedConstant)obj);
+ }
+ }
+
+ /// <summary>
+ /// The list of constants in the order they appear in the constant array
+ /// </summary>
+ private readonly List<object> _values = new List<object>();
+
+ /// <summary>
+ /// The index of each constant in the constant array
+ /// </summary>
+ private readonly Dictionary<object, int> _indexes = new Dictionary<object, int>(ReferenceEqualityComparer<object>.Instance);
+
+ /// <summary>
+ /// Each constant referenced within this lambda, and how often it was referenced
+ /// </summary>
+ private readonly Dictionary<TypedConstant, int> _references = new Dictionary<TypedConstant, int>();
+
+ /// <summary>
+ /// IL locals for storing frequently used constants
+ /// </summary>
+ private readonly Dictionary<TypedConstant, LocalBuilder> _cache = new Dictionary<TypedConstant, LocalBuilder>();
+
+ internal int Count {
+ get { return _values.Count; }
+ }
+
+ internal object[] ToArray() {
+ return _values.ToArray();
+ }
+
+ /// <summary>
+ /// Called by VariableBinder. Adds the constant to the list (if needed)
+ /// and increases the reference count by one
+ /// </summary>
+ internal void AddReference(object value, Type type) {
+ if (!_indexes.ContainsKey(value)) {
+ _indexes.Add(value, _values.Count);
+ _values.Add(value);
+ }
+ Helpers.IncrementCount(new TypedConstant(value, type), _references);
+ }
+
+ /// <summary>
+ /// Emits a live object as a constant
+ /// </summary>
+ internal void EmitConstant(LambdaCompiler lc, object value, Type type) {
+ Debug.Assert(!ILGen.CanEmitConstant(value, type));
+
+ if (!lc.CanEmitBoundConstants) {
+ throw Error.CannotCompileConstant(value);
+ }
+
+ LocalBuilder local;
+ if (_cache.TryGetValue(new TypedConstant(value, type), out local)) {
+ lc.IL.Emit(OpCodes.Ldloc, local);
+ return;
+ }
+ EmitConstantsArray(lc);
+ EmitConstantFromArray(lc, value, type);
+ }
+
+ /// <summary>
+ /// Emit code to cache frequently used constants into IL locals,
+ /// instead of pulling them out of the array each time
+ /// </summary>
+ internal void EmitCacheConstants(LambdaCompiler lc) {
+ int count = 0;
+ foreach (var reference in _references) {
+ if (!lc.CanEmitBoundConstants) {
+ throw Error.CannotCompileConstant(reference.Value);
+ }
+
+ if (ShouldCache(reference.Value)) {
+ count++;
+ }
+ }
+ if (count == 0) {
+ return;
+ }
+ EmitConstantsArray(lc);
+ foreach (var reference in _references) {
+ if (ShouldCache(reference.Value)) {
+ if (--count > 0) {
+ // Dup array to keep it on the stack
+ lc.IL.Emit(OpCodes.Dup);
+ }
+ LocalBuilder local = lc.IL.DeclareLocal(reference.Key.Type);
+ EmitConstantFromArray(lc, reference.Key.Value, local.LocalType);
+ lc.IL.Emit(OpCodes.Stloc, local);
+ _cache.Add(reference.Key, local);
+ }
+ }
+ }
+
+ private static bool ShouldCache(int refCount) {
+ // This caching is too aggressive in the face of conditionals and
+ // switch. Also, it is too conservative for variables used inside
+ // of loops.
+ return refCount > 2;
+ }
+
+ private static void EmitConstantsArray(LambdaCompiler lc) {
+ Debug.Assert(lc.CanEmitBoundConstants); // this should've been checked already
+
+ lc.EmitClosureArgument();
+ lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Constants"));
+ }
+
+ private void EmitConstantFromArray(LambdaCompiler lc, object value, Type type) {
+ int index;
+ if (!_indexes.TryGetValue(value, out index)) {
+ _indexes.Add(value, index = _values.Count);
+ _values.Add(value);
+ }
+
+ lc.IL.EmitInt(index);
+ lc.IL.Emit(OpCodes.Ldelem_Ref);
+ if (type.IsValueType) {
+ lc.IL.Emit(OpCodes.Unbox_Any, type);
+ } else if (type != typeof(object)) {
+ lc.IL.Emit(OpCodes.Castclass, type);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Closure.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Closure.cs
new file mode 100644
index 00000000000..58c8b375a55
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Closure.cs
@@ -0,0 +1,57 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.ComponentModel;
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+
+ /// <summary>
+ /// This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+ /// Represents the runtime state of a dynamically generated method.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never), DebuggerStepThrough]
+ public sealed class Closure {
+ /// <summary>
+ /// Represents the non-trivial constants and locally executable expressions that are referenced by a dynamically generated method.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
+ public readonly object[] Constants;
+
+ /// <summary>
+ /// Represents the hoisted local variables from the parent context.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
+ public readonly object[] Locals;
+
+ /// <summary>
+ /// Creates an object to hold state of a dynamically generated method.
+ /// </summary>
+ /// <param name="constants">The constant values used by the method.</param>
+ /// <param name="locals">The hoisted local variables from the parent context.</param>
+ public Closure(object[] constants, object[] locals) {
+ Constants = constants;
+ Locals = locals;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.Storage.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.Storage.cs
new file mode 100644
index 00000000000..0e348c26967
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.Storage.cs
@@ -0,0 +1,191 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ internal sealed partial class CompilerScope {
+
+ private abstract class Storage {
+ internal readonly LambdaCompiler Compiler;
+ internal readonly ParameterExpression Variable;
+
+ internal Storage(LambdaCompiler compiler, ParameterExpression variable) {
+ Compiler = compiler;
+ Variable = variable;
+ }
+
+ internal abstract void EmitLoad();
+ internal abstract void EmitAddress();
+ internal abstract void EmitStore();
+
+ internal virtual void EmitStore(Storage value) {
+ value.EmitLoad();
+ EmitStore();
+ }
+
+ internal virtual void FreeLocal() {
+ }
+ }
+
+ private sealed class LocalStorage : Storage {
+ private readonly LocalBuilder _local;
+
+ internal LocalStorage(LambdaCompiler compiler, ParameterExpression variable)
+ : base(compiler, variable) {
+ // ByRef variables are supported. This is used internally by
+ // the compiler when emitting an inlined lambda invoke, to
+ // handle ByRef parameters. BlockExpression prevents this
+ // from being exposed to user created trees.
+ _local = compiler.GetNamedLocal(variable.IsByRef ? variable.Type.MakeByRefType() : variable.Type, variable);
+ }
+
+ internal override void EmitLoad() {
+ Compiler.IL.Emit(OpCodes.Ldloc, _local);
+ }
+
+ internal override void EmitStore() {
+ Compiler.IL.Emit(OpCodes.Stloc, _local);
+ }
+
+ internal override void EmitAddress() {
+ Compiler.IL.Emit(OpCodes.Ldloca, _local);
+ }
+ }
+
+ private sealed class ArgumentStorage : Storage {
+ private readonly int _argument;
+
+ internal ArgumentStorage(LambdaCompiler compiler, ParameterExpression p)
+ : base(compiler, p) {
+ _argument = compiler.GetLambdaArgument(compiler.Parameters.IndexOf(p));
+ }
+
+ internal override void EmitLoad() {
+ Compiler.IL.EmitLoadArg(_argument);
+ }
+
+ internal override void EmitStore() {
+ Compiler.IL.EmitStoreArg(_argument);
+ }
+
+ internal override void EmitAddress() {
+ Compiler.IL.EmitLoadArgAddress(_argument);
+ }
+ }
+
+ private sealed class ElementBoxStorage : Storage {
+ private readonly int _index;
+ private readonly Storage _array;
+ private readonly Type _boxType;
+ private readonly FieldInfo _boxValueField;
+
+ internal ElementBoxStorage(Storage array, int index, ParameterExpression variable)
+ : base(array.Compiler, variable) {
+ _array = array;
+ _index = index;
+ _boxType = typeof(StrongBox<>).MakeGenericType(variable.Type);
+ _boxValueField = _boxType.GetField("Value");
+ }
+
+ internal override void EmitLoad() {
+ EmitLoadBox();
+ Compiler.IL.Emit(OpCodes.Ldfld, _boxValueField);
+ }
+
+ internal override void EmitStore() {
+ LocalBuilder value = Compiler.GetLocal(Variable.Type);
+ Compiler.IL.Emit(OpCodes.Stloc, value);
+ EmitLoadBox();
+ Compiler.IL.Emit(OpCodes.Ldloc, value);
+ Compiler.FreeLocal(value);
+ Compiler.IL.Emit(OpCodes.Stfld, _boxValueField);
+ }
+
+ internal override void EmitStore(Storage value) {
+ EmitLoadBox();
+ value.EmitLoad();
+ Compiler.IL.Emit(OpCodes.Stfld, _boxValueField);
+ }
+
+ internal override void EmitAddress() {
+ EmitLoadBox();
+ Compiler.IL.Emit(OpCodes.Ldflda, _boxValueField);
+ }
+
+ internal void EmitLoadBox() {
+ _array.EmitLoad();
+ Compiler.IL.EmitInt(_index);
+ Compiler.IL.Emit(OpCodes.Ldelem_Ref);
+ Compiler.IL.Emit(OpCodes.Castclass, _boxType);
+ }
+ }
+
+ private sealed class LocalBoxStorage : Storage {
+ private readonly LocalBuilder _boxLocal;
+ private readonly Type _boxType;
+ private readonly FieldInfo _boxValueField;
+
+ internal LocalBoxStorage(LambdaCompiler compiler, ParameterExpression variable)
+ : base(compiler, variable) {
+ _boxType = typeof(StrongBox<>).MakeGenericType(variable.Type);
+ _boxValueField = _boxType.GetField("Value");
+ _boxLocal = compiler.GetNamedLocal(_boxType, variable);
+ }
+
+ internal override void EmitLoad() {
+ Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal);
+ Compiler.IL.Emit(OpCodes.Ldfld, _boxValueField);
+ }
+
+ internal override void EmitAddress() {
+ Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal);
+ Compiler.IL.Emit(OpCodes.Ldflda, _boxValueField);
+ }
+
+ internal override void EmitStore() {
+ LocalBuilder value = Compiler.GetLocal(Variable.Type);
+ Compiler.IL.Emit(OpCodes.Stloc, value);
+ Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal);
+ Compiler.IL.Emit(OpCodes.Ldloc, value);
+ Compiler.FreeLocal(value);
+ Compiler.IL.Emit(OpCodes.Stfld, _boxValueField);
+ }
+
+ internal override void EmitStore(Storage value) {
+ Compiler.IL.Emit(OpCodes.Ldloc, _boxLocal);
+ value.EmitLoad();
+ Compiler.IL.Emit(OpCodes.Stfld, _boxValueField);
+ }
+
+ internal void EmitStoreBox() {
+ Compiler.IL.Emit(OpCodes.Stloc, _boxLocal);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.cs
new file mode 100644
index 00000000000..c0faaa933b7
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/CompilerScope.cs
@@ -0,0 +1,468 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ internal enum VariableStorageKind {
+ Local,
+ Hoisted
+ }
+
+ /// <summary>
+ /// CompilerScope is the data structure which the Compiler keeps information
+ /// related to compiling scopes. It stores the following information:
+ /// 1. Parent relationship (for resolving variables)
+ /// 2. Information about hoisted variables
+ /// 3. Information for resolving closures
+ ///
+ /// Instances are produced by VariableBinder, which does a tree walk
+ /// looking for scope nodes: LambdaExpression and BlockExpression.
+ /// </summary>
+ internal sealed partial class CompilerScope {
+ /// <summary>
+ /// parent scope, if any
+ /// </summary>
+ private CompilerScope _parent;
+
+ /// <summary>
+ /// The expression node for this scope
+ /// Can be LambdaExpression, BlockExpression, or CatchBlock
+ /// </summary>
+ internal readonly object Node;
+
+ /// <summary>
+ /// True if this node corresponds to an IL method.
+ /// Can only be true if the Node is a LambdaExpression.
+ /// But inlined lambdas will have it set to false.
+ /// </summary>
+ internal readonly bool IsMethod;
+
+ /// <summary>
+ /// Does this scope (or any inner scope) close over variables from any
+ /// parent scope?
+ /// Populated by VariableBinder
+ /// </summary>
+ internal bool NeedsClosure;
+
+ /// <summary>
+ /// Variables defined in this scope, and whether they're hoisted or not
+ /// Populated by VariableBinder
+ /// </summary>
+ internal readonly Dictionary<ParameterExpression, VariableStorageKind> Definitions = new Dictionary<ParameterExpression, VariableStorageKind>();
+
+ /// <summary>
+ /// Each variable referenced within this scope, and how often it was referenced
+ /// Populated by VariableBinder
+ /// </summary>
+ internal Dictionary<ParameterExpression, int> ReferenceCount;
+
+ /// <summary>
+ /// Scopes whose variables were merged into this one
+ ///
+ /// Created lazily as we create hundreds of compiler scopes w/o merging scopes when compiling rules.
+ /// </summary>
+ internal Set<object> MergedScopes;
+
+ /// <summary>
+ /// The scope's hoisted locals, if any.
+ /// Provides storage for variables that are referenced from nested lambdas
+ /// </summary>
+ private HoistedLocals _hoistedLocals;
+
+ /// <summary>
+ /// The closed over hoisted locals
+ /// </summary>
+ private HoistedLocals _closureHoistedLocals;
+
+ /// <summary>
+ /// Mutable dictionary that maps non-hoisted variables to either local
+ /// slots or argument slots
+ /// </summary>
+ private readonly Dictionary<ParameterExpression, Storage> _locals = new Dictionary<ParameterExpression, Storage>();
+
+ internal CompilerScope(object node, bool isMethod) {
+ Node = node;
+ IsMethod = isMethod;
+ var variables = GetVariables(node);
+
+ Definitions = new Dictionary<ParameterExpression, VariableStorageKind>(variables.Count);
+ foreach (var v in variables) {
+ Definitions.Add(v, VariableStorageKind.Local);
+ }
+ }
+
+ /// <summary>
+ /// This scope's hoisted locals, or the closed over locals, if any
+ /// Equivalent to: _hoistedLocals ?? _closureHoistedLocals
+ /// </summary>
+ internal HoistedLocals NearestHoistedLocals {
+ get { return _hoistedLocals ?? _closureHoistedLocals; }
+ }
+
+ /// <summary>
+ /// Called when entering a lambda/block. Performs all variable allocation
+ /// needed, including creating hoisted locals and IL locals for accessing
+ /// parent locals
+ /// </summary>
+ internal CompilerScope Enter(LambdaCompiler lc, CompilerScope parent) {
+ SetParent(lc, parent);
+
+ AllocateLocals(lc);
+
+ if (IsMethod && _closureHoistedLocals != null) {
+ EmitClosureAccess(lc, _closureHoistedLocals);
+ }
+
+ EmitNewHoistedLocals(lc);
+
+ if (IsMethod) {
+ EmitCachedVariables();
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Frees unnamed locals, clears state associated with this compiler
+ /// </summary>
+ internal CompilerScope Exit() {
+ // free scope's variables
+ if (!IsMethod) {
+ foreach (Storage storage in _locals.Values) {
+ storage.FreeLocal();
+ }
+ }
+
+ // Clear state that is associated with this parent
+ // (because the scope can be reused in another context)
+ CompilerScope parent = _parent;
+ _parent = null;
+ _hoistedLocals = null;
+ _closureHoistedLocals = null;
+ _locals.Clear();
+
+ return parent;
+ }
+
+ #region LocalScopeExpression support
+
+ internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection<ParameterExpression> vars) {
+ if (NearestHoistedLocals != null) {
+ // Find what array each variable is on & its index
+ var indexes = new List<long>(vars.Count);
+
+ foreach (var variable in vars) {
+ // For each variable, find what array it's defined on
+ ulong parents = 0;
+ HoistedLocals locals = NearestHoistedLocals;
+ while (!locals.Indexes.ContainsKey(variable)) {
+ parents++;
+ locals = locals.Parent;
+ Debug.Assert(locals != null);
+ }
+
+ // combine the number of parents we walked, with the
+ // real index of variable to get the index to emit.
+ ulong index = (parents << 32) | (uint)locals.Indexes[variable];
+
+ indexes.Add((long)index);
+ }
+
+ if (indexes.Count > 0) {
+ EmitGet(NearestHoistedLocals.SelfVariable);
+ lc.EmitConstantArray(indexes.ToArray());
+ lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new[] { typeof(object[]), typeof(long[]) }));
+ return;
+ }
+ }
+
+ // No visible variables
+ lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes));
+ return;
+ }
+
+ #endregion
+
+ #region Variable access
+
+ /// <summary>
+ /// Adds a new virtual variable corresponding to an IL local
+ /// </summary>
+ internal void AddLocal(LambdaCompiler gen, ParameterExpression variable) {
+ _locals.Add(variable, new LocalStorage(gen, variable));
+ }
+
+ internal void EmitGet(ParameterExpression variable) {
+ ResolveVariable(variable).EmitLoad();
+ }
+
+ internal void EmitSet(ParameterExpression variable) {
+ ResolveVariable(variable).EmitStore();
+ }
+
+ internal void EmitAddressOf(ParameterExpression variable) {
+ ResolveVariable(variable).EmitAddress();
+ }
+
+ private Storage ResolveVariable(ParameterExpression variable) {
+ return ResolveVariable(variable, NearestHoistedLocals);
+ }
+
+ /// <summary>
+ /// Resolve a local variable in this scope or a closed over scope
+ /// Throws if the variable is defined
+ /// </summary>
+ private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) {
+ // Search IL locals and arguments, but only in this lambda
+ for (CompilerScope s = this; s != null; s = s._parent) {
+ Storage storage;
+ if (s._locals.TryGetValue(variable, out storage)) {
+ return storage;
+ }
+
+ // if this is a lambda, we're done
+ if (s.IsMethod) {
+ break;
+ }
+ }
+
+ // search hoisted locals
+ for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent) {
+ int index;
+ if (h.Indexes.TryGetValue(variable, out index)) {
+ return new ElementBoxStorage(
+ ResolveVariable(h.SelfVariable, hoistedLocals),
+ index,
+ variable
+ );
+ }
+ }
+
+ //
+ // If this is an unbound variable in the lambda, the error will be
+ // thrown from VariableBinder. So an error here is generally caused
+ // by an internal error, e.g. a scope was created but it bypassed
+ // VariableBinder.
+ //
+ throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName);
+ }
+
+ #endregion
+
+ private void SetParent(LambdaCompiler lc, CompilerScope parent) {
+ Debug.Assert(_parent == null && parent != this);
+ _parent = parent;
+
+ if (NeedsClosure && _parent != null) {
+ _closureHoistedLocals = _parent.NearestHoistedLocals;
+ }
+
+ var hoistedVars = GetVariables().Where(p => Definitions[p] == VariableStorageKind.Hoisted).ToReadOnly();
+
+ if (hoistedVars.Count > 0) {
+ _hoistedLocals = new HoistedLocals(_closureHoistedLocals, hoistedVars);
+ AddLocal(lc, _hoistedLocals.SelfVariable);
+ }
+ }
+
+ // Emits creation of the hoisted local storage
+ private void EmitNewHoistedLocals(LambdaCompiler lc) {
+ if (_hoistedLocals == null) {
+ return;
+ }
+
+ // create the array
+ lc.IL.EmitInt(_hoistedLocals.Variables.Count);
+ lc.IL.Emit(OpCodes.Newarr, typeof(object));
+
+ // initialize all elements
+ int i = 0;
+ foreach (ParameterExpression v in _hoistedLocals.Variables) {
+ // array[i] = new StrongBox<T>(...);
+ lc.IL.Emit(OpCodes.Dup);
+ lc.IL.EmitInt(i++);
+ Type boxType = typeof(StrongBox<>).MakeGenericType(v.Type);
+
+ if (IsMethod && lc.Parameters.Contains(v)) {
+ // array[i] = new StrongBox<T>(argument);
+ int index = lc.Parameters.IndexOf(v);
+ lc.EmitLambdaArgument(index);
+ lc.IL.Emit(OpCodes.Newobj, boxType.GetConstructor(new Type[] { v.Type }));
+ } else if (v == _hoistedLocals.ParentVariable) {
+ // array[i] = new StrongBox<T>(closure.Locals);
+ ResolveVariable(v, _closureHoistedLocals).EmitLoad();
+ lc.IL.Emit(OpCodes.Newobj, boxType.GetConstructor(new Type[] { v.Type }));
+ } else {
+ // array[i] = new StrongBox<T>();
+ lc.IL.Emit(OpCodes.Newobj, boxType.GetConstructor(Type.EmptyTypes));
+ }
+ // if we want to cache this into a local, do it now
+ if (ShouldCache(v)) {
+ lc.IL.Emit(OpCodes.Dup);
+ CacheBoxToLocal(lc, v);
+ }
+ lc.IL.Emit(OpCodes.Stelem_Ref);
+ }
+
+ // store it
+ EmitSet(_hoistedLocals.SelfVariable);
+ }
+
+ // If hoisted variables are referenced "enough", we cache the
+ // StrongBox<T> in an IL local, which saves an array index and a cast
+ // when we go to look it up later
+ private void EmitCachedVariables() {
+ if (ReferenceCount == null) {
+ return;
+ }
+
+ foreach (var refCount in ReferenceCount) {
+ if (ShouldCache(refCount.Key, refCount.Value)) {
+ var storage = ResolveVariable(refCount.Key) as ElementBoxStorage;
+ if (storage != null) {
+ storage.EmitLoadBox();
+ CacheBoxToLocal(storage.Compiler, refCount.Key);
+ }
+ }
+ }
+ }
+
+ private bool ShouldCache(ParameterExpression v, int refCount) {
+ // This caching is too aggressive in the face of conditionals and
+ // switch. Also, it is too conservative for variables used inside
+ // of loops.
+ return refCount > 2 && !_locals.ContainsKey(v);
+ }
+
+ private bool ShouldCache(ParameterExpression v) {
+ if (ReferenceCount == null) {
+ return false;
+ }
+
+ int refCount;
+ return ReferenceCount.TryGetValue(v, out refCount) && ShouldCache(v, refCount);
+ }
+
+ private void CacheBoxToLocal(LambdaCompiler lc, ParameterExpression v) {
+ Debug.Assert(ShouldCache(v) && !_locals.ContainsKey(v));
+ var local = new LocalBoxStorage(lc, v);
+ local.EmitStoreBox();
+ _locals.Add(v, local);
+ }
+
+ // Creates IL locals for accessing closures
+ private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals) {
+ if (locals == null) {
+ return;
+ }
+
+ EmitClosureToVariable(lc, locals);
+
+ while ((locals = locals.Parent) != null) {
+ var v = locals.SelfVariable;
+ var local = new LocalStorage(lc, v);
+ local.EmitStore(ResolveVariable(v));
+ _locals.Add(v, local);
+ }
+ }
+
+ private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals) {
+ lc.EmitClosureArgument();
+ lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Locals"));
+ AddLocal(lc, locals.SelfVariable);
+ EmitSet(locals.SelfVariable);
+ }
+
+ // Allocates slots for IL locals or IL arguments
+ private void AllocateLocals(LambdaCompiler lc) {
+ foreach (ParameterExpression v in GetVariables()) {
+ if (Definitions[v] == VariableStorageKind.Local) {
+ //
+ // If v is in lc.Parameters, it is a parameter.
+ // Otherwise, it is a local variable.
+ //
+ // Also, for inlined lambdas we'll create a local, which
+ // is possibly a byref local if the parameter is byref.
+ //
+ Storage s;
+ if (IsMethod && lc.Parameters.Contains(v)) {
+ s = new ArgumentStorage(lc, v);
+ } else {
+ s = new LocalStorage(lc, v);
+ }
+ _locals.Add(v, s);
+ }
+ }
+ }
+
+ private IList<ParameterExpression> GetVariables() {
+ var vars = GetVariables(Node);
+ if (MergedScopes == null) {
+ return vars;
+ }
+ var list = new List<ParameterExpression>(vars);
+ foreach (var scope in MergedScopes) {
+ list.AddRange(GetVariables(scope));
+ }
+ return list;
+ }
+
+ private static IList<ParameterExpression> GetVariables(object scope) {
+ var lambda = scope as LambdaExpression;
+ if (lambda != null) {
+ return lambda.Parameters;
+ }
+ var block = scope as BlockExpression;
+ if (block != null) {
+ return block.Variables;
+ }
+ return new[] { ((CatchBlock)scope).Variable };
+ }
+
+ private string CurrentLambdaName {
+ get {
+ CompilerScope s = this;
+ while (true) {
+ var lambda = s.Node as LambdaExpression;
+ if (lambda != null) {
+ return lambda.Name;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ConstantCheck.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ConstantCheck.cs
new file mode 100644
index 00000000000..33ae973fb9a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ConstantCheck.cs
@@ -0,0 +1,133 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+ internal enum AnalyzeTypeIsResult {
+ KnownFalse,
+ KnownTrue,
+ KnownAssignable, // need null check only
+ Unknown, // need full runtime check
+ }
+
+ internal static class ConstantCheck {
+
+ internal static bool IsNull(Expression e) {
+ switch (e.NodeType) {
+ case ExpressionType.Constant:
+ return ((ConstantExpression)e).Value == null;
+
+ case ExpressionType.TypeAs:
+ var typeAs = (UnaryExpression)e;
+ // if the TypeAs check is guarenteed to fail, then its result will be null
+ return AnalyzeTypeIs(typeAs) == AnalyzeTypeIsResult.KnownFalse;
+ }
+ return false;
+ }
+
+
+ /// <summary>
+ /// If the result of a TypeBinaryExpression is known statically, this
+ /// returns the result, otherwise it returns null, meaning we'll need
+ /// to perform the IsInst instruction at runtime.
+ ///
+ /// The result of this function must be equivalent to IsInst, or
+ /// null.
+ /// </summary>
+ internal static AnalyzeTypeIsResult AnalyzeTypeIs(TypeBinaryExpression typeIs) {
+ return AnalyzeTypeIs(typeIs.Expression, typeIs.TypeOperand);
+ }
+
+ /// <summary>
+ /// If the result of a unary TypeAs expression is known statically, this
+ /// returns the result, otherwise it returns null, meaning we'll need
+ /// to perform the IsInst instruction at runtime.
+ ///
+ /// The result of this function must be equivalent to IsInst, or
+ /// null.
+ /// </summary>
+ internal static AnalyzeTypeIsResult AnalyzeTypeIs(UnaryExpression typeAs) {
+ Debug.Assert(typeAs.NodeType == ExpressionType.TypeAs);
+ return AnalyzeTypeIs(typeAs.Operand, typeAs.Type);
+ }
+
+ /// <summary>
+ /// If the result of an isinst opcode is known statically, this
+ /// returns the result, otherwise it returns null, meaning we'll need
+ /// to perform the IsInst instruction at runtime.
+ ///
+ /// The result of this function must be equivalent to IsInst, or
+ /// null.
+ /// </summary>
+ private static AnalyzeTypeIsResult AnalyzeTypeIs(Expression operand, Type testType) {
+ Type operandType = operand.Type;
+
+ // Oddly, we allow void operands
+ // This is LinqV1 behavior of TypeIs
+ if (operandType == typeof(void)) {
+ return AnalyzeTypeIsResult.KnownFalse;
+ }
+
+ //
+ // Type comparisons treat nullable types as if they were the
+ // underlying type. The reason is when you box a nullable it
+ // becomes a boxed value of the underlying type, or null.
+ //
+ Type nnOperandType = operandType.GetNonNullableType();
+ Type nnTestType = testType.GetNonNullableType();
+
+ //
+ // See if we can determine the answer based on the static types
+ //
+ // Extensive testing showed that Type.IsAssignableFrom,
+ // Type.IsInstanceOfType, and the isinst instruction were all
+ // equivalent when used against a live object
+ //
+ if (nnTestType.IsAssignableFrom(nnOperandType)) {
+ // If the operand is a value type (other than nullable), we
+ // know the result is always true.
+ if (operandType.IsValueType && !operandType.IsNullableType()) {
+ return AnalyzeTypeIsResult.KnownTrue;
+ }
+
+ // For reference/nullable types, we need to compare to null at runtime
+ return AnalyzeTypeIsResult.KnownAssignable;
+ }
+
+ //
+ // If we couldn't statically assign and the type is sealed, no
+ // value at runtime can make isinst succeed
+ //
+ if (nnOperandType.IsSealed) {
+ return AnalyzeTypeIsResult.KnownFalse;
+ }
+
+ // Otherwise we need a full runtime check
+ return AnalyzeTypeIsResult.Unknown;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs
new file mode 100644
index 00000000000..843b30bd1fe
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DebugInfoGenerator.cs
@@ -0,0 +1,72 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#else
+using ILGenerator = Microsoft.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#endif
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using System.Diagnostics.SymbolStore;
+using System.Reflection;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// Generates debug information for lambdas in an expression tree.
+ /// </summary>
+ public abstract class DebugInfoGenerator {
+ /// <summary>
+ /// Creates PDB symbol generator.
+ /// </summary>
+ /// <returns>PDB symbol generator.</returns>
+ public static DebugInfoGenerator CreatePdbGenerator() {
+ return new SymbolDocumentGenerator();
+ }
+
+ /// <summary>
+ /// Marks a sequence point.
+ /// </summary>
+ /// <param name="method">The lambda being generated.</param>
+ /// <param name="ilOffset">IL offset where to mark the sequence point.</param>
+ /// <param name="sequencePoint">Debug informaton corresponding to the sequence point.</param>
+ public abstract void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression sequencePoint);
+
+ internal virtual void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) {
+ MarkSequencePoint(method, ilg.CurrentOffset, sequencePoint);
+ }
+
+ internal virtual void SetLocalName(LocalBuilder localBuilder, string name) {
+ // nop
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.Generated.cs
new file mode 100644
index 00000000000..7d5528fa924
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.Generated.cs
@@ -0,0 +1,299 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic;
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting;
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ internal static partial class DelegateHelpers {
+ private static TypeInfo _DelegateCache = new TypeInfo();
+
+ #region Generated Maximum Delegate Arity
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_max_delegate_arity from: generate_dynsites.py
+
+ private const int MaximumArity = 17;
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ internal class TypeInfo {
+ public Type DelegateType;
+ public Dictionary<Type, TypeInfo> TypeChain;
+
+ public Type MakeDelegateType(Type retType, params Expression[] args) {
+ return MakeDelegateType(retType, (IList<Expression>)args);
+ }
+
+ public Type MakeDelegateType(Type retType, IList<Expression> args) {
+ // nope, go ahead and create it and spend the
+ // cost of creating the array.
+ Type[] paramTypes = new Type[args.Count + 2];
+ paramTypes[0] = typeof(CallSite);
+ paramTypes[paramTypes.Length - 1] = retType;
+ for (int i = 0; i < args.Count; i++) {
+ paramTypes[i + 1] = args[i].Type;
+ }
+
+ return DelegateType = MakeNewDelegate(paramTypes);
+ }
+ }
+
+
+ /// <summary>
+ /// Finds a delegate type using the types in the array.
+ /// We use the cache to avoid copying the array, and to cache the
+ /// created delegate type
+ /// </summary>
+ internal static Type MakeDelegateType(Type[] types) {
+ lock (_DelegateCache) {
+ TypeInfo curTypeInfo = _DelegateCache;
+
+ // arguments & return type
+ for (int i = 0; i < types.Length; i++) {
+ curTypeInfo = NextTypeInfo(types[i], curTypeInfo);
+ }
+
+ // see if we have the delegate already
+ if (curTypeInfo.DelegateType == null) {
+ // clone because MakeCustomDelegate can hold onto the array.
+ curTypeInfo.DelegateType = MakeNewDelegate((Type[])types.Clone());
+ }
+
+ return curTypeInfo.DelegateType;
+ }
+ }
+
+ /// <summary>
+ /// Finds a delegate type for a CallSite using the types in the ReadOnlyCollection of Expression.
+ ///
+ /// We take the readonly collection of Expression explicitly to avoid allocating memory (an array
+ /// of types) on lookup of delegate types.
+ /// </summary>
+ internal static Type MakeCallSiteDelegate(ReadOnlyCollection<Expression> types, Type returnType) {
+ lock (_DelegateCache) {
+ TypeInfo curTypeInfo = _DelegateCache;
+
+ // CallSite
+ curTypeInfo = NextTypeInfo(typeof(CallSite), curTypeInfo);
+
+ // arguments
+ for (int i = 0; i < types.Count; i++) {
+ curTypeInfo = NextTypeInfo(types[i].Type, curTypeInfo);
+ }
+
+ // return type
+ curTypeInfo = NextTypeInfo(returnType, curTypeInfo);
+
+ // see if we have the delegate already
+ if (curTypeInfo.DelegateType == null) {
+ curTypeInfo.MakeDelegateType(returnType, types);
+ }
+
+ return curTypeInfo.DelegateType;
+ }
+ }
+
+ /// <summary>
+ /// Finds a delegate type for a CallSite using the MetaObject array.
+ ///
+ /// We take the array of MetaObject explicitly to avoid allocating memory (an array of types) on
+ /// lookup of delegate types.
+ /// </summary>
+ internal static Type MakeDeferredSiteDelegate(DynamicMetaObject[] args, Type returnType) {
+ lock (_DelegateCache) {
+ TypeInfo curTypeInfo = _DelegateCache;
+
+ // CallSite
+ curTypeInfo = NextTypeInfo(typeof(CallSite), curTypeInfo);
+
+ // arguments
+ for (int i = 0; i < args.Length; i++) {
+ DynamicMetaObject mo = args[i];
+ Type paramType = mo.Expression.Type;
+ if (IsByRef(mo)) {
+ paramType = paramType.MakeByRefType();
+ }
+ curTypeInfo = NextTypeInfo(paramType, curTypeInfo);
+ }
+
+ // return type
+ curTypeInfo = NextTypeInfo(returnType, curTypeInfo);
+
+ // see if we have the delegate already
+ if (curTypeInfo.DelegateType == null) {
+ // nope, go ahead and create it and spend the
+ // cost of creating the array.
+ Type[] paramTypes = new Type[args.Length + 2];
+ paramTypes[0] = typeof(CallSite);
+ paramTypes[paramTypes.Length - 1] = returnType;
+ for (int i = 0; i < args.Length; i++) {
+ DynamicMetaObject mo = args[i];
+ Type paramType = mo.Expression.Type;
+ if (IsByRef(mo)) {
+ paramType = paramType.MakeByRefType();
+ }
+ paramTypes[i + 1] = paramType;
+ }
+
+ curTypeInfo.DelegateType = MakeNewDelegate(paramTypes);
+ }
+
+ return curTypeInfo.DelegateType;
+ }
+ }
+
+ private static bool IsByRef(DynamicMetaObject mo) {
+ ParameterExpression pe = mo.Expression as ParameterExpression;
+ return pe != null && pe.IsByRef;
+ }
+
+ internal static TypeInfo NextTypeInfo(Type initialArg) {
+ lock (_DelegateCache) {
+ return NextTypeInfo(initialArg, _DelegateCache);
+ }
+ }
+
+ internal static TypeInfo GetNextTypeInfo(Type initialArg, TypeInfo curTypeInfo) {
+ lock (_DelegateCache) {
+ return NextTypeInfo(initialArg, curTypeInfo);
+ }
+ }
+
+ private static TypeInfo NextTypeInfo(Type initialArg, TypeInfo curTypeInfo) {
+ Type lookingUp = initialArg;
+ TypeInfo nextTypeInfo;
+ if (curTypeInfo.TypeChain == null) {
+ curTypeInfo.TypeChain = new Dictionary<Type, TypeInfo>();
+ }
+
+ if (!curTypeInfo.TypeChain.TryGetValue(lookingUp, out nextTypeInfo)) {
+ curTypeInfo.TypeChain[lookingUp] = nextTypeInfo = new TypeInfo();
+ }
+ return nextTypeInfo;
+ }
+
+ /// <summary>
+ /// Creates a new delegate, or uses a func/action
+ /// Note: this method does not cache
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static Type MakeNewDelegate(Type[] types) {
+ Debug.Assert(types != null && types.Length > 0);
+
+ // Can only used predefined delegates if we have no byref types and
+ // the arity is small enough to fit in Func<...> or Action<...>
+ if (types.Length > MaximumArity || types.Any(t => t.IsByRef)) {
+ return MakeNewCustomDelegate(types);
+ }
+
+ Type result;
+ if (types[types.Length - 1] == typeof(void)) {
+ result = GetActionType(types.RemoveLast());
+ } else {
+ result = GetFuncType(types);
+ }
+ Debug.Assert(result != null);
+ return result;
+ }
+
+ internal static Type GetFuncType(Type[] types) {
+ switch (types.Length) {
+ #region Generated Delegate Func Types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_delegate_func from: generate_dynsites.py
+
+ case 1: return typeof(Func<>).MakeGenericType(types);
+ case 2: return typeof(Func<,>).MakeGenericType(types);
+ case 3: return typeof(Func<,,>).MakeGenericType(types);
+ case 4: return typeof(Func<,,,>).MakeGenericType(types);
+ case 5: return typeof(Func<,,,,>).MakeGenericType(types);
+ case 6: return typeof(Func<,,,,,>).MakeGenericType(types);
+ case 7: return typeof(Func<,,,,,,>).MakeGenericType(types);
+ case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types);
+ case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types);
+ case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types);
+ case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types);
+ case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types);
+ case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types);
+ case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types);
+ case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types);
+ case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types);
+ case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types);
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default: return null;
+ }
+ }
+
+ internal static Type GetActionType(Type[] types) {
+ switch (types.Length) {
+ case 0: return typeof(Action);
+ #region Generated Delegate Action Types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_delegate_action from: generate_dynsites.py
+
+ case 1: return typeof(Action<>).MakeGenericType(types);
+ case 2: return typeof(Action<,>).MakeGenericType(types);
+ case 3: return typeof(Action<,,>).MakeGenericType(types);
+ case 4: return typeof(Action<,,,>).MakeGenericType(types);
+ case 5: return typeof(Action<,,,,>).MakeGenericType(types);
+ case 6: return typeof(Action<,,,,,>).MakeGenericType(types);
+ case 7: return typeof(Action<,,,,,,>).MakeGenericType(types);
+ case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types);
+ case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types);
+ case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types);
+ case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types);
+ case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types);
+ case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types);
+ case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types);
+ case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types);
+ case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types);
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default: return null;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs
new file mode 100644
index 00000000000..ac8b05bec6e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/DelegateHelpers.cs
@@ -0,0 +1,47 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ internal static partial class DelegateHelpers {
+ private const MethodAttributes CtorAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public;
+ private const MethodImplAttributes ImplAttributes = MethodImplAttributes.Runtime | MethodImplAttributes.Managed;
+ private const MethodAttributes InvokeAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;
+ private static readonly Type[] _DelegateCtorSignature = new Type[] { typeof(object), typeof(IntPtr) };
+
+ private static Type MakeNewCustomDelegate(Type[] types) {
+ Type returnType = types[types.Length - 1];
+ Type[] parameters = types.RemoveLast();
+
+ TypeBuilder builder = AssemblyGen.DefineDelegateType("Delegate" + types.Length);
+ builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _DelegateCtorSignature).SetImplementationFlags(ImplAttributes);
+ builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes);
+ return builder.CreateType();
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ExpressionQuoter.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ExpressionQuoter.cs
new file mode 100644
index 00000000000..5313bda264f
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ExpressionQuoter.cs
@@ -0,0 +1,253 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ public partial class RuntimeOps {
+ /// <summary>
+ /// Quotes the provided expression tree.
+ /// </summary>
+ /// <param name="expression">The expression to quote.</param>
+ /// <param name="hoistedLocals">The hoisted local state provided by the compiler.</param>
+ /// <param name="locals">The actual hoisted local values.</param>
+ /// <returns>The quoted expression.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static Expression Quote(Expression expression, object hoistedLocals, object[] locals) {
+ Debug.Assert(hoistedLocals != null && locals != null);
+ var quoter = new ExpressionQuoter((HoistedLocals)hoistedLocals, locals);
+ return quoter.Visit(expression);
+ }
+
+ /// <summary>
+ /// Combines two runtime variable lists and returns a new list.
+ /// </summary>
+ /// <param name="first">The first list.</param>
+ /// <param name="second">The second list.</param>
+ /// <param name="indexes">The index array indicating which list to get variables from.</param>
+ /// <returns>The merged runtime variables.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static IRuntimeVariables MergeRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) {
+ return new MergedRuntimeVariables(first, second, indexes);
+ }
+
+ // Modifies a quoted Expression instance by changing hoisted variables and
+ // parameters into hoisted local references. The variable's StrongBox is
+ // burned as a constant, and all hoisted variables/parameters are rewritten
+ // as indexing expressions.
+ //
+ // The behavior of Quote is indended to be like C# and VB expression quoting
+ private sealed class ExpressionQuoter : ExpressionVisitor {
+ private readonly HoistedLocals _scope;
+ private readonly object[] _locals;
+
+ // A stack of variables that are defined in nested scopes. We search
+ // this first when resolving a variable in case a nested scope shadows
+ // one of our variable instances.
+ private readonly Stack<Set<ParameterExpression>> _shadowedVars = new Stack<Set<ParameterExpression>>();
+
+ internal ExpressionQuoter(HoistedLocals scope, object[] locals) {
+ _scope = scope;
+ _locals = locals;
+ }
+
+ protected internal override Expression VisitLambda<T>(Expression<T> node) {
+ _shadowedVars.Push(new Set<ParameterExpression>(node.Parameters));
+ Expression b = Visit(node.Body);
+ _shadowedVars.Pop();
+ if (b == node.Body) {
+ return node;
+ }
+ return Expression.Lambda<T>(b, node.Name, node.TailCall, node.Parameters);
+ }
+
+ protected internal override Expression VisitBlock(BlockExpression node) {
+ if (node.Variables.Count > 0) {
+ _shadowedVars.Push(new Set<ParameterExpression>(node.Variables));
+ }
+ var b = Visit(node.Expressions);
+ if (node.Variables.Count > 0) {
+ _shadowedVars.Pop();
+ }
+ if (b == node.Expressions) {
+ return node;
+ }
+ return Expression.Block(node.Variables, b);
+ }
+
+ protected override CatchBlock VisitCatchBlock(CatchBlock node) {
+ if (node.Variable != null) {
+ _shadowedVars.Push(new Set<ParameterExpression>(new[] { node.Variable }));
+ }
+ Expression b = Visit(node.Body);
+ Expression f = Visit(node.Filter);
+ if (node.Variable != null) {
+ _shadowedVars.Pop();
+ }
+ if (b == node.Body && f == node.Filter) {
+ return node;
+ }
+ return Expression.MakeCatchBlock(node.Test, node.Variable, b, f);
+ }
+
+ protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
+ int count = node.Variables.Count;
+ var boxes = new List<IStrongBox>();
+ var vars = new List<ParameterExpression>();
+ var indexes = new int[count];
+ for (int i = 0; i < count; i++) {
+ IStrongBox box = GetBox(node.Variables[i]);
+ if (box == null) {
+ indexes[i] = vars.Count;
+ vars.Add(node.Variables[i]);
+ } else {
+ indexes[i] = -1 - boxes.Count;
+ boxes.Add(box);
+ }
+ }
+
+ // No variables were rewritten. Just return the original node
+ if (boxes.Count == 0) {
+ return node;
+ }
+
+ var boxesConst = Expression.Constant(new RuntimeVariables(boxes.ToArray()), typeof(IRuntimeVariables));
+ // All of them were rewritten. Just return the array as a constant
+ if (vars.Count == 0) {
+ return boxesConst;
+ }
+
+ // Otherwise, we need to return an object that merges them
+ return Expression.Call(
+ typeof(RuntimeOps).GetMethod("MergeRuntimeVariables"),
+ Expression.RuntimeVariables(new TrueReadOnlyCollection<ParameterExpression>(vars.ToArray())),
+ boxesConst,
+ Expression.Constant(indexes)
+ );
+ }
+
+ protected internal override Expression VisitParameter(ParameterExpression node) {
+ IStrongBox box = GetBox(node);
+ if (box == null) {
+ return node;
+ }
+ return Expression.Field(Expression.Constant(box), "Value");
+ }
+
+ private IStrongBox GetBox(ParameterExpression variable) {
+ // Skip variables that are shadowed by a nested scope/lambda
+ foreach (Set<ParameterExpression> hidden in _shadowedVars) {
+ if (hidden.Contains(variable)) {
+ return null;
+ }
+ }
+
+ HoistedLocals scope = _scope;
+ object[] locals = _locals;
+ while (true) {
+ int hoistIndex;
+ if (scope.Indexes.TryGetValue(variable, out hoistIndex)) {
+ return (IStrongBox)locals[hoistIndex];
+ }
+ scope = scope.Parent;
+ if (scope == null) {
+ break;
+ }
+ locals = HoistedLocals.GetParent(locals);
+ }
+
+ // Unbound variable: an error should've been thrown already
+ // from VariableBinder
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ private sealed class RuntimeVariables : IRuntimeVariables {
+ private readonly IStrongBox[] _boxes;
+
+ internal RuntimeVariables(IStrongBox[] boxes) {
+ _boxes = boxes;
+ }
+
+ int IRuntimeVariables.Count {
+ get { return _boxes.Length; }
+ }
+
+ object IRuntimeVariables.this[int index] {
+ get {
+ return _boxes[index].Value;
+ }
+ set {
+ _boxes[index].Value = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provides a list of variables, supporing read/write of the values
+ /// Exposed via RuntimeVariablesExpression
+ /// </summary>
+ private sealed class MergedRuntimeVariables : IRuntimeVariables {
+ private readonly IRuntimeVariables _first;
+ private readonly IRuntimeVariables _second;
+
+ // For reach item, the index into the first or second list
+ // Positive values mean the first array, negative means the second
+ private readonly int[] _indexes;
+
+ internal MergedRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) {
+ _first = first;
+ _second = second;
+ _indexes = indexes;
+ }
+
+ public int Count {
+ get { return _indexes.Length; }
+ }
+
+ public object this[int index] {
+ get {
+ index = _indexes[index];
+ return (index >= 0) ? _first[index] : _second[-1 - index];
+ }
+ set {
+ index = _indexes[index];
+ if (index >= 0) {
+ _first[index] = value;
+ } else {
+ _second[-1 - index] = value;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/HoistedLocals.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/HoistedLocals.cs
new file mode 100644
index 00000000000..3179709362a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/HoistedLocals.cs
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ // Suppose we have something like:
+ //
+ // (string s)=>()=>s.
+ //
+ // We wish to generate the outer as:
+ //
+ // Func<string> OuterMethod(Closure closure, string s)
+ // {
+ // object[] locals = new object[1];
+ // locals[0] = new StrongBox<string>();
+ // ((StrongBox<string>)locals[0]).Value = s;
+ // return ((DynamicMethod)closure.Constants[0]).CreateDelegate(typeof(Func<string>), new Closure(null, locals));
+ // }
+ //
+ // ... and the inner as:
+ //
+ // string InnerMethod(Closure closure)
+ // {
+ // object[] locals = closure.Locals;
+ // return ((StrongBox<string>)locals[0]).Value;
+ // }
+ //
+ // This class tracks that "s" was hoisted into a closure, as the 0th
+ // element in the array
+ //
+ /// <summary>
+ /// Stores information about locals and arguments that are hoisted into
+ /// the closure array because they're referenced in an inner lambda.
+ ///
+ /// This class is sometimes emitted as a runtime constant for internal
+ /// use to hoist variables/parameters in quoted expressions
+ ///
+ /// Invariant: this class stores no mutable state
+ /// </summary>
+ internal sealed class HoistedLocals {
+
+ // The parent locals, if any
+ internal readonly HoistedLocals Parent;
+
+ // A mapping of hoisted variables to their indexes in the array
+ internal readonly ReadOnlyDictionary<Expression, int> Indexes;
+
+ // The variables, in the order they appear in the array
+ internal readonly ReadOnlyCollection<ParameterExpression> Variables;
+
+ // A virtual variable for accessing this locals array
+ internal readonly ParameterExpression SelfVariable;
+
+ internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection<ParameterExpression> vars) {
+
+ if (parent != null) {
+ // Add the parent locals array as the 0th element in the array
+ vars = new TrueReadOnlyCollection<ParameterExpression>(vars.AddFirst(parent.SelfVariable));
+ }
+
+ Dictionary<Expression, int> indexes = new Dictionary<Expression, int>(vars.Count);
+ for (int i = 0; i < vars.Count; i++) {
+ indexes.Add(vars[i], i);
+ }
+
+ SelfVariable = Expression.Variable(typeof(object[]), null);
+ Parent = parent;
+ Variables = vars;
+ Indexes = new ReadOnlyDictionary<Expression, int>(indexes);
+ }
+
+ internal ParameterExpression ParentVariable {
+ get { return Parent != null ? Parent.SelfVariable : null; }
+ }
+
+ internal static object[] GetParent(object[] locals) {
+ return ((StrongBox<object[]>)locals[0]).Value;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ILGen.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ILGen.cs
new file mode 100644
index 00000000000..f4521c2f0dd
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/ILGen.cs
@@ -0,0 +1,1061 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#else
+using ILGenerator = Microsoft.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#endif
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ internal static class ILGen {
+
+ internal static void Emit(this ILGenerator il, OpCode opcode, MethodBase methodBase) {
+ Debug.Assert(methodBase is MethodInfo || methodBase is ConstructorInfo);
+
+ if (methodBase.MemberType == MemberTypes.Constructor) {
+ il.Emit(opcode, (ConstructorInfo)methodBase);
+ } else {
+ il.Emit(opcode, (MethodInfo)methodBase);
+ }
+ }
+
+ #region Instruction helpers
+
+ internal static void EmitLoadArg(this ILGenerator il, int index) {
+ Debug.Assert(index >= 0);
+
+ switch (index) {
+ case 0:
+ il.Emit(OpCodes.Ldarg_0);
+ break;
+ case 1:
+ il.Emit(OpCodes.Ldarg_1);
+ break;
+ case 2:
+ il.Emit(OpCodes.Ldarg_2);
+ break;
+ case 3:
+ il.Emit(OpCodes.Ldarg_3);
+ break;
+ default:
+ if (index <= Byte.MaxValue) {
+ il.Emit(OpCodes.Ldarg_S, (byte)index);
+ } else {
+ il.Emit(OpCodes.Ldarg, index);
+ }
+ break;
+ }
+ }
+
+ internal static void EmitLoadArgAddress(this ILGenerator il, int index) {
+ Debug.Assert(index >= 0);
+
+ if (index <= Byte.MaxValue) {
+ il.Emit(OpCodes.Ldarga_S, (byte)index);
+ } else {
+ il.Emit(OpCodes.Ldarga, index);
+ }
+ }
+
+ internal static void EmitStoreArg(this ILGenerator il, int index) {
+ Debug.Assert(index >= 0);
+
+ if (index <= Byte.MaxValue) {
+ il.Emit(OpCodes.Starg_S, (byte)index);
+ } else {
+ il.Emit(OpCodes.Starg, index);
+ }
+ }
+
+ /// <summary>
+ /// Emits a Ldind* instruction for the appropriate type
+ /// </summary>
+ internal static void EmitLoadValueIndirect(this ILGenerator il, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (type.IsValueType) {
+ if (type == typeof(int)) {
+ il.Emit(OpCodes.Ldind_I4);
+ } else if (type == typeof(uint)) {
+ il.Emit(OpCodes.Ldind_U4);
+ } else if (type == typeof(short)) {
+ il.Emit(OpCodes.Ldind_I2);
+ } else if (type == typeof(ushort)) {
+ il.Emit(OpCodes.Ldind_U2);
+ } else if (type == typeof(long) || type == typeof(ulong)) {
+ il.Emit(OpCodes.Ldind_I8);
+ } else if (type == typeof(char)) {
+ il.Emit(OpCodes.Ldind_I2);
+ } else if (type == typeof(bool)) {
+ il.Emit(OpCodes.Ldind_I1);
+ } else if (type == typeof(float)) {
+ il.Emit(OpCodes.Ldind_R4);
+ } else if (type == typeof(double)) {
+ il.Emit(OpCodes.Ldind_R8);
+ } else {
+ il.Emit(OpCodes.Ldobj, type);
+ }
+ } else {
+ il.Emit(OpCodes.Ldind_Ref);
+ }
+ }
+
+
+ /// <summary>
+ /// Emits a Stind* instruction for the appropriate type.
+ /// </summary>
+ internal static void EmitStoreValueIndirect(this ILGenerator il, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (type.IsValueType) {
+ if (type == typeof(int)) {
+ il.Emit(OpCodes.Stind_I4);
+ } else if (type == typeof(short)) {
+ il.Emit(OpCodes.Stind_I2);
+ } else if (type == typeof(long) || type == typeof(ulong)) {
+ il.Emit(OpCodes.Stind_I8);
+ } else if (type == typeof(char)) {
+ il.Emit(OpCodes.Stind_I2);
+ } else if (type == typeof(bool)) {
+ il.Emit(OpCodes.Stind_I1);
+ } else if (type == typeof(float)) {
+ il.Emit(OpCodes.Stind_R4);
+ } else if (type == typeof(double)) {
+ il.Emit(OpCodes.Stind_R8);
+ } else {
+ il.Emit(OpCodes.Stobj, type);
+ }
+ } else {
+ il.Emit(OpCodes.Stind_Ref);
+ }
+ }
+
+ // Emits the Ldelem* instruction for the appropriate type
+
+ internal static void EmitLoadElement(this ILGenerator il, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (!type.IsValueType) {
+ il.Emit(OpCodes.Ldelem_Ref);
+ } else if (type.IsEnum) {
+ il.Emit(OpCodes.Ldelem, type);
+ } else {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Boolean:
+ case TypeCode.SByte:
+ il.Emit(OpCodes.Ldelem_I1);
+ break;
+ case TypeCode.Byte:
+ il.Emit(OpCodes.Ldelem_U1);
+ break;
+ case TypeCode.Int16:
+ il.Emit(OpCodes.Ldelem_I2);
+ break;
+ case TypeCode.Char:
+ case TypeCode.UInt16:
+ il.Emit(OpCodes.Ldelem_U2);
+ break;
+ case TypeCode.Int32:
+ il.Emit(OpCodes.Ldelem_I4);
+ break;
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Ldelem_U4);
+ break;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Ldelem_I8);
+ break;
+ case TypeCode.Single:
+ il.Emit(OpCodes.Ldelem_R4);
+ break;
+ case TypeCode.Double:
+ il.Emit(OpCodes.Ldelem_R8);
+ break;
+ default:
+ il.Emit(OpCodes.Ldelem, type);
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Emits a Stelem* instruction for the appropriate type.
+ /// </summary>
+ internal static void EmitStoreElement(this ILGenerator il, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (type.IsEnum) {
+ il.Emit(OpCodes.Stelem, type);
+ return;
+ }
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Boolean:
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ il.Emit(OpCodes.Stelem_I1);
+ break;
+ case TypeCode.Char:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ il.Emit(OpCodes.Stelem_I2);
+ break;
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Stelem_I4);
+ break;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Stelem_I8);
+ break;
+ case TypeCode.Single:
+ il.Emit(OpCodes.Stelem_R4);
+ break;
+ case TypeCode.Double:
+ il.Emit(OpCodes.Stelem_R8);
+ break;
+ default:
+ if (type.IsValueType) {
+ il.Emit(OpCodes.Stelem, type);
+ } else {
+ il.Emit(OpCodes.Stelem_Ref);
+ }
+ break;
+ }
+ }
+
+ internal static void EmitType(this ILGenerator il, Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ il.Emit(OpCodes.Ldtoken, type);
+ il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
+ }
+
+ #endregion
+
+ #region Fields, properties and methods
+
+ internal static void EmitFieldAddress(this ILGenerator il, FieldInfo fi) {
+ ContractUtils.RequiresNotNull(fi, "fi");
+
+ if (fi.IsStatic) {
+ il.Emit(OpCodes.Ldsflda, fi);
+ } else {
+ il.Emit(OpCodes.Ldflda, fi);
+ }
+ }
+
+ internal static void EmitFieldGet(this ILGenerator il, FieldInfo fi) {
+ ContractUtils.RequiresNotNull(fi, "fi");
+
+ if (fi.IsStatic) {
+ il.Emit(OpCodes.Ldsfld, fi);
+ } else {
+ il.Emit(OpCodes.Ldfld, fi);
+ }
+ }
+
+ internal static void EmitFieldSet(this ILGenerator il, FieldInfo fi) {
+ ContractUtils.RequiresNotNull(fi, "fi");
+
+ if (fi.IsStatic) {
+ il.Emit(OpCodes.Stsfld, fi);
+ } else {
+ il.Emit(OpCodes.Stfld, fi);
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
+ internal static void EmitNew(this ILGenerator il, ConstructorInfo ci) {
+ ContractUtils.RequiresNotNull(ci, "ci");
+
+ if (ci.DeclaringType.ContainsGenericParameters) {
+ throw Error.IllegalNewGenericParams(ci.DeclaringType);
+ }
+
+ il.Emit(OpCodes.Newobj, ci);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
+ internal static void EmitNew(this ILGenerator il, Type type, Type[] paramTypes) {
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(paramTypes, "paramTypes");
+
+ ConstructorInfo ci = type.GetConstructor(paramTypes);
+ ContractUtils.Requires(ci != null, "type", Strings.TypeDoesNotHaveConstructorForTheSignature);
+ il.EmitNew(ci);
+ }
+
+ #endregion
+
+ #region Constants
+
+ internal static void EmitNull(this ILGenerator il) {
+ il.Emit(OpCodes.Ldnull);
+ }
+
+ internal static void EmitString(this ILGenerator il, string value) {
+ ContractUtils.RequiresNotNull(value, "value");
+ il.Emit(OpCodes.Ldstr, value);
+ }
+
+ internal static void EmitBoolean(this ILGenerator il, bool value) {
+ if (value) {
+ il.Emit(OpCodes.Ldc_I4_1);
+ } else {
+ il.Emit(OpCodes.Ldc_I4_0);
+ }
+ }
+
+ internal static void EmitChar(this ILGenerator il, char value) {
+ il.EmitInt(value);
+ il.Emit(OpCodes.Conv_U2);
+ }
+
+ internal static void EmitByte(this ILGenerator il, byte value) {
+ il.EmitInt(value);
+ il.Emit(OpCodes.Conv_U1);
+ }
+
+ internal static void EmitSByte(this ILGenerator il, sbyte value) {
+ il.EmitInt(value);
+ il.Emit(OpCodes.Conv_I1);
+ }
+
+ internal static void EmitShort(this ILGenerator il, short value) {
+ il.EmitInt(value);
+ il.Emit(OpCodes.Conv_I2);
+ }
+
+ internal static void EmitUShort(this ILGenerator il, ushort value) {
+ il.EmitInt(value);
+ il.Emit(OpCodes.Conv_U2);
+ }
+
+ internal static void EmitInt(this ILGenerator il, int value) {
+ OpCode c;
+ switch (value) {
+ case -1:
+ c = OpCodes.Ldc_I4_M1;
+ break;
+ case 0:
+ c = OpCodes.Ldc_I4_0;
+ break;
+ case 1:
+ c = OpCodes.Ldc_I4_1;
+ break;
+ case 2:
+ c = OpCodes.Ldc_I4_2;
+ break;
+ case 3:
+ c = OpCodes.Ldc_I4_3;
+ break;
+ case 4:
+ c = OpCodes.Ldc_I4_4;
+ break;
+ case 5:
+ c = OpCodes.Ldc_I4_5;
+ break;
+ case 6:
+ c = OpCodes.Ldc_I4_6;
+ break;
+ case 7:
+ c = OpCodes.Ldc_I4_7;
+ break;
+ case 8:
+ c = OpCodes.Ldc_I4_8;
+ break;
+ default:
+ if (value >= -128 && value <= 127) {
+ il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
+ } else {
+ il.Emit(OpCodes.Ldc_I4, value);
+ }
+ return;
+ }
+ il.Emit(c);
+ }
+
+ internal static void EmitUInt(this ILGenerator il, uint value) {
+ il.EmitInt((int)value);
+ il.Emit(OpCodes.Conv_U4);
+ }
+
+ internal static void EmitLong(this ILGenerator il, long value) {
+ il.Emit(OpCodes.Ldc_I8, value);
+
+ //
+ // Now, emit convert to give the constant type information.
+ //
+ // Otherwise, it is treated as unsigned and overflow is not
+ // detected if it's used in checked ops.
+ //
+ il.Emit(OpCodes.Conv_I8);
+ }
+
+ internal static void EmitULong(this ILGenerator il, ulong value) {
+ il.Emit(OpCodes.Ldc_I8, (long)value);
+ il.Emit(OpCodes.Conv_U8);
+ }
+
+ internal static void EmitDouble(this ILGenerator il, double value) {
+ il.Emit(OpCodes.Ldc_R8, value);
+ }
+
+ internal static void EmitSingle(this ILGenerator il, float value) {
+ il.Emit(OpCodes.Ldc_R4, value);
+ }
+
+ // matches TryEmitConstant
+ internal static bool CanEmitConstant(object value, Type type) {
+ if (value == null || CanEmitILConstant(type)) {
+ return true;
+ }
+
+ Type t = value as Type;
+ if (t != null && ShouldLdtoken(t)) {
+ return true;
+ }
+
+ MethodBase mb = value as MethodBase;
+ if (mb != null && ShouldLdtoken(mb)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ // matches TryEmitILConstant
+ private static bool CanEmitILConstant(Type type) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Boolean:
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Char:
+ case TypeCode.Byte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Decimal:
+ case TypeCode.String:
+ return true;
+ }
+ return false;
+ }
+
+ internal static void EmitConstant(this ILGenerator il, object value) {
+ Debug.Assert(value != null);
+ EmitConstant(il, value, value.GetType());
+ }
+
+
+ //
+ // Note: we support emitting more things as IL constants than
+ // Linq does
+ internal static void EmitConstant(this ILGenerator il, object value, Type type) {
+ if (value == null) {
+ // Smarter than the Linq implementation which uses the initobj
+ // pattern for all value types (works, but requires a local and
+ // more IL)
+ il.EmitDefault(type);
+ return;
+ }
+
+ // Handle the easy cases
+ if (il.TryEmitILConstant(value, type)) {
+ return;
+ }
+
+ // Check for a few more types that we support emitting as constants
+ Type t = value as Type;
+ if (t != null && ShouldLdtoken(t)) {
+ il.EmitType(t);
+ if (type != typeof(Type)) {
+ il.Emit(OpCodes.Castclass, type);
+ }
+ return;
+ }
+
+ MethodBase mb = value as MethodBase;
+ if (mb != null && ShouldLdtoken(mb)) {
+ il.Emit(OpCodes.Ldtoken, mb);
+ Type dt = mb.DeclaringType;
+ if (dt != null && dt.IsGenericType) {
+ il.Emit(OpCodes.Ldtoken, dt);
+ il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) }));
+ } else {
+ il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle) }));
+ }
+ if (type != typeof(MethodBase)) {
+ il.Emit(OpCodes.Castclass, type);
+ }
+ return;
+ }
+
+ throw ContractUtils.Unreachable;
+ }
+
+ internal static bool ShouldLdtoken(Type t) {
+ return t is TypeBuilder || t.IsGenericParameter || t.IsVisible;
+ }
+
+ internal static bool ShouldLdtoken(MethodBase mb) {
+ // Can't ldtoken on a DynamicMethod
+ if (mb is DynamicMethod) {
+ return false;
+ }
+
+ Type dt = mb.DeclaringType;
+ return dt == null || ShouldLdtoken(dt);
+ }
+
+
+ private static bool TryEmitILConstant(this ILGenerator il, object value, Type type) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Boolean:
+ il.EmitBoolean((bool)value);
+ return true;
+ case TypeCode.SByte:
+ il.EmitSByte((sbyte)value);
+ return true;
+ case TypeCode.Int16:
+ il.EmitShort((short)value);
+ return true;
+ case TypeCode.Int32:
+ il.EmitInt((int)value);
+ return true;
+ case TypeCode.Int64:
+ il.EmitLong((long)value);
+ return true;
+ case TypeCode.Single:
+ il.EmitSingle((float)value);
+ return true;
+ case TypeCode.Double:
+ il.EmitDouble((double)value);
+ return true;
+ case TypeCode.Char:
+ il.EmitChar((char)value);
+ return true;
+ case TypeCode.Byte:
+ il.EmitByte((byte)value);
+ return true;
+ case TypeCode.UInt16:
+ il.EmitUShort((ushort)value);
+ return true;
+ case TypeCode.UInt32:
+ il.EmitUInt((uint)value);
+ return true;
+ case TypeCode.UInt64:
+ il.EmitULong((ulong)value);
+ return true;
+ case TypeCode.Decimal:
+ il.EmitDecimal((decimal)value);
+ return true;
+ case TypeCode.String:
+ il.EmitString((string)value);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region Linq Conversions
+
+ internal static void EmitConvertToType(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ if (TypeUtils.AreEquivalent(typeFrom, typeTo)) {
+ return;
+ }
+
+ if (typeFrom == typeof(void) || typeTo == typeof(void)) {
+ throw ContractUtils.Unreachable;
+ }
+
+ bool isTypeFromNullable = TypeUtils.IsNullableType(typeFrom);
+ bool isTypeToNullable = TypeUtils.IsNullableType(typeTo);
+
+ Type nnExprType = TypeUtils.GetNonNullableType(typeFrom);
+ Type nnType = TypeUtils.GetNonNullableType(typeTo);
+
+ if (typeFrom.IsInterface || // interface cast
+ typeTo.IsInterface ||
+ typeFrom == typeof(object) || // boxing cast
+ typeTo == typeof(object)) {
+ il.EmitCastToType(typeFrom, typeTo);
+ } else if (isTypeFromNullable || isTypeToNullable) {
+ il.EmitNullableConversion(typeFrom, typeTo, isChecked);
+ } else if (!(TypeUtils.IsConvertible(typeFrom) && TypeUtils.IsConvertible(typeTo)) // primitive runtime conversion
+ &&
+ (nnExprType.IsAssignableFrom(nnType) || // down cast
+ nnType.IsAssignableFrom(nnExprType))) // up cast
+ {
+ il.EmitCastToType(typeFrom, typeTo);
+ } else if (typeFrom.IsArray && typeTo.IsArray) {
+ // See DevDiv Bugs #94657.
+ il.EmitCastToType(typeFrom, typeTo);
+ } else {
+ il.EmitNumericConversion(typeFrom, typeTo, isChecked);
+ }
+ }
+
+
+ private static void EmitCastToType(this ILGenerator il, Type typeFrom, Type typeTo) {
+ if (!typeFrom.IsValueType && typeTo.IsValueType) {
+ il.Emit(OpCodes.Unbox_Any, typeTo);
+ } else if (typeFrom.IsValueType && !typeTo.IsValueType) {
+ il.Emit(OpCodes.Box, typeFrom);
+ if (typeTo != typeof(object)) {
+ il.Emit(OpCodes.Castclass, typeTo);
+ }
+ } else if (!typeFrom.IsValueType && !typeTo.IsValueType) {
+ il.Emit(OpCodes.Castclass, typeTo);
+ } else {
+ throw Error.InvalidCast(typeFrom, typeTo);
+ }
+ }
+
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private static void EmitNumericConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ bool isFromUnsigned = TypeUtils.IsUnsigned(typeFrom);
+ bool isFromFloatingPoint = TypeUtils.IsFloatingPoint(typeFrom);
+ if (typeTo == typeof(Single)) {
+ if (isFromUnsigned)
+ il.Emit(OpCodes.Conv_R_Un);
+ il.Emit(OpCodes.Conv_R4);
+ } else if (typeTo == typeof(Double)) {
+ if (isFromUnsigned)
+ il.Emit(OpCodes.Conv_R_Un);
+ il.Emit(OpCodes.Conv_R8);
+ } else {
+ TypeCode tc = Type.GetTypeCode(typeTo);
+ if (isChecked) {
+ if (isFromUnsigned) {
+ switch (tc) {
+ case TypeCode.SByte:
+ il.Emit(OpCodes.Conv_Ovf_I1_Un);
+ break;
+ case TypeCode.Int16:
+ il.Emit(OpCodes.Conv_Ovf_I2_Un);
+ break;
+ case TypeCode.Int32:
+ il.Emit(OpCodes.Conv_Ovf_I4_Un);
+ break;
+ case TypeCode.Int64:
+ il.Emit(OpCodes.Conv_Ovf_I8_Un);
+ break;
+ case TypeCode.Byte:
+ il.Emit(OpCodes.Conv_Ovf_U1_Un);
+ break;
+ case TypeCode.UInt16:
+ case TypeCode.Char:
+ il.Emit(OpCodes.Conv_Ovf_U2_Un);
+ break;
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Conv_Ovf_U4_Un);
+ break;
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Conv_Ovf_U8_Un);
+ break;
+ default:
+ throw Error.UnhandledConvert(typeTo);
+ }
+ } else {
+ switch (tc) {
+ case TypeCode.SByte:
+ il.Emit(OpCodes.Conv_Ovf_I1);
+ break;
+ case TypeCode.Int16:
+ il.Emit(OpCodes.Conv_Ovf_I2);
+ break;
+ case TypeCode.Int32:
+ il.Emit(OpCodes.Conv_Ovf_I4);
+ break;
+ case TypeCode.Int64:
+ il.Emit(OpCodes.Conv_Ovf_I8);
+ break;
+ case TypeCode.Byte:
+ il.Emit(OpCodes.Conv_Ovf_U1);
+ break;
+ case TypeCode.UInt16:
+ case TypeCode.Char:
+ il.Emit(OpCodes.Conv_Ovf_U2);
+ break;
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Conv_Ovf_U4);
+ break;
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Conv_Ovf_U8);
+ break;
+ default:
+ throw Error.UnhandledConvert(typeTo);
+ }
+ }
+ } else {
+ if (isFromUnsigned) {
+ switch (tc) {
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ il.Emit(OpCodes.Conv_U1);
+ break;
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Char:
+ il.Emit(OpCodes.Conv_U2);
+ break;
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Conv_U4);
+ break;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Conv_U8);
+ break;
+ default:
+ throw Error.UnhandledConvert(typeTo);
+ }
+ } else {
+ switch (tc) {
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ il.Emit(OpCodes.Conv_I1);
+ break;
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Char:
+ il.Emit(OpCodes.Conv_I2);
+ break;
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Conv_I4);
+ break;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Conv_I8);
+ break;
+ default:
+ throw Error.UnhandledConvert(typeTo);
+ }
+ }
+ }
+ }
+ }
+
+
+ private static void EmitNullableToNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ Debug.Assert(TypeUtils.IsNullableType(typeFrom));
+ Debug.Assert(TypeUtils.IsNullableType(typeTo));
+ Label labIfNull = default(Label);
+ Label labEnd = default(Label);
+ LocalBuilder locFrom = null;
+ LocalBuilder locTo = null;
+ locFrom = il.DeclareLocal(typeFrom);
+ il.Emit(OpCodes.Stloc, locFrom);
+ locTo = il.DeclareLocal(typeTo);
+ // test for null
+ il.Emit(OpCodes.Ldloca, locFrom);
+ il.EmitHasValue(typeFrom);
+ labIfNull = il.DefineLabel();
+ il.Emit(OpCodes.Brfalse_S, labIfNull);
+ il.Emit(OpCodes.Ldloca, locFrom);
+ il.EmitGetValueOrDefault(typeFrom);
+ Type nnTypeFrom = TypeUtils.GetNonNullableType(typeFrom);
+ Type nnTypeTo = TypeUtils.GetNonNullableType(typeTo);
+ il.EmitConvertToType(nnTypeFrom, nnTypeTo, isChecked);
+ // construct result type
+ ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });
+ il.Emit(OpCodes.Newobj, ci);
+ il.Emit(OpCodes.Stloc, locTo);
+ labEnd = il.DefineLabel();
+ il.Emit(OpCodes.Br_S, labEnd);
+ // if null then create a default one
+ il.MarkLabel(labIfNull);
+ il.Emit(OpCodes.Ldloca, locTo);
+ il.Emit(OpCodes.Initobj, typeTo);
+ il.MarkLabel(labEnd);
+ il.Emit(OpCodes.Ldloc, locTo);
+ }
+
+
+ private static void EmitNonNullableToNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ Debug.Assert(!TypeUtils.IsNullableType(typeFrom));
+ Debug.Assert(TypeUtils.IsNullableType(typeTo));
+ LocalBuilder locTo = null;
+ locTo = il.DeclareLocal(typeTo);
+ Type nnTypeTo = TypeUtils.GetNonNullableType(typeTo);
+ il.EmitConvertToType(typeFrom, nnTypeTo, isChecked);
+ ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });
+ il.Emit(OpCodes.Newobj, ci);
+ il.Emit(OpCodes.Stloc, locTo);
+ il.Emit(OpCodes.Ldloc, locTo);
+ }
+
+
+ private static void EmitNullableToNonNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ Debug.Assert(TypeUtils.IsNullableType(typeFrom));
+ Debug.Assert(!TypeUtils.IsNullableType(typeTo));
+ if (typeTo.IsValueType)
+ il.EmitNullableToNonNullableStructConversion(typeFrom, typeTo, isChecked);
+ else
+ il.EmitNullableToReferenceConversion(typeFrom);
+ }
+
+
+ private static void EmitNullableToNonNullableStructConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ Debug.Assert(TypeUtils.IsNullableType(typeFrom));
+ Debug.Assert(!TypeUtils.IsNullableType(typeTo));
+ Debug.Assert(typeTo.IsValueType);
+ LocalBuilder locFrom = null;
+ locFrom = il.DeclareLocal(typeFrom);
+ il.Emit(OpCodes.Stloc, locFrom);
+ il.Emit(OpCodes.Ldloca, locFrom);
+ il.EmitGetValue(typeFrom);
+ Type nnTypeFrom = TypeUtils.GetNonNullableType(typeFrom);
+ il.EmitConvertToType(nnTypeFrom, typeTo, isChecked);
+ }
+
+
+ private static void EmitNullableToReferenceConversion(this ILGenerator il, Type typeFrom) {
+ Debug.Assert(TypeUtils.IsNullableType(typeFrom));
+ // We've got a conversion from nullable to Object, ValueType, Enum, etc. Just box it so that
+ // we get the nullable semantics.
+ il.Emit(OpCodes.Box, typeFrom);
+ }
+
+
+ private static void EmitNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) {
+ bool isTypeFromNullable = TypeUtils.IsNullableType(typeFrom);
+ bool isTypeToNullable = TypeUtils.IsNullableType(typeTo);
+ Debug.Assert(isTypeFromNullable || isTypeToNullable);
+ if (isTypeFromNullable && isTypeToNullable)
+ il.EmitNullableToNullableConversion(typeFrom, typeTo, isChecked);
+ else if (isTypeFromNullable)
+ il.EmitNullableToNonNullableConversion(typeFrom, typeTo, isChecked);
+ else
+ il.EmitNonNullableToNullableConversion(typeFrom, typeTo, isChecked);
+ }
+
+
+ internal static void EmitHasValue(this ILGenerator il, Type nullableType) {
+ MethodInfo mi = nullableType.GetMethod("get_HasValue", BindingFlags.Instance | BindingFlags.Public);
+ Debug.Assert(nullableType.IsValueType);
+ il.Emit(OpCodes.Call, mi);
+ }
+
+
+ internal static void EmitGetValue(this ILGenerator il, Type nullableType) {
+ MethodInfo mi = nullableType.GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public);
+ Debug.Assert(nullableType.IsValueType);
+ il.Emit(OpCodes.Call, mi);
+ }
+
+
+ internal static void EmitGetValueOrDefault(this ILGenerator il, Type nullableType) {
+ MethodInfo mi = nullableType.GetMethod("GetValueOrDefault", System.Type.EmptyTypes);
+ Debug.Assert(nullableType.IsValueType);
+ il.Emit(OpCodes.Call, mi);
+ }
+
+ #endregion
+
+ #region Arrays
+
+ /// <summary>
+ /// Emits an array of constant values provided in the given list.
+ /// The array is strongly typed.
+ /// </summary>
+ internal static void EmitArray<T>(this ILGenerator il, IList<T> items) {
+ ContractUtils.RequiresNotNull(items, "items");
+
+ il.EmitInt(items.Count);
+ il.Emit(OpCodes.Newarr, typeof(T));
+ for (int i = 0; i < items.Count; i++) {
+ il.Emit(OpCodes.Dup);
+ il.EmitInt(i);
+ il.EmitConstant(items[i], typeof(T));
+ il.EmitStoreElement(typeof(T));
+ }
+ }
+
+ /// <summary>
+ /// Emits an array of values of count size. The items are emitted via the callback
+ /// which is provided with the current item index to emit.
+ /// </summary>
+ internal static void EmitArray(this ILGenerator il, Type elementType, int count, Action<int> emit) {
+ ContractUtils.RequiresNotNull(elementType, "elementType");
+ ContractUtils.RequiresNotNull(emit, "emit");
+ ContractUtils.Requires(count >= 0, "count", Strings.CountCannotBeNegative);
+
+ il.EmitInt(count);
+ il.Emit(OpCodes.Newarr, elementType);
+ for (int i = 0; i < count; i++) {
+ il.Emit(OpCodes.Dup);
+ il.EmitInt(i);
+
+ emit(i);
+
+ il.EmitStoreElement(elementType);
+ }
+ }
+
+ /// <summary>
+ /// Emits an array construction code.
+ /// The code assumes that bounds for all dimensions
+ /// are already emitted.
+ /// </summary>
+ internal static void EmitArray(this ILGenerator il, Type arrayType) {
+ ContractUtils.RequiresNotNull(arrayType, "arrayType");
+ ContractUtils.Requires(arrayType.IsArray, "arrayType", Strings.ArrayTypeMustBeArray);
+
+ int rank = arrayType.GetArrayRank();
+ if (rank == 1) {
+ il.Emit(OpCodes.Newarr, arrayType.GetElementType());
+ } else {
+ Type[] types = new Type[rank];
+ for (int i = 0; i < rank; i++) {
+ types[i] = typeof(int);
+ }
+ il.EmitNew(arrayType, types);
+ }
+ }
+
+ #endregion
+
+ #region Support for emitting constants
+
+ internal static void EmitDecimal(this ILGenerator il, decimal value) {
+ if (Decimal.Truncate(value) == value) {
+ if (Int32.MinValue <= value && value <= Int32.MaxValue) {
+ int intValue = Decimal.ToInt32(value);
+ il.EmitInt(intValue);
+ il.EmitNew(typeof(Decimal).GetConstructor(new Type[] { typeof(int) }));
+ } else if (Int64.MinValue <= value && value <= Int64.MaxValue) {
+ long longValue = Decimal.ToInt64(value);
+ il.EmitLong(longValue);
+ il.EmitNew(typeof(Decimal).GetConstructor(new Type[] { typeof(long) }));
+ } else {
+ il.EmitDecimalBits(value);
+ }
+ } else {
+ il.EmitDecimalBits(value);
+ }
+ }
+
+ private static void EmitDecimalBits(this ILGenerator il, decimal value) {
+ int[] bits = Decimal.GetBits(value);
+ il.EmitInt(bits[0]);
+ il.EmitInt(bits[1]);
+ il.EmitInt(bits[2]);
+ il.EmitBoolean((bits[3] & 0x80000000) != 0);
+ il.EmitByte((byte)(bits[3] >> 16));
+ il.EmitNew(typeof(decimal).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte) }));
+ }
+
+ /// <summary>
+ /// Emits default(T)
+ /// Semantics match C# compiler behavior
+ /// </summary>
+ internal static void EmitDefault(this ILGenerator il, Type type) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.Object:
+ case TypeCode.DateTime:
+ if (type.IsValueType) {
+ // Type.GetTypeCode on an enum returns the underlying
+ // integer TypeCode, so we won't get here.
+ Debug.Assert(!type.IsEnum);
+
+ // This is the IL for default(T) if T is a generic type
+ // parameter, so it should work for any type. It's also
+ // the standard pattern for structs.
+ LocalBuilder lb = il.DeclareLocal(type);
+ il.Emit(OpCodes.Ldloca, lb);
+ il.Emit(OpCodes.Initobj, type);
+ il.Emit(OpCodes.Ldloc, lb);
+ } else {
+ il.Emit(OpCodes.Ldnull);
+ }
+ break;
+
+ case TypeCode.Empty:
+ case TypeCode.String:
+ case TypeCode.DBNull:
+ il.Emit(OpCodes.Ldnull);
+ break;
+
+ case TypeCode.Boolean:
+ case TypeCode.Char:
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ il.Emit(OpCodes.Ldc_I4_0);
+ break;
+
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ il.Emit(OpCodes.Ldc_I4_0);
+ il.Emit(OpCodes.Conv_I8);
+ break;
+
+ case TypeCode.Single:
+ il.Emit(OpCodes.Ldc_R4, default(Single));
+ break;
+
+ case TypeCode.Double:
+ il.Emit(OpCodes.Ldc_R8, default(Double));
+ break;
+
+ case TypeCode.Decimal:
+ il.Emit(OpCodes.Ldc_I4_0);
+ il.Emit(OpCodes.Newobj, typeof(Decimal).GetConstructor(new Type[] { typeof(int) }));
+ break;
+
+ default:
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/KeyedQueue.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/KeyedQueue.cs
new file mode 100644
index 00000000000..464293c9c63
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/KeyedQueue.cs
@@ -0,0 +1,95 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ /// <summary>
+ /// A simple dictionary of queues, keyed off a particular type
+ /// This is useful for storing free lists of variables
+ /// </summary>
+ internal sealed class KeyedQueue<K, V> {
+ private readonly Dictionary<K, Queue<V>> _data;
+
+ internal KeyedQueue() {
+ _data = new Dictionary<K, Queue<V>>();
+ }
+
+ internal void Enqueue(K key, V value) {
+ Queue<V> queue;
+ if (!_data.TryGetValue(key, out queue)) {
+ _data.Add(key, queue = new Queue<V>());
+ }
+ queue.Enqueue(value);
+ }
+
+ internal V Dequeue(K key) {
+ Queue<V> queue;
+ if (!_data.TryGetValue(key, out queue)) {
+ throw Error.QueueEmpty();
+ }
+ V result = queue.Dequeue();
+ if (queue.Count == 0) {
+ _data.Remove(key);
+ }
+ return result;
+ }
+
+ internal bool TryDequeue(K key, out V value) {
+ Queue<V> queue;
+ if (_data.TryGetValue(key, out queue) && queue.Count > 0) {
+ value = queue.Dequeue();
+ if (queue.Count == 0) {
+ _data.Remove(key);
+ }
+ return true;
+ }
+ value = default(V);
+ return false;
+ }
+
+ internal V Peek(K key) {
+ Queue<V> queue;
+ if (!_data.TryGetValue(key, out queue)) {
+ throw Error.QueueEmpty();
+ }
+ return queue.Peek();
+ }
+
+ internal int GetCount(K key) {
+ Queue<V> queue;
+ if (!_data.TryGetValue(key, out queue)) {
+ return 0;
+ }
+ return queue.Count;
+ }
+
+ internal void Clear() {
+ _data.Clear();
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LabelInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LabelInfo.cs
new file mode 100644
index 00000000000..ad35a95e270
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LabelInfo.cs
@@ -0,0 +1,365 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#else
+using ILGenerator = Microsoft.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#endif
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection.Emit;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ /// <summary>
+ /// Contains compiler state corresponding to a LabelTarget
+ /// See also LabelScopeInfo.
+ /// </summary>
+ internal sealed class LabelInfo {
+ // The tree node representing this label
+ private readonly LabelTarget _node;
+
+ // The IL label, will be mutated if Node is redefined
+ private Label _label;
+ private bool _labelDefined;
+
+ internal Label Label {
+ get {
+ EnsureLabelAndValue();
+ return _label;
+ }
+ }
+
+ // The local that carries the label's value, if any
+ private LocalBuilder _value;
+
+ // The blocks where this label is defined. If it has more than one item,
+ // the blocks can't be jumped to except from a child block
+ private readonly Set<LabelScopeInfo> _definitions = new Set<LabelScopeInfo>();
+
+ // Blocks that jump to this block
+ private readonly List<LabelScopeInfo> _references = new List<LabelScopeInfo>();
+
+ // True if this label is the last thing in this block
+ // (meaning we can emit a direct return)
+ private readonly bool _canReturn;
+
+ // True if at least one jump is across blocks
+ // If we have any jump across blocks to this label, then the
+ // LabelTarget can only be defined in one place
+ private bool _acrossBlockJump;
+
+ // Until we have more information, default to a leave instruction,
+ // which always works. Note: leave spills the stack, so we need to
+ // ensure that StackSpiller has guarenteed us an empty stack at this
+ // point. Otherwise Leave and Branch are not equivalent
+ private OpCode _opCode = OpCodes.Leave;
+
+ private readonly ILGenerator _ilg;
+
+ internal LabelInfo(ILGenerator il, LabelTarget node, bool canReturn) {
+ _ilg = il;
+ _node = node;
+ _canReturn = canReturn;
+ }
+
+ internal bool CanReturn {
+ get { return _canReturn; }
+ }
+
+ /// <summary>
+ /// Indicates if it is legal to emit a "branch" instruction based on
+ /// currently available information. Call the Reference method before
+ /// using this property.
+ /// </summary>
+ internal bool CanBranch {
+ get { return _opCode != OpCodes.Leave; }
+ }
+
+ internal void Reference(LabelScopeInfo block) {
+ _references.Add(block);
+ if (_definitions.Count > 0) {
+ ValidateJump(block);
+ }
+ }
+
+ // Returns true if the label was successfully defined
+ // or false if the label is now ambiguous
+ internal void Define(LabelScopeInfo block) {
+ // Prevent the label from being shadowed, which enforces cleaner
+ // trees. Also we depend on this for simplicity (keeping only one
+ // active IL Label per LabelInfo)
+ for (LabelScopeInfo j = block; j != null; j = j.Parent) {
+ if (j.ContainsTarget(_node)) {
+ throw Error.LabelTargetAlreadyDefined(_node.Name);
+ }
+ }
+
+ _definitions.Add(block);
+ block.AddLabelInfo(_node, this);
+
+ // Once defined, validate all jumps
+ if (_definitions.Count == 1) {
+ foreach (var r in _references) {
+ ValidateJump(r);
+ }
+ } else {
+ // Was just redefined, if we had any across block jumps, they're
+ // now invalid
+ if (_acrossBlockJump) {
+ throw Error.AmbiguousJump(_node.Name);
+ }
+ // For local jumps, we need a new IL label
+ // This is okay because:
+ // 1. no across block jumps have been made or will be made
+ // 2. we don't allow the label to be shadowed
+ _labelDefined = false;
+ }
+ }
+
+ private void ValidateJump(LabelScopeInfo reference) {
+ // Assume we can do a ret/branch
+ _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;
+
+ // look for a simple jump out
+ for (LabelScopeInfo j = reference; j != null; j = j.Parent) {
+ if (_definitions.Contains(j)) {
+ // found it, jump is valid!
+ return;
+ }
+ if (j.Kind == LabelScopeKind.Finally ||
+ j.Kind == LabelScopeKind.Filter) {
+ break;
+ }
+ if (j.Kind == LabelScopeKind.Try ||
+ j.Kind == LabelScopeKind.Catch) {
+ _opCode = OpCodes.Leave;
+ }
+ }
+
+ _acrossBlockJump = true;
+ if (_node != null && _node.Type != typeof(void)) {
+ throw Error.NonLocalJumpWithValue(_node.Name);
+ }
+
+ if (_definitions.Count > 1) {
+ throw Error.AmbiguousJump(_node.Name);
+ }
+
+ // We didn't find an outward jump. Look for a jump across blocks
+ LabelScopeInfo def = _definitions.First();
+ LabelScopeInfo common = Helpers.CommonNode(def, reference, b => b.Parent);
+
+ // Assume we can do a ret/branch
+ _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;
+
+ // Validate that we aren't jumping across a finally
+ for (LabelScopeInfo j = reference; j != common; j = j.Parent) {
+ if (j.Kind == LabelScopeKind.Finally) {
+ throw Error.ControlCannotLeaveFinally();
+ }
+ if (j.Kind == LabelScopeKind.Filter) {
+ throw Error.ControlCannotLeaveFilterTest();
+ }
+ if (j.Kind == LabelScopeKind.Try ||
+ j.Kind == LabelScopeKind.Catch) {
+ _opCode = OpCodes.Leave;
+ }
+ }
+
+ // Valdiate that we aren't jumping into a catch or an expression
+ for (LabelScopeInfo j = def; j != common; j = j.Parent) {
+ if (!j.CanJumpInto) {
+ if (j.Kind == LabelScopeKind.Expression) {
+ throw Error.ControlCannotEnterExpression();
+ } else {
+ throw Error.ControlCannotEnterTry();
+ }
+ }
+ }
+ }
+
+ internal void ValidateFinish() {
+ // Make sure that if this label was jumped to, it is also defined
+ if (_references.Count > 0 && _definitions.Count == 0) {
+ throw Error.LabelTargetUndefined(_node.Name);
+ }
+ }
+
+ internal void EmitJump() {
+ // Return directly if we can
+ if (_opCode == OpCodes.Ret) {
+ _ilg.Emit(OpCodes.Ret);
+ } else {
+ StoreValue();
+ _ilg.Emit(_opCode, Label);
+ }
+ }
+
+ private void StoreValue() {
+ EnsureLabelAndValue();
+ if (_value != null) {
+ _ilg.Emit(OpCodes.Stloc, _value);
+ }
+ }
+
+ internal void Mark() {
+ if (_canReturn) {
+ // Don't mark return labels unless they were actually jumped to
+ // (returns are last so we know for sure if anyone jumped to it)
+ if (!_labelDefined) {
+ // We don't even need to emit the "ret" because
+ // LambdaCompiler does that for us.
+ return;
+ }
+
+ // Otherwise, emit something like:
+ // ret
+ // <marked label>:
+ // ldloc <value>
+ _ilg.Emit(OpCodes.Ret);
+ } else {
+
+ // For the normal case, we emit:
+ // stloc <value>
+ // <marked label>:
+ // ldloc <value>
+ StoreValue();
+ }
+ MarkWithEmptyStack();
+ }
+
+ // Like Mark, but assumes the stack is empty
+ internal void MarkWithEmptyStack() {
+ _ilg.MarkLabel(Label);
+ if (_value != null) {
+ // We always read the value from a local, because we don't know
+ // if there will be a "leave" instruction targeting it ("branch"
+ // preserves its stack, but "leave" empties the stack)
+ _ilg.Emit(OpCodes.Ldloc, _value);
+ }
+ }
+
+ private void EnsureLabelAndValue() {
+ if (!_labelDefined) {
+ _labelDefined = true;
+ _label = _ilg.DefineLabel();
+ if (_node != null && _node.Type != typeof(void)) {
+ _value = _ilg.DeclareLocal(_node.Type);
+ }
+ }
+ }
+ }
+
+ internal enum LabelScopeKind {
+ // any "statement like" node that can be jumped into
+ Statement,
+
+ // these correspond to the node of the same name
+ Block,
+ Switch,
+ Lambda,
+ Try,
+
+ // these correspond to the part of the try block we're in
+ Catch,
+ Finally,
+ Filter,
+
+ // the catch-all value for any other expression type
+ // (means we can't jump into it)
+ Expression,
+ }
+
+ //
+ // Tracks scoping information for LabelTargets. Logically corresponds to a
+ // "label scope". Even though we have arbitrary goto support, we still need
+ // to track what kinds of nodes that gotos are jumping through, both to
+ // emit property IL ("leave" out of a try block), and for validation, and
+ // to allow labels to be duplicated in the tree, as long as the jumps are
+ // considered "up only" jumps.
+ //
+ // We create one of these for every Expression that can be jumped into, as
+ // well as creating them for the first expression we can't jump into. The
+ // "Kind" property indicates what kind of scope this is.
+ //
+ internal sealed class LabelScopeInfo {
+ private Dictionary<LabelTarget, LabelInfo> Labels; // lazily allocated, we typically use this only once every 6th-7th block
+ internal readonly LabelScopeKind Kind;
+ internal readonly LabelScopeInfo Parent;
+
+ internal LabelScopeInfo(LabelScopeInfo parent, LabelScopeKind kind) {
+ Parent = parent;
+ Kind = kind;
+ }
+
+ /// <summary>
+ /// Returns true if we can jump into this node
+ /// </summary>
+ internal bool CanJumpInto {
+ get {
+ switch (Kind) {
+ case LabelScopeKind.Block:
+ case LabelScopeKind.Statement:
+ case LabelScopeKind.Switch:
+ case LabelScopeKind.Lambda:
+ return true;
+ }
+ return false;
+ }
+ }
+
+
+ internal bool ContainsTarget(LabelTarget target) {
+ if (Labels == null) {
+ return false;
+ }
+
+ return Labels.ContainsKey(target);
+ }
+
+ internal bool TryGetLabelInfo(LabelTarget target, out LabelInfo info) {
+ if (Labels == null) {
+ info = null;
+ return false;
+ }
+
+ return Labels.TryGetValue(target, out info);
+ }
+
+ internal void AddLabelInfo(LabelTarget target, LabelInfo info) {
+ Debug.Assert(CanJumpInto);
+
+ if (Labels == null) {
+ Labels = new Dictionary<LabelTarget, LabelInfo>();
+ }
+
+ Labels.Add(target, info);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Address.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Address.cs
new file mode 100644
index 00000000000..acdbcd33016
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Address.cs
@@ -0,0 +1,339 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ partial class LambdaCompiler {
+ private void EmitAddress(Expression node, Type type) {
+ EmitAddress(node, type, CompilationFlags.EmitExpressionStart);
+ }
+
+ // We don't want "ref" parameters to modify values of expressions
+ // except where it would in IL: locals, args, fields, and array elements
+ // (Unbox is an exception, it's intended to emit a ref to the orignal
+ // boxed value)
+ private void EmitAddress(Expression node, Type type, CompilationFlags flags) {
+ Debug.Assert(node != null);
+ bool emitStart = (flags & CompilationFlags.EmitExpressionStartMask) == CompilationFlags.EmitExpressionStart;
+ CompilationFlags startEmitted = emitStart ? EmitExpressionStart(node) : CompilationFlags.EmitNoExpressionStart;
+
+ switch (node.NodeType) {
+ default:
+ EmitExpressionAddress(node, type);
+ break;
+
+ case ExpressionType.ArrayIndex:
+ AddressOf((BinaryExpression)node, type);
+ break;
+
+ case ExpressionType.Parameter:
+ AddressOf((ParameterExpression)node, type);
+ break;
+
+ case ExpressionType.MemberAccess:
+ AddressOf((MemberExpression)node, type);
+ break;
+
+ case ExpressionType.Unbox:
+ AddressOf((UnaryExpression)node, type);
+ break;
+
+ case ExpressionType.Call:
+ AddressOf((MethodCallExpression)node, type);
+ break;
+
+ case ExpressionType.Index:
+ AddressOf((IndexExpression)node, type);
+ break;
+ }
+
+ if (emitStart) {
+ EmitExpressionEnd(startEmitted);
+ }
+ }
+
+
+ private void AddressOf(BinaryExpression node, Type type) {
+ Debug.Assert(node.NodeType == ExpressionType.ArrayIndex && node.Method == null);
+
+ if (TypeUtils.AreEquivalent(type, node.Type)) {
+ EmitExpression(node.Left);
+ EmitExpression(node.Right);
+ Type rightType = node.Right.Type;
+ if (TypeUtils.IsNullableType(rightType)) {
+ LocalBuilder loc = GetLocal(rightType);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitGetValue(rightType);
+ FreeLocal(loc);
+ }
+ Type indexType = TypeUtils.GetNonNullableType(rightType);
+ if (indexType != typeof(int)) {
+ _ilg.EmitConvertToType(indexType, typeof(int), true);
+ }
+ _ilg.Emit(OpCodes.Ldelema, node.Type);
+ } else {
+ EmitExpressionAddress(node, type);
+ }
+ }
+
+ private void AddressOf(ParameterExpression node, Type type) {
+ if (TypeUtils.AreEquivalent(type, node.Type)) {
+ if (node.IsByRef) {
+ _scope.EmitGet(node);
+ } else {
+ _scope.EmitAddressOf(node);
+ }
+ } else {
+ EmitExpressionAddress(node, type);
+ }
+ }
+
+
+ private void AddressOf(MemberExpression node, Type type) {
+ if (TypeUtils.AreEquivalent(type, node.Type)) {
+ // emit "this", if any
+ Type objectType = null;
+ if (node.Expression != null) {
+ EmitInstance(node.Expression, objectType = node.Expression.Type);
+ }
+ EmitMemberAddress(node.Member, objectType);
+ } else {
+ EmitExpressionAddress(node, type);
+ }
+ }
+
+ // assumes the instance is already on the stack
+ private void EmitMemberAddress(MemberInfo member, Type objectType) {
+ if (member.MemberType == MemberTypes.Field) {
+ FieldInfo field = (FieldInfo)member;
+
+ // Verifiable code may not take the address of an init-only field.
+ // If we are asked to do so then get the value out of the field, stuff it
+ // into a local of the same type, and then take the address of the local.
+ // Typically this is what we want to do anyway; if we are saying
+ // Foo.bar.ToString() for a static value-typed field bar then we don't need
+ // the address of field bar to do the call. The address of a local which
+ // has the same value as bar is sufficient.
+
+ // CONSIDER:
+ // The C# compiler will not compile a lambda expression tree
+ // which writes to the address of an init-only field. But one could
+ // probably use the expression tree API to build such an expression.
+ // (When compiled, such an expression would fail silently.) It might
+ // be worth it to add checking to the expression tree API to ensure
+ // that it is illegal to attempt to write to an init-only field,
+ // the same way that it is illegal to write to a read-only property.
+ // The same goes for literal fields.
+ if (!field.IsLiteral && !field.IsInitOnly) {
+ _ilg.EmitFieldAddress(field);
+ return;
+ }
+ }
+
+ EmitMemberGet(member, objectType);
+ LocalBuilder temp = GetLocal(GetMemberType(member));
+ _ilg.Emit(OpCodes.Stloc, temp);
+ _ilg.Emit(OpCodes.Ldloca, temp);
+ }
+
+
+ private void AddressOf(MethodCallExpression node, Type type) {
+ // An array index of a multi-dimensional array is represented by a call to Array.Get,
+ // rather than having its own array-access node. This means that when we are trying to
+ // get the address of a member of a multi-dimensional array, we'll be trying to
+ // get the address of a Get method, and it will fail to do so. Instead, detect
+ // this situation and replace it with a call to the Address method.
+ if (!node.Method.IsStatic &&
+ node.Object.Type.IsArray &&
+ node.Method == node.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)) {
+
+ MethodInfo mi = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance);
+
+ EmitMethodCall(node.Object, mi, node);
+ } else {
+ EmitExpressionAddress(node, type);
+ }
+ }
+
+ private void AddressOf(IndexExpression node, Type type) {
+ if (!TypeUtils.AreEquivalent(type, node.Type) || node.Indexer != null) {
+ EmitExpressionAddress(node, type);
+ return;
+ }
+
+ if (node.Arguments.Count == 1) {
+ EmitExpression(node.Object);
+ EmitExpression(node.Arguments[0]);
+ _ilg.Emit(OpCodes.Ldelema, node.Type);
+ } else {
+ var address = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance);
+ EmitMethodCall(node.Object, address, node);
+ }
+ }
+
+ private void AddressOf(UnaryExpression node, Type type) {
+ Debug.Assert(node.NodeType == ExpressionType.Unbox);
+ Debug.Assert(type.IsValueType && !TypeUtils.IsNullableType(type));
+
+ // Unbox leaves a pointer to the boxed value on the stack
+ EmitExpression(node.Operand);
+ _ilg.Emit(OpCodes.Unbox, type);
+ }
+
+ private void EmitExpressionAddress(Expression node, Type type) {
+ Debug.Assert(TypeUtils.AreReferenceAssignable(type, node.Type));
+
+ EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
+ LocalBuilder tmp = GetLocal(type);
+ _ilg.Emit(OpCodes.Stloc, tmp);
+ _ilg.Emit(OpCodes.Ldloca, tmp);
+ }
+
+
+ // Emits the address of the expression, returning the write back if necessary
+ //
+ // For properties, we want to write back into the property if it's
+ // passed byref.
+ private WriteBack EmitAddressWriteBack(Expression node, Type type) {
+ CompilationFlags startEmitted = EmitExpressionStart(node);
+
+ WriteBack result = null;
+ if (TypeUtils.AreEquivalent(type, node.Type)) {
+ switch (node.NodeType) {
+ case ExpressionType.MemberAccess:
+ result = AddressOfWriteBack((MemberExpression)node);
+ break;
+ case ExpressionType.Index:
+ result = AddressOfWriteBack((IndexExpression)node);
+ break;
+ }
+ }
+ if (result == null) {
+ EmitAddress(node, type, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
+ }
+
+ EmitExpressionEnd(startEmitted);
+
+ return result;
+ }
+
+ private WriteBack AddressOfWriteBack(MemberExpression node) {
+ if (node.Member.MemberType != MemberTypes.Property || !((PropertyInfo)node.Member).CanWrite) {
+ return null;
+ }
+
+ // emit instance, if any
+ LocalBuilder instanceLocal = null;
+ Type instanceType = null;
+ if (node.Expression != null) {
+ EmitInstance(node.Expression, instanceType = node.Expression.Type);
+ // store in local
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Stloc, instanceLocal = GetLocal(instanceType));
+ }
+
+ PropertyInfo pi = (PropertyInfo)node.Member;
+
+ // emit the get
+ EmitCall(instanceType, pi.GetGetMethod(true));
+
+ // emit the address of the value
+ var valueLocal = GetLocal(node.Type);
+ _ilg.Emit(OpCodes.Stloc, valueLocal);
+ _ilg.Emit(OpCodes.Ldloca, valueLocal);
+
+ // Set the property after the method call
+ // don't re-evaluate anything
+ return delegate() {
+ if (instanceLocal != null) {
+ _ilg.Emit(OpCodes.Ldloc, instanceLocal);
+ FreeLocal(instanceLocal);
+ }
+ _ilg.Emit(OpCodes.Ldloc, valueLocal);
+ FreeLocal(valueLocal);
+ EmitCall(instanceType, pi.GetSetMethod(true));
+ };
+ }
+
+ private WriteBack AddressOfWriteBack(IndexExpression node) {
+ if (node.Indexer == null || !node.Indexer.CanWrite) {
+ return null;
+ }
+
+ // emit instance, if any
+ LocalBuilder instanceLocal = null;
+ Type instanceType = null;
+ if (node.Object != null) {
+ EmitInstance(node.Object, instanceType = node.Object.Type);
+
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Stloc, instanceLocal = GetLocal(instanceType));
+ }
+
+ // Emit indexes. We don't allow byref args, so no need to worry
+ // about writebacks or EmitAddress
+ List<LocalBuilder> args = new List<LocalBuilder>();
+ foreach (var arg in node.Arguments) {
+ EmitExpression(arg);
+
+ var argLocal = GetLocal(arg.Type);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Stloc, argLocal);
+ args.Add(argLocal);
+ }
+
+ // emit the get
+ EmitGetIndexCall(node, instanceType);
+
+ // emit the address of the value
+ var valueLocal = GetLocal(node.Type);
+ _ilg.Emit(OpCodes.Stloc, valueLocal);
+ _ilg.Emit(OpCodes.Ldloca, valueLocal);
+
+ // Set the property after the method call
+ // don't re-evaluate anything
+ return delegate() {
+ if (instanceLocal != null) {
+ _ilg.Emit(OpCodes.Ldloc, instanceLocal);
+ FreeLocal(instanceLocal);
+ }
+ foreach (var arg in args) {
+ _ilg.Emit(OpCodes.Ldloc, arg);
+ FreeLocal(arg);
+ }
+ _ilg.Emit(OpCodes.Ldloc, valueLocal);
+ FreeLocal(valueLocal);
+
+ EmitSetIndexCall(node, instanceType);
+ };
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs
new file mode 100644
index 00000000000..03a18d04f6a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs
@@ -0,0 +1,706 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ partial class LambdaCompiler {
+
+ private void EmitBinaryExpression(Expression expr) {
+ EmitBinaryExpression(expr, CompilationFlags.EmitAsNoTail);
+ }
+
+ private void EmitBinaryExpression(Expression expr, CompilationFlags flags) {
+ BinaryExpression b = (BinaryExpression)expr;
+
+ Debug.Assert(b.NodeType != ExpressionType.AndAlso && b.NodeType != ExpressionType.OrElse && b.NodeType != ExpressionType.Coalesce);
+
+ if (b.Method != null) {
+ EmitBinaryMethod(b, flags);
+ return;
+ }
+
+ // For EQ and NE, if there is a user-specified method, use it.
+ // Otherwise implement the C# semantics that allow equality
+ // comparisons on non-primitive nullable structs that don't
+ // overload "=="
+ if ((b.NodeType == ExpressionType.Equal || b.NodeType == ExpressionType.NotEqual) &&
+ (b.Type == typeof(bool) || b.Type == typeof(bool?))) {
+
+ // If we have x==null, x!=null, null==x or null!=x where x is
+ // nullable but not null, then generate a call to x.HasValue.
+ Debug.Assert(!b.IsLiftedToNull || b.Type == typeof(bool?));
+ if (ConstantCheck.IsNull(b.Left) && !ConstantCheck.IsNull(b.Right) && TypeUtils.IsNullableType(b.Right.Type)) {
+ EmitNullEquality(b.NodeType, b.Right, b.IsLiftedToNull);
+ return;
+ }
+ if (ConstantCheck.IsNull(b.Right) && !ConstantCheck.IsNull(b.Left) && TypeUtils.IsNullableType(b.Left.Type)) {
+ EmitNullEquality(b.NodeType, b.Left, b.IsLiftedToNull);
+ return;
+ }
+
+ // For EQ and NE, we can avoid some conversions if we're
+ // ultimately just comparing two managed pointers.
+ EmitExpression(GetEqualityOperand(b.Left));
+ EmitExpression(GetEqualityOperand(b.Right));
+ } else {
+ // Otherwise generate it normally
+ EmitExpression(b.Left);
+ EmitExpression(b.Right);
+ }
+
+ EmitBinaryOperator(b.NodeType, b.Left.Type, b.Right.Type, b.Type, b.IsLiftedToNull);
+ }
+
+
+ private void EmitNullEquality(ExpressionType op, Expression e, bool isLiftedToNull) {
+ Debug.Assert(TypeUtils.IsNullableType(e.Type));
+ Debug.Assert(op == ExpressionType.Equal || op == ExpressionType.NotEqual);
+ // If we are lifted to null then just evaluate the expression for its side effects, discard,
+ // and generate null. If we are not lifted to null then generate a call to HasValue.
+ if (isLiftedToNull) {
+ EmitExpressionAsVoid(e);
+ _ilg.EmitDefault(typeof(bool?));
+ } else {
+ EmitAddress(e, e.Type);
+ _ilg.EmitHasValue(e.Type);
+ if (op == ExpressionType.Equal) {
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ }
+ }
+ }
+
+
+ private void EmitBinaryMethod(BinaryExpression b, CompilationFlags flags) {
+ if (b.IsLifted) {
+ ParameterExpression p1 = Expression.Variable(TypeUtils.GetNonNullableType(b.Left.Type), null);
+ ParameterExpression p2 = Expression.Variable(TypeUtils.GetNonNullableType(b.Right.Type), null);
+ MethodCallExpression mc = Expression.Call(null, b.Method, p1, p2);
+ Type resultType = null;
+ if (b.IsLiftedToNull) {
+ resultType = TypeUtils.GetNullableType(mc.Type);
+ } else {
+ switch (b.NodeType) {
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ if (mc.Type != typeof(bool)) {
+ throw Error.ArgumentMustBeBoolean();
+ }
+ resultType = typeof(bool);
+ break;
+ default:
+ resultType = TypeUtils.GetNullableType(mc.Type);
+ break;
+ }
+ }
+ var variables = new ParameterExpression[] { p1, p2 };
+ var arguments = new Expression[] { b.Left, b.Right };
+ ValidateLift(variables, arguments);
+ EmitLift(b.NodeType, resultType, mc, variables, arguments);
+ } else {
+ EmitMethodCallExpression(Expression.Call(null, b.Method, b.Left, b.Right), flags);
+ }
+ }
+
+
+ private void EmitBinaryOperator(ExpressionType op, Type leftType, Type rightType, Type resultType, bool liftedToNull) {
+ bool leftIsNullable = TypeUtils.IsNullableType(leftType);
+ bool rightIsNullable = TypeUtils.IsNullableType(rightType);
+
+ switch (op) {
+ case ExpressionType.ArrayIndex:
+ if (rightType != typeof(int)) {
+ throw ContractUtils.Unreachable;
+ }
+ _ilg.EmitLoadElement(leftType.GetElementType());
+ return;
+ case ExpressionType.Coalesce:
+ throw Error.UnexpectedCoalesceOperator();
+ }
+
+ if (leftIsNullable || rightIsNullable) {
+ EmitLiftedBinaryOp(op, leftType, rightType, resultType, liftedToNull);
+ } else {
+ EmitUnliftedBinaryOp(op, leftType, rightType);
+ EmitConvertArithmeticResult(op, resultType);
+ }
+ }
+
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private void EmitUnliftedBinaryOp(ExpressionType op, Type leftType, Type rightType) {
+ Debug.Assert(!TypeUtils.IsNullableType(leftType));
+ Debug.Assert(!TypeUtils.IsNullableType(rightType));
+
+ if (op == ExpressionType.Equal || op == ExpressionType.NotEqual) {
+ EmitUnliftedEquality(op, leftType);
+ return;
+ }
+ if (!leftType.IsPrimitive) {
+ throw Error.OperatorNotImplementedForType(op, leftType);
+ }
+ switch (op) {
+ case ExpressionType.Add:
+ _ilg.Emit(OpCodes.Add);
+ break;
+ case ExpressionType.AddChecked:
+ if (TypeUtils.IsFloatingPoint(leftType)) {
+ _ilg.Emit(OpCodes.Add);
+ } else if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Add_Ovf_Un);
+ } else {
+ _ilg.Emit(OpCodes.Add_Ovf);
+ }
+ break;
+ case ExpressionType.Subtract:
+ _ilg.Emit(OpCodes.Sub);
+ break;
+ case ExpressionType.SubtractChecked:
+ if (TypeUtils.IsFloatingPoint(leftType)) {
+ _ilg.Emit(OpCodes.Sub);
+ } else if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Sub_Ovf_Un);
+ } else {
+ _ilg.Emit(OpCodes.Sub_Ovf);
+ }
+ break;
+ case ExpressionType.Multiply:
+ _ilg.Emit(OpCodes.Mul);
+ break;
+ case ExpressionType.MultiplyChecked:
+ if (TypeUtils.IsFloatingPoint(leftType)) {
+ _ilg.Emit(OpCodes.Mul);
+ } else if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Mul_Ovf_Un);
+ } else {
+ _ilg.Emit(OpCodes.Mul_Ovf);
+ }
+ break;
+ case ExpressionType.Divide:
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Div_Un);
+ } else {
+ _ilg.Emit(OpCodes.Div);
+ }
+ break;
+ case ExpressionType.Modulo:
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Rem_Un);
+ } else {
+ _ilg.Emit(OpCodes.Rem);
+ }
+ break;
+ case ExpressionType.And:
+ case ExpressionType.AndAlso:
+ _ilg.Emit(OpCodes.And);
+ break;
+ case ExpressionType.Or:
+ case ExpressionType.OrElse:
+ _ilg.Emit(OpCodes.Or);
+ break;
+ case ExpressionType.LessThan:
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Clt_Un);
+ } else {
+ _ilg.Emit(OpCodes.Clt);
+ }
+ break;
+ case ExpressionType.LessThanOrEqual: {
+ Label labFalse = _ilg.DefineLabel();
+ Label labEnd = _ilg.DefineLabel();
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Ble_Un_S, labFalse);
+ } else {
+ _ilg.Emit(OpCodes.Ble_S, labFalse);
+ }
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br_S, labEnd);
+ _ilg.MarkLabel(labFalse);
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.MarkLabel(labEnd);
+ }
+ break;
+ case ExpressionType.GreaterThan:
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Cgt_Un);
+ } else {
+ _ilg.Emit(OpCodes.Cgt);
+ }
+ break;
+ case ExpressionType.GreaterThanOrEqual: {
+ Label labFalse = _ilg.DefineLabel();
+ Label labEnd = _ilg.DefineLabel();
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Bge_Un_S, labFalse);
+ } else {
+ _ilg.Emit(OpCodes.Bge_S, labFalse);
+ }
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br_S, labEnd);
+ _ilg.MarkLabel(labFalse);
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.MarkLabel(labEnd);
+ }
+ break;
+ case ExpressionType.ExclusiveOr:
+ _ilg.Emit(OpCodes.Xor);
+ break;
+ case ExpressionType.LeftShift:
+ if (rightType != typeof(int)) {
+ throw ContractUtils.Unreachable;
+ }
+ _ilg.Emit(OpCodes.Shl);
+ break;
+ case ExpressionType.RightShift:
+ if (rightType != typeof(int)) {
+ throw ContractUtils.Unreachable;
+ }
+ if (TypeUtils.IsUnsigned(leftType)) {
+ _ilg.Emit(OpCodes.Shr_Un);
+ } else {
+ _ilg.Emit(OpCodes.Shr);
+ }
+ break;
+ default:
+ throw Error.UnhandledBinary(op);
+ }
+ }
+
+ // Binary/unary operations on 8 and 16 bit operand types will leave a
+ // 32-bit value on the stack, because that's how IL works. For these
+ // cases, we need to cast it back to the resultType, possibly using a
+ // checked conversion if the original operator was convert
+ private void EmitConvertArithmeticResult(ExpressionType op, Type resultType) {
+ Debug.Assert(!resultType.IsNullableType());
+
+ switch (Type.GetTypeCode(resultType)) {
+ case TypeCode.Byte:
+ _ilg.Emit(IsChecked(op) ? OpCodes.Conv_Ovf_U1 : OpCodes.Conv_U1);
+ break;
+ case TypeCode.SByte:
+ _ilg.Emit(IsChecked(op) ? OpCodes.Conv_Ovf_I1 : OpCodes.Conv_I1);
+ break;
+ case TypeCode.UInt16:
+ _ilg.Emit(IsChecked(op) ? OpCodes.Conv_Ovf_U2 : OpCodes.Conv_U2);
+ break;
+ case TypeCode.Int16:
+ _ilg.Emit(IsChecked(op) ? OpCodes.Conv_Ovf_I2 : OpCodes.Conv_I2);
+ break;
+ }
+ }
+
+ private void EmitUnliftedEquality(ExpressionType op, Type type) {
+ Debug.Assert(op == ExpressionType.Equal || op == ExpressionType.NotEqual);
+ if (!type.IsPrimitive && type.IsValueType && !type.IsEnum) {
+ throw Error.OperatorNotImplementedForType(op, type);
+ }
+ _ilg.Emit(OpCodes.Ceq);
+ if (op == ExpressionType.NotEqual) {
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ }
+ }
+
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private void EmitLiftedBinaryOp(ExpressionType op, Type leftType, Type rightType, Type resultType, bool liftedToNull) {
+ Debug.Assert(TypeUtils.IsNullableType(leftType) || TypeUtils.IsNullableType(rightType));
+ switch (op) {
+ case ExpressionType.And:
+ if (leftType == typeof(bool?)) {
+ EmitLiftedBooleanAnd();
+ } else {
+ EmitLiftedBinaryArithmetic(op, leftType, rightType, resultType);
+ }
+ break;
+ case ExpressionType.Or:
+ if (leftType == typeof(bool?)) {
+ EmitLiftedBooleanOr();
+ } else {
+ EmitLiftedBinaryArithmetic(op, leftType, rightType, resultType);
+ }
+ break;
+ case ExpressionType.ExclusiveOr:
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ case ExpressionType.LeftShift:
+ case ExpressionType.RightShift:
+ EmitLiftedBinaryArithmetic(op, leftType, rightType, resultType);
+ break;
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ EmitLiftedRelational(op, leftType, rightType, resultType, liftedToNull);
+ break;
+ case ExpressionType.AndAlso:
+ case ExpressionType.OrElse:
+ default:
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+
+ private void EmitLiftedRelational(ExpressionType op, Type leftType, Type rightType, Type resultType, bool liftedToNull) {
+ Debug.Assert(TypeUtils.IsNullableType(leftType));
+
+ Label shortCircuit = _ilg.DefineLabel();
+ LocalBuilder locLeft = GetLocal(leftType);
+ LocalBuilder locRight = GetLocal(rightType);
+
+ // store values (reverse order since they are already on the stack)
+ _ilg.Emit(OpCodes.Stloc, locRight);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+
+ if (op == ExpressionType.Equal) {
+ // test for both null -> true
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(leftType);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(rightType);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.And);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Brtrue_S, shortCircuit);
+ _ilg.Emit(OpCodes.Pop);
+
+ // test for either is null -> false
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(leftType);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(rightType);
+ _ilg.Emit(OpCodes.And);
+
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Brfalse_S, shortCircuit);
+ _ilg.Emit(OpCodes.Pop);
+ } else if (op == ExpressionType.NotEqual) {
+ // test for both null -> false
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(leftType);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(rightType);
+ _ilg.Emit(OpCodes.Or);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Brfalse_S, shortCircuit);
+ _ilg.Emit(OpCodes.Pop);
+
+ // test for either is null -> true
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(leftType);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(rightType);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Or);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Brtrue_S, shortCircuit);
+ _ilg.Emit(OpCodes.Pop);
+ } else {
+ // test for either is null -> false
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(leftType);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(rightType);
+ _ilg.Emit(OpCodes.And);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Brfalse_S, shortCircuit);
+ _ilg.Emit(OpCodes.Pop);
+ }
+
+ // do op on values
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitGetValueOrDefault(leftType);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitGetValueOrDefault(rightType);
+
+ //RELEASING locLeft locRight
+ FreeLocal(locLeft);
+ FreeLocal(locRight);
+
+ EmitBinaryOperator(
+ op,
+ TypeUtils.GetNonNullableType(leftType),
+ TypeUtils.GetNonNullableType(rightType),
+ TypeUtils.GetNonNullableType(resultType),
+ false
+ );
+
+ if (!liftedToNull) {
+ _ilg.MarkLabel(shortCircuit);
+ }
+
+ if (!TypeUtils.AreEquivalent(resultType, TypeUtils.GetNonNullableType(resultType))) {
+ _ilg.EmitConvertToType(TypeUtils.GetNonNullableType(resultType), resultType, true);
+ }
+
+ if (liftedToNull) {
+ Label labEnd = _ilg.DefineLabel();
+ _ilg.Emit(OpCodes.Br, labEnd);
+ _ilg.MarkLabel(shortCircuit);
+ _ilg.Emit(OpCodes.Pop);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Unbox_Any, resultType);
+ _ilg.MarkLabel(labEnd);
+ }
+ }
+
+
+ private void EmitLiftedBinaryArithmetic(ExpressionType op, Type leftType, Type rightType, Type resultType) {
+ bool leftIsNullable = TypeUtils.IsNullableType(leftType);
+ bool rightIsNullable = TypeUtils.IsNullableType(rightType);
+
+ Debug.Assert(leftIsNullable || rightIsNullable);
+
+ Label labIfNull = _ilg.DefineLabel();
+ Label labEnd = _ilg.DefineLabel();
+ LocalBuilder locLeft = GetLocal(leftType);
+ LocalBuilder locRight = GetLocal(rightType);
+ LocalBuilder locResult = GetLocal(resultType);
+
+ // store values (reverse order since they are already on the stack)
+ _ilg.Emit(OpCodes.Stloc, locRight);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+
+ // test for null
+ // use short circuiting
+ if (leftIsNullable) {
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(leftType);
+ _ilg.Emit(OpCodes.Brfalse_S, labIfNull);
+ }
+ if (rightIsNullable) {
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(rightType);
+ _ilg.Emit(OpCodes.Brfalse_S, labIfNull);
+ }
+
+ // do op on values
+ if (leftIsNullable) {
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitGetValueOrDefault(leftType);
+ } else {
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+ }
+
+ if (rightIsNullable) {
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitGetValueOrDefault(rightType);
+ } else {
+ _ilg.Emit(OpCodes.Ldloc, locRight);
+ }
+
+ //RELEASING locLeft locRight
+ FreeLocal(locLeft);
+ FreeLocal(locRight);
+
+ EmitBinaryOperator(op, TypeUtils.GetNonNullableType(leftType), TypeUtils.GetNonNullableType(rightType), TypeUtils.GetNonNullableType(resultType), false);
+
+ // construct result type
+ ConstructorInfo ci = resultType.GetConstructor(new Type[] { TypeUtils.GetNonNullableType(resultType) });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, locResult);
+ _ilg.Emit(OpCodes.Br_S, labEnd);
+
+ // if null then create a default one
+ _ilg.MarkLabel(labIfNull);
+ _ilg.Emit(OpCodes.Ldloca, locResult);
+ _ilg.Emit(OpCodes.Initobj, resultType);
+
+ _ilg.MarkLabel(labEnd);
+
+ _ilg.Emit(OpCodes.Ldloc, locResult);
+
+ //RELEASING locResult
+ FreeLocal(locResult);
+ }
+
+
+ private void EmitLiftedBooleanAnd() {
+ Type type = typeof(bool?);
+ Label labComputeRight = _ilg.DefineLabel();
+ Label labReturnFalse = _ilg.DefineLabel();
+ Label labReturnNull = _ilg.DefineLabel();
+ Label labReturnValue = _ilg.DefineLabel();
+ Label labExit = _ilg.DefineLabel();
+
+ // store values (reverse order since they are already on the stack)
+ LocalBuilder locLeft = GetLocal(type);
+ LocalBuilder locRight = GetLocal(type);
+ _ilg.Emit(OpCodes.Stloc, locRight);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+
+ // compute left
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labComputeRight);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brtrue, labReturnFalse);
+
+ // compute right
+ _ilg.MarkLabel(labComputeRight);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse_S, labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+
+ //RELEASING locRight
+ FreeLocal(locRight);
+
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brtrue_S, labReturnFalse);
+
+ // check left for null again
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labReturnNull);
+
+ // return true
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+
+ // return false
+ _ilg.MarkLabel(labReturnFalse);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+
+ _ilg.MarkLabel(labReturnValue);
+ ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(bool) });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+ _ilg.Emit(OpCodes.Br, labExit);
+
+ // return null
+ _ilg.MarkLabel(labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.Emit(OpCodes.Initobj, type);
+
+ _ilg.MarkLabel(labExit);
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+
+ //RELEASING locLeft
+ FreeLocal(locLeft);
+ }
+
+
+ private void EmitLiftedBooleanOr() {
+ Type type = typeof(bool?);
+ Label labComputeRight = _ilg.DefineLabel();
+ Label labReturnTrue = _ilg.DefineLabel();
+ Label labReturnNull = _ilg.DefineLabel();
+ Label labReturnValue = _ilg.DefineLabel();
+ Label labExit = _ilg.DefineLabel();
+
+ // store values (reverse order since they are already on the stack)
+ LocalBuilder locLeft = GetLocal(type);
+ LocalBuilder locRight = GetLocal(type);
+ _ilg.Emit(OpCodes.Stloc, locRight);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+
+ // compute left
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labComputeRight);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse, labReturnTrue);
+
+ // compute right
+ _ilg.MarkLabel(labComputeRight);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse_S, labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+
+ //RELEASING locRight
+ FreeLocal(locRight);
+
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse_S, labReturnTrue);
+
+ // check left for null again
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labReturnNull);
+
+ // return false
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+
+ // return true
+ _ilg.MarkLabel(labReturnTrue);
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+
+ _ilg.MarkLabel(labReturnValue);
+ ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(bool) });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+ _ilg.Emit(OpCodes.Br, labExit);
+
+ // return null
+ _ilg.MarkLabel(labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.Emit(OpCodes.Initobj, type);
+
+ _ilg.MarkLabel(labExit);
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+
+ //RELEASING locLeft
+ FreeLocal(locLeft);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.ControlFlow.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.ControlFlow.cs
new file mode 100644
index 00000000000..2b9de7c56ac
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.ControlFlow.cs
@@ -0,0 +1,263 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ // The part of the LambdaCompiler dealing with low level control flow
+ // break, contiue, return, exceptions, etc
+ partial class LambdaCompiler {
+
+ private LabelInfo EnsureLabel(LabelTarget node) {
+ LabelInfo result;
+ if (!_labelInfo.TryGetValue(node, out result)) {
+ _labelInfo.Add(node, result = new LabelInfo(_ilg, node, false));
+ }
+ return result;
+ }
+
+ private LabelInfo ReferenceLabel(LabelTarget node) {
+ LabelInfo result = EnsureLabel(node);
+ result.Reference(_labelBlock);
+ return result;
+ }
+
+ private LabelInfo DefineLabel(LabelTarget node) {
+ if (node == null) {
+ return new LabelInfo(_ilg, null, false);
+ }
+ LabelInfo result = EnsureLabel(node);
+ result.Define(_labelBlock);
+ return result;
+ }
+
+ private void PushLabelBlock(LabelScopeKind type) {
+ _labelBlock = new LabelScopeInfo(_labelBlock, type);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kind")]
+ private void PopLabelBlock(LabelScopeKind kind) {
+ Debug.Assert(_labelBlock != null && _labelBlock.Kind == kind);
+ _labelBlock = _labelBlock.Parent;
+ }
+
+ private void EmitLabelExpression(Expression expr, CompilationFlags flags) {
+ var node = (LabelExpression)expr;
+ Debug.Assert(node.Target != null);
+
+ // If we're an immediate child of a block, our label will already
+ // be defined. If not, we need to define our own block so this
+ // label isn't exposed except to its own child expression.
+ LabelInfo label = null;
+
+ if (_labelBlock.Kind == LabelScopeKind.Block) {
+ _labelBlock.TryGetLabelInfo(node.Target, out label);
+
+ // We're in a block but didn't find our label, try switch
+ if (label == null && _labelBlock.Parent.Kind == LabelScopeKind.Switch) {
+ _labelBlock.Parent.TryGetLabelInfo(node.Target, out label);
+ }
+
+ // if we're in a switch or block, we should've found the label
+ Debug.Assert(label != null);
+ }
+
+ if (label == null) {
+ label = DefineLabel(node.Target);
+ }
+
+ if (node.DefaultValue != null) {
+ if (node.Target.Type == typeof(void)) {
+ EmitExpressionAsVoid(node.DefaultValue, flags);
+ } else {
+ flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart);
+ EmitExpression(node.DefaultValue, flags);
+ }
+ }
+
+ label.Mark();
+ }
+
+ private void EmitGotoExpression(Expression expr, CompilationFlags flags) {
+ var node = (GotoExpression)expr;
+ var labelInfo = ReferenceLabel(node.Target);
+
+ var tailCall = flags & CompilationFlags.EmitAsTailCallMask;
+ if (tailCall != CompilationFlags.EmitAsNoTail) {
+ // Since tail call flags are not passed into EmitTryExpression, CanReturn
+ // means the goto will be emitted as Ret. Therefore we can emit the goto's
+ // default value with tail call. This can be improved by detecting if the
+ // target label is equivalent to the return label.
+ tailCall = labelInfo.CanReturn ? CompilationFlags.EmitAsTail : CompilationFlags.EmitAsNoTail;
+ flags = UpdateEmitAsTailCallFlag(flags, tailCall);
+ }
+
+ if (node.Value != null) {
+ if (node.Target.Type == typeof(void)) {
+ EmitExpressionAsVoid(node.Value, flags);
+ } else {
+ flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart);
+ EmitExpression(node.Value, flags);
+ }
+ }
+
+ labelInfo.EmitJump();
+
+ EmitUnreachable(node, flags);
+ }
+
+ // We need to push default(T), unless we're emitting ourselves as
+ // void. Even though the code is unreachable, we still have to
+ // generate correct IL. We can get rid of this once we have better
+ // reachability analysis.
+ private void EmitUnreachable(Expression node, CompilationFlags flags) {
+ if (node.Type != typeof(void) && (flags & CompilationFlags.EmitAsVoidType) == 0) {
+ _ilg.EmitDefault(node.Type);
+ }
+ }
+
+ private bool TryPushLabelBlock(Expression node) {
+ // Anything that is "statement-like" -- e.g. has no associated
+ // stack state can be jumped into, with the exception of try-blocks
+ // We indicate this by a "Block"
+ //
+ // Otherwise, we push an "Expression" to indicate that it can't be
+ // jumped into
+ switch (node.NodeType) {
+ default:
+ if (_labelBlock.Kind != LabelScopeKind.Expression) {
+ PushLabelBlock(LabelScopeKind.Expression);
+ return true;
+ }
+ return false;
+ case ExpressionType.Label:
+ // LabelExpression is a bit special, if it's directly in a
+ // block it becomes associate with the block's scope. Same
+ // thing if it's in a switch case body.
+ if (_labelBlock.Kind == LabelScopeKind.Block) {
+ var label = ((LabelExpression)node).Target;
+ if (_labelBlock.ContainsTarget(label)) {
+ return false;
+ }
+ if (_labelBlock.Parent.Kind == LabelScopeKind.Switch &&
+ _labelBlock.Parent.ContainsTarget(label)) {
+ return false;
+ }
+ }
+ PushLabelBlock(LabelScopeKind.Statement);
+ return true;
+ case ExpressionType.Block:
+ if (node is SpilledExpressionBlock) {
+ // treat it as an expression
+ goto default;
+ }
+
+ PushLabelBlock(LabelScopeKind.Block);
+ // Labels defined immediately in the block are valid for
+ // the whole block.
+ if (_labelBlock.Parent.Kind != LabelScopeKind.Switch) {
+ DefineBlockLabels(node);
+ }
+ return true;
+ case ExpressionType.Switch:
+ PushLabelBlock(LabelScopeKind.Switch);
+ // Define labels inside of the switch cases so theyare in
+ // scope for the whole switch. This allows "goto case" and
+ // "goto default" to be considered as local jumps.
+ var @switch = (SwitchExpression)node;
+ foreach (SwitchCase c in @switch.Cases) {
+ DefineBlockLabels(c.Body);
+ }
+ DefineBlockLabels(@switch.DefaultBody);
+ return true;
+
+ // Remove this when Convert(Void) goes away.
+ case ExpressionType.Convert:
+ if (node.Type != typeof(void)) {
+ // treat it as an expression
+ goto default;
+ }
+ PushLabelBlock(LabelScopeKind.Statement);
+ return true;
+
+ case ExpressionType.Conditional:
+ case ExpressionType.Loop:
+ case ExpressionType.Goto:
+ PushLabelBlock(LabelScopeKind.Statement);
+ return true;
+ }
+ }
+
+ private void DefineBlockLabels(Expression node) {
+ var block = node as BlockExpression;
+ if (block == null || block is SpilledExpressionBlock) {
+ return;
+ }
+ for (int i = 0, n = block.ExpressionCount; i < n; i++) {
+ Expression e = block.GetExpression(i);
+
+ var label = e as LabelExpression;
+ if (label != null) {
+ DefineLabel(label.Target);
+ }
+ }
+ }
+
+ // See if this lambda has a return label
+ // If so, we'll create it now and mark it as allowing the "ret" opcode
+ // This allows us to generate better IL
+ private void AddReturnLabel(LambdaExpression lambda) {
+ var expression = lambda.Body;
+
+ while (true) {
+ switch (expression.NodeType) {
+ default:
+ // Didn't find return label
+ return;
+ case ExpressionType.Label:
+ // Found the label. We can directly return from this place
+ // only if the label type is reference assignable to the lambda return type.
+ var label = ((LabelExpression)expression).Target;
+ _labelInfo.Add(label, new LabelInfo(_ilg, label, TypeUtils.AreReferenceAssignable(lambda.ReturnType, label.Type)));
+ return;
+ case ExpressionType.Block:
+ // Look in the last significant expression of a block
+ var body = (BlockExpression)expression;
+ // omit empty and debuginfo at the end of the block since they
+ // are not going to emit any IL
+ for (int i = body.ExpressionCount - 1; i >= 0; i--) {
+ expression = body.GetExpression(i);
+ if (Significant(expression)) {
+ break;
+ }
+ }
+ continue;
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Expressions.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Expressions.cs
new file mode 100644
index 00000000000..35224319a84
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Expressions.cs
@@ -0,0 +1,1094 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ partial class LambdaCompiler {
+ [Flags]
+ internal enum CompilationFlags {
+ EmitExpressionStart = 0x0001,
+ EmitNoExpressionStart = 0x0002,
+ EmitAsDefaultType = 0x0010,
+ EmitAsVoidType = 0x0020,
+ EmitAsTail = 0x0100, // at the tail position of a lambda, tail call can be safely emitted
+ EmitAsMiddle = 0x0200, // in the middle of a lambda, tail call can be emitted if it is in a return
+ EmitAsNoTail = 0x0400, // neither at the tail or in a return, or tail call is not turned on, no tail call is emitted
+
+ EmitExpressionStartMask = 0x000f,
+ EmitAsTypeMask = 0x00f0,
+ EmitAsTailCallMask = 0x0f00
+ }
+
+ /// <summary>
+ /// Update the flag with a new EmitAsTailCall flag
+ /// </summary>
+ private static CompilationFlags UpdateEmitAsTailCallFlag(CompilationFlags flags, CompilationFlags newValue) {
+ Debug.Assert(newValue == CompilationFlags.EmitAsTail || newValue == CompilationFlags.EmitAsMiddle || newValue == CompilationFlags.EmitAsNoTail);
+ var oldValue = flags & CompilationFlags.EmitAsTailCallMask;
+ return flags ^ oldValue | newValue;
+ }
+
+ /// <summary>
+ /// Update the flag with a new EmitExpressionStart flag
+ /// </summary>
+ private static CompilationFlags UpdateEmitExpressionStartFlag(CompilationFlags flags, CompilationFlags newValue) {
+ Debug.Assert(newValue == CompilationFlags.EmitExpressionStart || newValue == CompilationFlags.EmitNoExpressionStart);
+ var oldValue = flags & CompilationFlags.EmitExpressionStartMask;
+ return flags ^ oldValue | newValue;
+ }
+
+ /// <summary>
+ /// Update the flag with a new EmitAsType flag
+ /// </summary>
+ private static CompilationFlags UpdateEmitAsTypeFlag(CompilationFlags flags, CompilationFlags newValue) {
+ Debug.Assert(newValue == CompilationFlags.EmitAsDefaultType || newValue == CompilationFlags.EmitAsVoidType);
+ var oldValue = flags & CompilationFlags.EmitAsTypeMask;
+ return flags ^ oldValue | newValue;
+ }
+
+ /// <summary>
+ /// Generates code for this expression in a value position.
+ /// This method will leave the value of the expression
+ /// on the top of the stack typed as Type.
+ /// </summary>
+ internal void EmitExpression(Expression node) {
+ EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitExpressionStart);
+ }
+
+ /// <summary>
+ /// Emits an expression and discards the result. For some nodes this emits
+ /// more optimial code then EmitExpression/Pop
+ /// </summary>
+ private void EmitExpressionAsVoid(Expression node) {
+ EmitExpressionAsVoid(node, CompilationFlags.EmitAsNoTail);
+ }
+
+ private void EmitExpressionAsVoid(Expression node, CompilationFlags flags) {
+ Debug.Assert(node != null);
+
+ CompilationFlags startEmitted = EmitExpressionStart(node);
+
+ switch (node.NodeType) {
+ case ExpressionType.Assign:
+ EmitAssign((BinaryExpression)node, CompilationFlags.EmitAsVoidType);
+ break;
+ case ExpressionType.Block:
+ Emit((BlockExpression)node, UpdateEmitAsTypeFlag(flags, CompilationFlags.EmitAsVoidType));
+ break;
+ case ExpressionType.Throw:
+ EmitThrow((UnaryExpression)node, CompilationFlags.EmitAsVoidType);
+ break;
+ case ExpressionType.Goto:
+ EmitGotoExpression(node, UpdateEmitAsTypeFlag(flags, CompilationFlags.EmitAsVoidType));
+ break;
+ case ExpressionType.Constant:
+ case ExpressionType.Default:
+ case ExpressionType.Parameter:
+ // no-op
+ break;
+ default:
+ if (node.Type == typeof(void)) {
+ EmitExpression(node, UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitNoExpressionStart));
+ } else {
+ EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
+ _ilg.Emit(OpCodes.Pop);
+ }
+ break;
+ }
+ EmitExpressionEnd(startEmitted);
+ }
+
+ private void EmitExpressionAsType(Expression node, Type type, CompilationFlags flags) {
+
+ if (type == typeof(void)) {
+ EmitExpressionAsVoid(node, flags);
+ } else {
+ // if the node is emitted as a different type, CastClass IL is emitted at the end,
+ // should not emit with tail calls.
+ if (!TypeUtils.AreEquivalent(node.Type, type)) {
+ EmitExpression(node);
+ Debug.Assert(TypeUtils.AreReferenceAssignable(type, node.Type));
+ _ilg.Emit(OpCodes.Castclass, type);
+ } else {
+ // emit the with the flags and emit emit expression start
+ EmitExpression(node, UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart));
+ }
+ }
+ }
+
+ #region label block tracking
+
+ private CompilationFlags EmitExpressionStart(Expression node) {
+ if (TryPushLabelBlock(node)) {
+ return CompilationFlags.EmitExpressionStart;
+ }
+ return CompilationFlags.EmitNoExpressionStart;
+ }
+
+ private void EmitExpressionEnd(CompilationFlags flags) {
+ if ((flags & CompilationFlags.EmitExpressionStartMask) == CompilationFlags.EmitExpressionStart) {
+ PopLabelBlock(_labelBlock.Kind);
+ }
+ }
+
+ #endregion
+
+ #region InvocationExpression
+
+ private void EmitInvocationExpression(Expression expr, CompilationFlags flags) {
+ InvocationExpression node = (InvocationExpression)expr;
+
+ // Optimization: inline code for literal lambda's directly
+ //
+ // This is worth it because otherwise we end up with a extra call
+ // to DynamicMethod.CreateDelegate, which is expensive.
+ //
+ if (node.LambdaOperand != null) {
+ EmitInlinedInvoke(node, flags);
+ return;
+ }
+
+ expr = node.Expression;
+ if (typeof(LambdaExpression).IsAssignableFrom(expr.Type)) {
+ // if the invoke target is a lambda expression tree, first compile it into a delegate
+ expr = Expression.Call(expr, expr.Type.GetMethod("Compile", new Type[0]));
+ }
+ expr = Expression.Call(expr, expr.Type.GetMethod("Invoke"), node.Arguments);
+
+ EmitExpression(expr);
+ }
+
+ private void EmitInlinedInvoke(InvocationExpression invoke, CompilationFlags flags) {
+ var lambda = invoke.LambdaOperand;
+
+ // This is tricky: we need to emit the arguments outside of the
+ // scope, but set them inside the scope. Fortunately, using the IL
+ // stack it is entirely doable.
+
+ // 1. Emit invoke arguments
+ List<WriteBack> wb = EmitArguments(lambda.Type.GetMethod("Invoke"), invoke);
+
+ // 2. Create the nested LambdaCompiler
+ var inner = new LambdaCompiler(this, lambda);
+
+ // 3. Emit the body
+ // if the inlined lambda is the last expression of the whole lambda,
+ // tail call can be applied.
+ if (wb.Count != 0) {
+ flags = UpdateEmitAsTailCallFlag(flags, CompilationFlags.EmitAsNoTail);
+ }
+ inner.EmitLambdaBody(_scope, true, flags);
+
+ // 4. Emit writebacks if needed
+ EmitWriteBack(wb);
+ }
+
+ #endregion
+
+ #region IndexExpression
+
+ private void EmitIndexExpression(Expression expr) {
+ var node = (IndexExpression)expr;
+
+ // Emit instance, if calling an instance method
+ Type objectType = null;
+ if (node.Object != null) {
+ EmitInstance(node.Object, objectType = node.Object.Type);
+ }
+
+ // Emit indexes. We don't allow byref args, so no need to worry
+ // about writebacks or EmitAddress
+ foreach (var arg in node.Arguments) {
+ EmitExpression(arg);
+ }
+
+ EmitGetIndexCall(node, objectType);
+ }
+
+ private void EmitIndexAssignment(BinaryExpression node, CompilationFlags flags) {
+ var index = (IndexExpression)node.Left;
+
+ var emitAs = flags & CompilationFlags.EmitAsTypeMask;
+
+ // Emit instance, if calling an instance method
+ Type objectType = null;
+ if (index.Object != null) {
+ EmitInstance(index.Object, objectType = index.Object.Type);
+ }
+
+ // Emit indexes. We don't allow byref args, so no need to worry
+ // about writebacks or EmitAddress
+ foreach (var arg in index.Arguments) {
+ EmitExpression(arg);
+ }
+
+ // Emit value
+ EmitExpression(node.Right);
+
+ // Save the expression value, if needed
+ LocalBuilder temp = null;
+ if (emitAs != CompilationFlags.EmitAsVoidType) {
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Stloc, temp = GetLocal(node.Type));
+ }
+
+ EmitSetIndexCall(index, objectType);
+
+ // Restore the value
+ if (emitAs != CompilationFlags.EmitAsVoidType) {
+ _ilg.Emit(OpCodes.Ldloc, temp);
+ FreeLocal(temp);
+ }
+ }
+
+ private void EmitGetIndexCall(IndexExpression node, Type objectType) {
+ if (node.Indexer != null) {
+ // For indexed properties, just call the getter
+ var method = node.Indexer.GetGetMethod(true);
+ EmitCall(objectType, method);
+ } else if (node.Arguments.Count != 1) {
+ // Multidimensional arrays, call get
+ _ilg.Emit(OpCodes.Call, node.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance));
+ } else {
+ // For one dimensional arrays, emit load
+ _ilg.EmitLoadElement(node.Type);
+ }
+ }
+
+ private void EmitSetIndexCall(IndexExpression node, Type objectType) {
+ if (node.Indexer != null) {
+ // For indexed properties, just call the setter
+ var method = node.Indexer.GetSetMethod(true);
+ EmitCall(objectType, method);
+ } else if (node.Arguments.Count != 1) {
+ // Multidimensional arrays, call set
+ _ilg.Emit(OpCodes.Call, node.Object.Type.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance));
+ } else {
+ // For one dimensional arrays, emit store
+ _ilg.EmitStoreElement(node.Type);
+ }
+ }
+
+ #endregion
+
+ #region MethodCallExpression
+
+ private void EmitMethodCallExpression(Expression expr, CompilationFlags flags) {
+ MethodCallExpression node = (MethodCallExpression)expr;
+
+ EmitMethodCall(node.Object, node.Method, node, flags);
+ }
+
+ private void EmitMethodCallExpression(Expression expr) {
+ EmitMethodCallExpression(expr, CompilationFlags.EmitAsNoTail);
+ }
+
+ private void EmitMethodCall(Expression obj, MethodInfo method, IArgumentProvider methodCallExpr) {
+ EmitMethodCall(obj, method, methodCallExpr, CompilationFlags.EmitAsNoTail);
+ }
+
+ private void EmitMethodCall(Expression obj, MethodInfo method, IArgumentProvider methodCallExpr, CompilationFlags flags) {
+ // Emit instance, if calling an instance method
+ Type objectType = null;
+ if (!method.IsStatic) {
+ EmitInstance(obj, objectType = obj.Type);
+ }
+ // if the obj has a value type, its address is passed to the method call so we cannot destroy the
+ // stack by emitting a tail call
+ if (obj != null && obj.Type.IsValueType) {
+ EmitMethodCall(method, methodCallExpr, objectType);
+ } else {
+ EmitMethodCall(method, methodCallExpr, objectType, flags);
+ }
+ }
+
+ // assumes 'object' of non-static call is already on stack
+ private void EmitMethodCall(MethodInfo mi, IArgumentProvider args, Type objectType) {
+ EmitMethodCall(mi, args, objectType, CompilationFlags.EmitAsNoTail);
+ }
+
+ // assumes 'object' of non-static call is already on stack
+ private void EmitMethodCall(MethodInfo mi, IArgumentProvider args, Type objectType, CompilationFlags flags) {
+
+ // Emit arguments
+ List<WriteBack> wb = EmitArguments(mi, args);
+
+ // Emit the actual call
+ OpCode callOp = UseVirtual(mi) ? OpCodes.Callvirt : OpCodes.Call;
+ if (callOp == OpCodes.Callvirt && objectType.IsValueType) {
+ // This automatically boxes value types if necessary.
+ _ilg.Emit(OpCodes.Constrained, objectType);
+ }
+ // The method call can be a tail call if
+ // 1) the method call is the last instruction before Ret
+ // 2) the method does not have any ByRef parameters, refer to ECMA-335 Partition III Section 2.4.
+ // "Verification requires that no managed pointers are passed to the method being called, since
+ // it does not track pointers into the current frame."
+ if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail && !MethodHasByRefParameter(mi)) {
+ _ilg.Emit(OpCodes.Tailcall);
+ }
+ if (mi.CallingConvention == CallingConventions.VarArgs) {
+ _ilg.EmitCall(callOp, mi, args.Map(a => a.Type));
+ } else {
+ _ilg.Emit(callOp, mi);
+ }
+
+ // Emit writebacks for properties passed as "ref" arguments
+ EmitWriteBack(wb);
+ }
+
+ private static bool MethodHasByRefParameter(MethodInfo mi) {
+ foreach (var pi in mi.GetParametersCached()) {
+ if (pi.IsByRefParameter()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void EmitCall(Type objectType, MethodInfo method) {
+ if (method.CallingConvention == CallingConventions.VarArgs) {
+ throw Error.UnexpectedVarArgsCall(method);
+ }
+
+ OpCode callOp = UseVirtual(method) ? OpCodes.Callvirt : OpCodes.Call;
+ if (callOp == OpCodes.Callvirt && objectType.IsValueType) {
+ _ilg.Emit(OpCodes.Constrained, objectType);
+ }
+ _ilg.Emit(callOp, method);
+ }
+
+ private static bool UseVirtual(MethodInfo mi) {
+ // There are two factors: is the method static, virtual or non-virtual instance?
+ // And is the object ref or value?
+ // The cases are:
+ //
+ // static, ref: call
+ // static, value: call
+ // virtual, ref: callvirt
+ // virtual, value: call -- eg, double.ToString must be a non-virtual call to be verifiable.
+ // instance, ref: callvirt -- this looks wrong, but is verifiable and gives us a free null check.
+ // instance, value: call
+ //
+ // We never need to generate a nonvirtual call to a virtual method on a reference type because
+ // expression trees do not support "base.Foo()" style calling.
+ //
+ // We could do an optimization here for the case where we know that the object is a non-null
+ // reference type and the method is a non-virtual instance method. For example, if we had
+ // (new Foo()).Bar() for instance method Bar we don't need the null check so we could do a
+ // call rather than a callvirt. However that seems like it would not be a very big win for
+ // most dynamically generated code scenarios, so let's not do that for now.
+
+ if (mi.IsStatic) {
+ return false;
+ }
+ if (mi.DeclaringType.IsValueType) {
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Emits arguments to a call, and returns an array of writebacks that
+ /// should happen after the call.
+ /// </summary>
+ private List<WriteBack> EmitArguments(MethodBase method, IArgumentProvider args) {
+ return EmitArguments(method, args, 0);
+ }
+
+ /// <summary>
+ /// Emits arguments to a call, and returns an array of writebacks that
+ /// should happen after the call. For emitting dynamic expressions, we
+ /// need to skip the first parameter of the method (the call site).
+ /// </summary>
+ private List<WriteBack> EmitArguments(MethodBase method, IArgumentProvider args, int skipParameters) {
+ ParameterInfo[] pis = method.GetParametersCached();
+ Debug.Assert(args.ArgumentCount + skipParameters == pis.Length);
+
+ var writeBacks = new List<WriteBack>();
+ for (int i = skipParameters, n = pis.Length; i < n; i++) {
+ ParameterInfo parameter = pis[i];
+ Expression argument = args.GetArgument(i - skipParameters);
+ Type type = parameter.ParameterType;
+
+ if (type.IsByRef) {
+ type = type.GetElementType();
+
+ WriteBack wb = EmitAddressWriteBack(argument, type);
+ if (wb != null) {
+ writeBacks.Add(wb);
+ }
+ } else {
+ EmitExpression(argument);
+ }
+ }
+ return writeBacks;
+ }
+
+ private static void EmitWriteBack(IList<WriteBack> writeBacks) {
+ foreach (WriteBack wb in writeBacks) {
+ wb();
+ }
+ }
+
+ #endregion
+
+ private void EmitConstantExpression(Expression expr) {
+ ConstantExpression node = (ConstantExpression)expr;
+
+ EmitConstant(node.Value, node.Type);
+ }
+
+ private void EmitConstant(object value, Type type) {
+ // Try to emit the constant directly into IL
+ if (ILGen.CanEmitConstant(value, type)) {
+ _ilg.EmitConstant(value, type);
+ return;
+ }
+
+ _boundConstants.EmitConstant(this, value, type);
+ }
+
+ private void EmitDynamicExpression(Expression expr) {
+ if (!(_method is DynamicMethod)) {
+ throw Error.CannotCompileDynamic();
+ }
+
+ var node = (DynamicExpression)expr;
+
+ var site = CallSite.Create(node.DelegateType, node.Binder);
+ Type siteType = site.GetType();
+
+ var invoke = node.DelegateType.GetMethod("Invoke");
+
+ // site.Target.Invoke(site, args)
+ EmitConstant(site, siteType);
+
+ // Emit the temp as type CallSite so we get more reuse
+ _ilg.Emit(OpCodes.Dup);
+#if MICROSOFT_SCRIPTING_CORE
+ // For 3.5, emit the temp as CallSite<T> to work around a Jit32
+ // verifier issue (fixed in 3.5 sp1)
+ var siteTemp = GetLocal(siteType);
+#else
+ var siteTemp = GetLocal(typeof(CallSite));
+#endif
+ _ilg.Emit(OpCodes.Stloc, siteTemp);
+ _ilg.Emit(OpCodes.Ldfld, siteType.GetField("Target"));
+ _ilg.Emit(OpCodes.Ldloc, siteTemp);
+ FreeLocal(siteTemp);
+
+ List<WriteBack> wb = EmitArguments(invoke, node, 1);
+ _ilg.Emit(OpCodes.Callvirt, invoke);
+ EmitWriteBack(wb);
+ }
+
+ private void EmitNewExpression(Expression expr) {
+ NewExpression node = (NewExpression)expr;
+
+ if (node.Constructor != null) {
+ List<WriteBack> wb = EmitArguments(node.Constructor, node);
+ _ilg.Emit(OpCodes.Newobj, node.Constructor);
+ EmitWriteBack(wb);
+ } else {
+ Debug.Assert(node.Arguments.Count == 0, "Node with arguments must have a constructor.");
+ Debug.Assert(node.Type.IsValueType, "Only value type may have constructor not set.");
+ LocalBuilder temp = GetLocal(node.Type);
+ _ilg.Emit(OpCodes.Ldloca, temp);
+ _ilg.Emit(OpCodes.Initobj, node.Type);
+ _ilg.Emit(OpCodes.Ldloc, temp);
+ FreeLocal(temp);
+ }
+ }
+
+ private void EmitTypeBinaryExpression(Expression expr) {
+ TypeBinaryExpression node = (TypeBinaryExpression)expr;
+
+ if (node.NodeType == ExpressionType.TypeEqual) {
+ EmitExpression(node.ReduceTypeEqual());
+ return;
+ }
+
+ Type type = node.Expression.Type;
+
+ // Try to determine the result statically
+ AnalyzeTypeIsResult result = ConstantCheck.AnalyzeTypeIs(node);
+
+ if (result == AnalyzeTypeIsResult.KnownTrue ||
+ result == AnalyzeTypeIsResult.KnownFalse) {
+ // Result is known statically, so just emit the expression for
+ // its side effects and return the result
+ EmitExpressionAsVoid(node.Expression);
+ _ilg.EmitBoolean(result == AnalyzeTypeIsResult.KnownTrue);
+ return;
+ }
+
+ if (result == AnalyzeTypeIsResult.KnownAssignable) {
+ // We know the type can be assigned, but still need to check
+ // for null at runtime
+ if (type.IsNullableType()) {
+ EmitAddress(node.Expression, type);
+ _ilg.EmitHasValue(type);
+ return;
+ }
+
+ Debug.Assert(!type.IsValueType);
+ EmitExpression(node.Expression);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ return;
+ }
+
+ Debug.Assert(result == AnalyzeTypeIsResult.Unknown);
+
+ // Emit a full runtime "isinst" check
+ EmitExpression(node.Expression);
+ if (type.IsValueType) {
+ _ilg.Emit(OpCodes.Box, type);
+ }
+ _ilg.Emit(OpCodes.Isinst, node.TypeOperand);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Cgt_Un);
+ }
+
+ private void EmitVariableAssignment(BinaryExpression node, CompilationFlags flags) {
+ var variable = (ParameterExpression)node.Left;
+ var emitAs = flags & CompilationFlags.EmitAsTypeMask;
+
+ EmitExpression(node.Right);
+ if (emitAs != CompilationFlags.EmitAsVoidType) {
+ _ilg.Emit(OpCodes.Dup);
+ }
+
+ if (variable.IsByRef) {
+ // Note: the stloc/ldloc pattern is a bit suboptimal, but it
+ // saves us from having to spill stack when assigning to a
+ // byref parameter. We already make this same tradeoff for
+ // hoisted variables, see ElementStorage.EmitStore
+
+ LocalBuilder value = GetLocal(variable.Type);
+ _ilg.Emit(OpCodes.Stloc, value);
+ _scope.EmitGet(variable);
+ _ilg.Emit(OpCodes.Ldloc, value);
+ FreeLocal(value);
+ _ilg.EmitStoreValueIndirect(variable.Type);
+ } else {
+ _scope.EmitSet(variable);
+ }
+ }
+
+ private void EmitAssignBinaryExpression(Expression expr) {
+ EmitAssign((BinaryExpression)expr, CompilationFlags.EmitAsDefaultType);
+ }
+
+ private void EmitAssign(BinaryExpression node, CompilationFlags emitAs) {
+ switch (node.Left.NodeType) {
+ case ExpressionType.Index:
+ EmitIndexAssignment(node, emitAs);
+ return;
+ case ExpressionType.MemberAccess:
+ EmitMemberAssignment(node, emitAs);
+ return;
+ case ExpressionType.Parameter:
+ EmitVariableAssignment(node, emitAs);
+ return;
+ default:
+ throw Error.InvalidLvalue(node.Left.NodeType);
+ }
+ }
+
+ private void EmitParameterExpression(Expression expr) {
+ ParameterExpression node = (ParameterExpression)expr;
+ _scope.EmitGet(node);
+ if (node.IsByRef) {
+ _ilg.EmitLoadValueIndirect(node.Type);
+ }
+ }
+
+ private void EmitLambdaExpression(Expression expr) {
+ LambdaExpression node = (LambdaExpression)expr;
+ EmitDelegateConstruction(node);
+ }
+
+ private void EmitRuntimeVariablesExpression(Expression expr) {
+ RuntimeVariablesExpression node = (RuntimeVariablesExpression)expr;
+ _scope.EmitVariableAccess(this, node.Variables);
+ }
+
+ private void EmitMemberAssignment(BinaryExpression node, CompilationFlags flags) {
+ MemberExpression lvalue = (MemberExpression)node.Left;
+ MemberInfo member = lvalue.Member;
+
+ // emit "this", if any
+ Type objectType = null;
+ if (lvalue.Expression != null) {
+ EmitInstance(lvalue.Expression, objectType = lvalue.Expression.Type);
+ }
+
+ // emit value
+ EmitExpression(node.Right);
+
+ LocalBuilder temp = null;
+ var emitAs = flags & CompilationFlags.EmitAsTypeMask;
+ if (emitAs != CompilationFlags.EmitAsVoidType) {
+ // save the value so we can return it
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Stloc, temp = GetLocal(node.Type));
+ }
+
+ switch (member.MemberType) {
+ case MemberTypes.Field:
+ _ilg.EmitFieldSet((FieldInfo)member);
+ break;
+ case MemberTypes.Property:
+ EmitCall(objectType, ((PropertyInfo)member).GetSetMethod(true));
+ break;
+ default:
+ throw Error.InvalidMemberType(member.MemberType);
+ }
+
+ if (emitAs != CompilationFlags.EmitAsVoidType) {
+ _ilg.Emit(OpCodes.Ldloc, temp);
+ FreeLocal(temp);
+ }
+ }
+
+ private void EmitMemberExpression(Expression expr) {
+ MemberExpression node = (MemberExpression)expr;
+
+ // emit "this", if any
+ Type instanceType = null;
+ if (node.Expression != null) {
+ EmitInstance(node.Expression, instanceType = node.Expression.Type);
+ }
+
+ EmitMemberGet(node.Member, instanceType);
+ }
+
+ // assumes instance is already on the stack
+ private void EmitMemberGet(MemberInfo member, Type objectType) {
+ switch (member.MemberType) {
+ case MemberTypes.Field:
+ FieldInfo fi = (FieldInfo)member;
+ if (fi.IsLiteral) {
+ EmitConstant(fi.GetRawConstantValue(), fi.FieldType);
+ } else {
+ _ilg.EmitFieldGet(fi);
+ }
+ break;
+ case MemberTypes.Property:
+ EmitCall(objectType, ((PropertyInfo)member).GetGetMethod(true));
+ break;
+ default:
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ private void EmitInstance(Expression instance, Type type) {
+ if (instance != null) {
+ if (type.IsValueType) {
+ EmitAddress(instance, type);
+ } else {
+ EmitExpression(instance);
+ }
+ }
+ }
+
+ private void EmitNewArrayExpression(Expression expr) {
+ NewArrayExpression node = (NewArrayExpression)expr;
+
+ if (node.NodeType == ExpressionType.NewArrayInit) {
+ _ilg.EmitArray(
+ node.Type.GetElementType(),
+ node.Expressions.Count,
+ delegate(int index) {
+ EmitExpression(node.Expressions[index]);
+ }
+ );
+ } else {
+ ReadOnlyCollection<Expression> bounds = node.Expressions;
+ for (int i = 0; i < bounds.Count; i++) {
+ Expression x = bounds[i];
+ EmitExpression(x);
+ _ilg.EmitConvertToType(x.Type, typeof(int), true);
+ }
+ _ilg.EmitArray(node.Type);
+ }
+ }
+
+ private void EmitDebugInfoExpression(Expression expr) {
+ if (!EmitDebugSymbols) {
+ return;
+ }
+ var node = (DebugInfoExpression)expr;
+
+ if (node.IsClear && _sequencePointCleared) {
+ // Emitting another clearance after one clearance does not
+ // have any effect, so we can save it.
+ return;
+ }
+
+ _tree.DebugInfoGenerator.MarkSequencePoint(_lambda, _method, _ilg, node);
+ _ilg.Emit(OpCodes.Nop);
+ _sequencePointCleared = node.IsClear;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
+ private static void EmitExtensionExpression(Expression expr) {
+ throw Error.ExtensionNotReduced();
+ }
+
+ #region ListInit, MemberInit
+
+ private void EmitListInitExpression(Expression expr) {
+ EmitListInit((ListInitExpression)expr);
+ }
+
+ private void EmitMemberInitExpression(Expression expr) {
+ EmitMemberInit((MemberInitExpression)expr);
+ }
+
+ private void EmitBinding(MemberBinding binding, Type objectType) {
+ switch (binding.BindingType) {
+ case MemberBindingType.Assignment:
+ EmitMemberAssignment((MemberAssignment)binding, objectType);
+ break;
+ case MemberBindingType.ListBinding:
+ EmitMemberListBinding((MemberListBinding)binding);
+ break;
+ case MemberBindingType.MemberBinding:
+ EmitMemberMemberBinding((MemberMemberBinding)binding);
+ break;
+ default:
+ throw Error.UnknownBindingType();
+ }
+ }
+
+ private void EmitMemberAssignment(MemberAssignment binding, Type objectType) {
+ EmitExpression(binding.Expression);
+ FieldInfo fi = binding.Member as FieldInfo;
+ if (fi != null) {
+ _ilg.Emit(OpCodes.Stfld, fi);
+ } else {
+ PropertyInfo pi = binding.Member as PropertyInfo;
+ if (pi != null) {
+ EmitCall(objectType, pi.GetSetMethod(true));
+ } else {
+ throw Error.UnhandledBinding();
+ }
+ }
+ }
+
+ private void EmitMemberMemberBinding(MemberMemberBinding binding) {
+ Type type = GetMemberType(binding.Member);
+ if (binding.Member is PropertyInfo && type.IsValueType) {
+ throw Error.CannotAutoInitializeValueTypeMemberThroughProperty(binding.Member);
+ }
+ if (type.IsValueType) {
+ EmitMemberAddress(binding.Member, binding.Member.DeclaringType);
+ } else {
+ EmitMemberGet(binding.Member, binding.Member.DeclaringType);
+ }
+ EmitMemberInit(binding.Bindings, false, type);
+ }
+
+ private void EmitMemberListBinding(MemberListBinding binding) {
+ Type type = GetMemberType(binding.Member);
+ if (binding.Member is PropertyInfo && type.IsValueType) {
+ throw Error.CannotAutoInitializeValueTypeElementThroughProperty(binding.Member);
+ }
+ if (type.IsValueType) {
+ EmitMemberAddress(binding.Member, binding.Member.DeclaringType);
+ } else {
+ EmitMemberGet(binding.Member, binding.Member.DeclaringType);
+ }
+ EmitListInit(binding.Initializers, false, type);
+ }
+
+ private void EmitMemberInit(MemberInitExpression init) {
+ EmitExpression(init.NewExpression);
+ LocalBuilder loc = null;
+ if (init.NewExpression.Type.IsValueType && init.Bindings.Count > 0) {
+ loc = _ilg.DeclareLocal(init.NewExpression.Type);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ }
+ EmitMemberInit(init.Bindings, loc == null, init.NewExpression.Type);
+ if (loc != null) {
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ }
+ }
+
+ // This method assumes that the instance is on the stack and is expected, based on "keepOnStack" flag
+ // to either leave the instance on the stack, or pop it.
+ private void EmitMemberInit(ReadOnlyCollection<MemberBinding> bindings, bool keepOnStack, Type objectType) {
+ int n = bindings.Count;
+ if (n == 0) {
+ // If there are no initializers and instance is not to be kept on the stack, we must pop explicitly.
+ if (!keepOnStack) {
+ _ilg.Emit(OpCodes.Pop);
+ }
+ } else {
+ for (int i = 0; i < n; i++) {
+ if (keepOnStack || i < n - 1) {
+ _ilg.Emit(OpCodes.Dup);
+ }
+ EmitBinding(bindings[i], objectType);
+ }
+ }
+ }
+
+ private void EmitListInit(ListInitExpression init) {
+ EmitExpression(init.NewExpression);
+ LocalBuilder loc = null;
+ if (init.NewExpression.Type.IsValueType) {
+ loc = _ilg.DeclareLocal(init.NewExpression.Type);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ }
+ EmitListInit(init.Initializers, loc == null, init.NewExpression.Type);
+ if (loc != null) {
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ }
+ }
+
+ // This method assumes that the list instance is on the stack and is expected, based on "keepOnStack" flag
+ // to either leave the list instance on the stack, or pop it.
+ private void EmitListInit(ReadOnlyCollection<ElementInit> initializers, bool keepOnStack, Type objectType) {
+ int n = initializers.Count;
+
+ if (n == 0) {
+ // If there are no initializers and instance is not to be kept on the stack, we must pop explicitly.
+ if (!keepOnStack) {
+ _ilg.Emit(OpCodes.Pop);
+ }
+ } else {
+ for (int i = 0; i < n; i++) {
+ if (keepOnStack || i < n - 1) {
+ _ilg.Emit(OpCodes.Dup);
+ }
+ EmitMethodCall(initializers[i].AddMethod, initializers[i], objectType);
+
+ // Aome add methods, ArrayList.Add for example, return non-void
+ if (initializers[i].AddMethod.ReturnType != typeof(void)) {
+ _ilg.Emit(OpCodes.Pop);
+ }
+ }
+ }
+ }
+
+ private static Type GetMemberType(MemberInfo member) {
+ FieldInfo fi = member as FieldInfo;
+ if (fi != null) return fi.FieldType;
+ PropertyInfo pi = member as PropertyInfo;
+ if (pi != null) return pi.PropertyType;
+ throw Error.MemberNotFieldOrProperty(member);
+ }
+
+ #endregion
+
+ #region Expression helpers
+
+ internal static void ValidateLift(IList<ParameterExpression> variables, IList<Expression> arguments) {
+ System.Diagnostics.Debug.Assert(variables != null);
+ System.Diagnostics.Debug.Assert(arguments != null);
+
+ if (variables.Count != arguments.Count) {
+ throw Error.IncorrectNumberOfIndexes();
+ }
+ for (int i = 0, n = variables.Count; i < n; i++) {
+ if (!TypeUtils.AreReferenceAssignable(variables[i].Type, TypeUtils.GetNonNullableType(arguments[i].Type))) {
+ throw Error.ArgumentTypesMustMatch();
+ }
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpression mc, ParameterExpression[] paramList, Expression[] argList) {
+ Debug.Assert(TypeUtils.AreEquivalent(TypeUtils.GetNonNullableType(resultType), TypeUtils.GetNonNullableType(mc.Type)));
+
+ switch (nodeType) {
+ default:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual: {
+ Label exit = _ilg.DefineLabel();
+ Label exitNull = _ilg.DefineLabel();
+ LocalBuilder anyNull = _ilg.DeclareLocal(typeof(bool));
+ for (int i = 0, n = paramList.Length; i < n; i++) {
+ ParameterExpression v = paramList[i];
+ Expression arg = argList[i];
+ if (TypeUtils.IsNullableType(arg.Type)) {
+ _scope.AddLocal(this, v);
+ EmitAddress(arg, arg.Type);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.EmitHasValue(arg.Type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Stloc, anyNull);
+ _ilg.EmitGetValueOrDefault(arg.Type);
+ _scope.EmitSet(v);
+ } else {
+ _scope.AddLocal(this, v);
+ EmitExpression(arg);
+ if (!arg.Type.IsValueType) {
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Stloc, anyNull);
+ }
+ _scope.EmitSet(v);
+ }
+ _ilg.Emit(OpCodes.Ldloc, anyNull);
+ _ilg.Emit(OpCodes.Brtrue, exitNull);
+ }
+ EmitMethodCallExpression(mc);
+ if (TypeUtils.IsNullableType(resultType) && !TypeUtils.AreEquivalent(resultType, mc.Type)) {
+ ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ }
+ _ilg.Emit(OpCodes.Br_S, exit);
+ _ilg.MarkLabel(exitNull);
+ if (TypeUtils.AreEquivalent(resultType, TypeUtils.GetNullableType(mc.Type))) {
+ if (resultType.IsValueType) {
+ LocalBuilder result = GetLocal(resultType);
+ _ilg.Emit(OpCodes.Ldloca, result);
+ _ilg.Emit(OpCodes.Initobj, resultType);
+ _ilg.Emit(OpCodes.Ldloc, result);
+ FreeLocal(result);
+ } else {
+ _ilg.Emit(OpCodes.Ldnull);
+ }
+ } else {
+ switch (nodeType) {
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ break;
+ default:
+ throw Error.UnknownLiftType(nodeType);
+ }
+ }
+ _ilg.MarkLabel(exit);
+ return;
+ }
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual: {
+ if (TypeUtils.AreEquivalent(resultType, TypeUtils.GetNullableType(mc.Type))) {
+ goto default;
+ }
+ Label exit = _ilg.DefineLabel();
+ Label exitAllNull = _ilg.DefineLabel();
+ Label exitAnyNull = _ilg.DefineLabel();
+
+ LocalBuilder anyNull = _ilg.DeclareLocal(typeof(bool));
+ LocalBuilder allNull = _ilg.DeclareLocal(typeof(bool));
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Stloc, anyNull);
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Stloc, allNull);
+
+ for (int i = 0, n = paramList.Length; i < n; i++) {
+ ParameterExpression v = paramList[i];
+ Expression arg = argList[i];
+ _scope.AddLocal(this, v);
+ if (TypeUtils.IsNullableType(arg.Type)) {
+ EmitAddress(arg, arg.Type);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.EmitHasValue(arg.Type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Ldloc, anyNull);
+ _ilg.Emit(OpCodes.Or);
+ _ilg.Emit(OpCodes.Stloc, anyNull);
+ _ilg.Emit(OpCodes.Ldloc, allNull);
+ _ilg.Emit(OpCodes.And);
+ _ilg.Emit(OpCodes.Stloc, allNull);
+ _ilg.EmitGetValueOrDefault(arg.Type);
+ } else {
+ EmitExpression(arg);
+ if (!arg.Type.IsValueType) {
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Ldloc, anyNull);
+ _ilg.Emit(OpCodes.Or);
+ _ilg.Emit(OpCodes.Stloc, anyNull);
+ _ilg.Emit(OpCodes.Ldloc, allNull);
+ _ilg.Emit(OpCodes.And);
+ _ilg.Emit(OpCodes.Stloc, allNull);
+ } else {
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Stloc, allNull);
+ }
+ }
+ _scope.EmitSet(v);
+ }
+ _ilg.Emit(OpCodes.Ldloc, allNull);
+ _ilg.Emit(OpCodes.Brtrue, exitAllNull);
+ _ilg.Emit(OpCodes.Ldloc, anyNull);
+ _ilg.Emit(OpCodes.Brtrue, exitAnyNull);
+
+ EmitMethodCallExpression(mc);
+ if (TypeUtils.IsNullableType(resultType) && !TypeUtils.AreEquivalent(resultType, mc.Type)) {
+ ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ }
+ _ilg.Emit(OpCodes.Br_S, exit);
+
+ _ilg.MarkLabel(exitAllNull);
+ _ilg.EmitBoolean(nodeType == ExpressionType.Equal);
+ _ilg.Emit(OpCodes.Br_S, exit);
+
+ _ilg.MarkLabel(exitAnyNull);
+ _ilg.EmitBoolean(nodeType == ExpressionType.NotEqual);
+
+ _ilg.MarkLabel(exit);
+ return;
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Generated.cs
new file mode 100644
index 00000000000..5599650b650
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Generated.cs
@@ -0,0 +1,288 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ partial class LambdaCompiler {
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private void EmitExpression(Expression node, CompilationFlags flags) {
+ Debug.Assert(node != null);
+
+ bool emitStart = (flags & CompilationFlags.EmitExpressionStartMask) == CompilationFlags.EmitExpressionStart;
+
+ CompilationFlags startEmitted = emitStart ? EmitExpressionStart(node) : CompilationFlags.EmitNoExpressionStart;
+ // only pass tail call flags to emit the expression
+ flags = flags & CompilationFlags.EmitAsTailCallMask;
+
+ switch (node.NodeType) {
+ #region Generated Expression Compiler
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_compiler from: generate_tree.py
+
+ case ExpressionType.Add:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.AddChecked:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.And:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.AndAlso:
+ EmitAndAlsoBinaryExpression(node, flags);
+ break;
+ case ExpressionType.ArrayLength:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.ArrayIndex:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Call:
+ EmitMethodCallExpression(node, flags);
+ break;
+ case ExpressionType.Coalesce:
+ EmitCoalesceBinaryExpression(node);
+ break;
+ case ExpressionType.Conditional:
+ EmitConditionalExpression(node, flags);
+ break;
+ case ExpressionType.Constant:
+ EmitConstantExpression(node);
+ break;
+ case ExpressionType.Convert:
+ EmitConvertUnaryExpression(node, flags);
+ break;
+ case ExpressionType.ConvertChecked:
+ EmitConvertUnaryExpression(node, flags);
+ break;
+ case ExpressionType.Divide:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Equal:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.ExclusiveOr:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.GreaterThan:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.GreaterThanOrEqual:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Invoke:
+ EmitInvocationExpression(node, flags);
+ break;
+ case ExpressionType.Lambda:
+ EmitLambdaExpression(node);
+ break;
+ case ExpressionType.LeftShift:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.LessThan:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.LessThanOrEqual:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.ListInit:
+ EmitListInitExpression(node);
+ break;
+ case ExpressionType.MemberAccess:
+ EmitMemberExpression(node);
+ break;
+ case ExpressionType.MemberInit:
+ EmitMemberInitExpression(node);
+ break;
+ case ExpressionType.Modulo:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Multiply:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.MultiplyChecked:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Negate:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.UnaryPlus:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.NegateChecked:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.New:
+ EmitNewExpression(node);
+ break;
+ case ExpressionType.NewArrayInit:
+ EmitNewArrayExpression(node);
+ break;
+ case ExpressionType.NewArrayBounds:
+ EmitNewArrayExpression(node);
+ break;
+ case ExpressionType.Not:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.NotEqual:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Or:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.OrElse:
+ EmitOrElseBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Parameter:
+ EmitParameterExpression(node);
+ break;
+ case ExpressionType.Power:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Quote:
+ EmitQuoteUnaryExpression(node);
+ break;
+ case ExpressionType.RightShift:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.Subtract:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.SubtractChecked:
+ EmitBinaryExpression(node, flags);
+ break;
+ case ExpressionType.TypeAs:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.TypeIs:
+ EmitTypeBinaryExpression(node);
+ break;
+ case ExpressionType.Assign:
+ EmitAssignBinaryExpression(node);
+ break;
+ case ExpressionType.Block:
+ EmitBlockExpression(node, flags);
+ break;
+ case ExpressionType.DebugInfo:
+ EmitDebugInfoExpression(node);
+ break;
+ case ExpressionType.Decrement:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.Dynamic:
+ EmitDynamicExpression(node);
+ break;
+ case ExpressionType.Default:
+ EmitDefaultExpression(node);
+ break;
+ case ExpressionType.Extension:
+ EmitExtensionExpression(node);
+ break;
+ case ExpressionType.Goto:
+ EmitGotoExpression(node, flags);
+ break;
+ case ExpressionType.Increment:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.Index:
+ EmitIndexExpression(node);
+ break;
+ case ExpressionType.Label:
+ EmitLabelExpression(node, flags);
+ break;
+ case ExpressionType.RuntimeVariables:
+ EmitRuntimeVariablesExpression(node);
+ break;
+ case ExpressionType.Loop:
+ EmitLoopExpression(node);
+ break;
+ case ExpressionType.Switch:
+ EmitSwitchExpression(node, flags);
+ break;
+ case ExpressionType.Throw:
+ EmitThrowUnaryExpression(node);
+ break;
+ case ExpressionType.Try:
+ EmitTryExpression(node);
+ break;
+ case ExpressionType.Unbox:
+ EmitUnboxUnaryExpression(node);
+ break;
+ case ExpressionType.TypeEqual:
+ EmitTypeBinaryExpression(node);
+ break;
+ case ExpressionType.OnesComplement:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.IsTrue:
+ EmitUnaryExpression(node, flags);
+ break;
+ case ExpressionType.IsFalse:
+ EmitUnaryExpression(node, flags);
+ break;
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default:
+ throw ContractUtils.Unreachable;
+ }
+
+ if (emitStart) {
+ EmitExpressionEnd(startEmitted);
+ }
+ }
+
+ private static bool IsChecked(ExpressionType op) {
+ switch (op) {
+ #region Generated Checked Operations
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_checked_ops from: generate_tree.py
+
+ case ExpressionType.AddChecked:
+ case ExpressionType.ConvertChecked:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.AddAssignChecked:
+ case ExpressionType.MultiplyAssignChecked:
+ case ExpressionType.SubtractAssignChecked:
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ return true;
+ }
+ return false;
+ }
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Lambda.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Lambda.cs
new file mode 100644
index 00000000000..f789af9dabd
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Lambda.cs
@@ -0,0 +1,202 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Threading;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ /// <summary>
+ /// Dynamic Language Runtime Compiler.
+ /// This part compiles lambdas.
+ /// </summary>
+ partial class LambdaCompiler {
+ private static int _Counter;
+
+ internal void EmitConstantArray<T>(T[] array) {
+ // Emit as runtime constant if possible
+ // if not, emit into IL
+ if (_method is DynamicMethod) {
+ EmitConstant(array, typeof(T[]));
+ } else if(_typeBuilder != null) {
+ // store into field in our type builder, we will initialize
+ // the value only once.
+ FieldBuilder fb = CreateStaticField("ConstantArray", typeof(T[]));
+ Label l = _ilg.DefineLabel();
+ _ilg.Emit(OpCodes.Ldsfld, fb);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Bne_Un, l);
+ _ilg.EmitArray(array);
+ _ilg.Emit(OpCodes.Stsfld, fb);
+ _ilg.MarkLabel(l);
+ _ilg.Emit(OpCodes.Ldsfld, fb);
+ } else {
+ _ilg.EmitArray(array);
+ }
+ }
+
+ private void EmitClosureCreation(LambdaCompiler inner) {
+ bool closure = inner._scope.NeedsClosure;
+ bool boundConstants = inner._boundConstants.Count > 0;
+
+ if (!closure && !boundConstants) {
+ _ilg.EmitNull();
+ return;
+ }
+
+ // new Closure(constantPool, currentHoistedLocals)
+ if (boundConstants) {
+ _boundConstants.EmitConstant(this, inner._boundConstants.ToArray(), typeof(object[]));
+ } else {
+ _ilg.EmitNull();
+ }
+ if (closure) {
+ _scope.EmitGet(_scope.NearestHoistedLocals.SelfVariable);
+ } else {
+ _ilg.EmitNull();
+ }
+ _ilg.EmitNew(typeof(Closure).GetConstructor(new Type[] { typeof(object[]), typeof(object[]) }));
+ }
+
+ /// <summary>
+ /// Emits code which creates new instance of the delegateType delegate.
+ ///
+ /// Since the delegate is getting closed over the "Closure" argument, this
+ /// cannot be used with virtual/instance methods (inner must be static method)
+ /// </summary>
+ private void EmitDelegateConstruction(LambdaCompiler inner) {
+ Type delegateType = inner._lambda.Type;
+ DynamicMethod dynamicMethod = inner._method as DynamicMethod;
+ if (dynamicMethod != null) {
+ // dynamicMethod.CreateDelegate(delegateType, closure)
+ _boundConstants.EmitConstant(this, dynamicMethod, typeof(DynamicMethod));
+ _ilg.EmitType(delegateType);
+ EmitClosureCreation(inner);
+ _ilg.Emit(OpCodes.Callvirt, typeof(DynamicMethod).GetMethod("CreateDelegate", new Type[] { typeof(Type), typeof(object) }));
+ _ilg.Emit(OpCodes.Castclass, delegateType);
+ } else {
+ // new DelegateType(closure)
+ EmitClosureCreation(inner);
+ _ilg.Emit(OpCodes.Ldftn, (MethodInfo)inner._method);
+ _ilg.Emit(OpCodes.Newobj, (ConstructorInfo)(delegateType.GetMember(".ctor")[0]));
+ }
+ }
+
+ /// <summary>
+ /// Emits a delegate to the method generated for the LambdaExpression.
+ /// May end up creating a wrapper to match the requested delegate type.
+ /// </summary>
+ /// <param name="lambda">Lambda for which to generate a delegate</param>
+ ///
+ private void EmitDelegateConstruction(LambdaExpression lambda) {
+ // 1. Create the new compiler
+ LambdaCompiler impl;
+ if (_method is DynamicMethod) {
+ impl = new LambdaCompiler(_tree, lambda);
+ } else {
+ // When the lambda does not have a name or the name is empty, generate a unique name for it.
+ string name = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
+ MethodBuilder mb = _typeBuilder.DefineMethod(name, MethodAttributes.Private | MethodAttributes.Static);
+ impl = new LambdaCompiler(_tree, lambda, mb);
+ }
+
+ // 2. emit the lambda
+ // Since additional ILs are always emitted after the lambda's body, should not emit with tail call optimization.
+ impl.EmitLambdaBody(_scope, false, CompilationFlags.EmitAsNoTail);
+
+ // 3. emit the delegate creation in the outer lambda
+ EmitDelegateConstruction(impl);
+ }
+
+ private static Type[] GetParameterTypes(LambdaExpression lambda) {
+ return lambda.Parameters.Map(p => p.IsByRef ? p.Type.MakeByRefType() : p.Type);
+ }
+
+ private static string GetUniqueMethodName() {
+ return "<ExpressionCompilerImplementationDetails>{" + Interlocked.Increment(ref _Counter) + "}lambda_method";
+ }
+
+ private void EmitLambdaBody() {
+ // The lambda body is the "last" expression of the lambda
+ CompilationFlags tailCallFlag = _lambda.TailCall ? CompilationFlags.EmitAsTail : CompilationFlags.EmitAsNoTail;
+ EmitLambdaBody(null, false, tailCallFlag);
+ }
+
+ /// <summary>
+ /// Emits the lambda body. If inlined, the parameters should already be
+ /// pushed onto the IL stack.
+ /// </summary>
+ /// <param name="parent">The parent scope.</param>
+ /// <param name="inlined">true if the lambda is inlined; false otherwise.</param>
+ /// <param name="flags">
+ /// The emum to specify if the lambda is compiled with the tail call optimization.
+ /// </param>
+ private void EmitLambdaBody(CompilerScope parent, bool inlined, CompilationFlags flags) {
+ _scope.Enter(this, parent);
+
+ if (inlined) {
+ // The arguments were already pushed onto the IL stack.
+ // Store them into locals, popping in reverse order.
+ //
+ // If any arguments were ByRef, the address is on the stack and
+ // we'll be storing it into the variable, which has a ref type.
+ for (int i = _lambda.Parameters.Count - 1; i >= 0; i--) {
+ _scope.EmitSet(_lambda.Parameters[i]);
+ }
+ }
+
+ // Need to emit the expression start for the lambda body
+ flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart);
+ if (_lambda.ReturnType == typeof(void)) {
+ EmitExpressionAsVoid(_lambda.Body, flags);
+ } else {
+ EmitExpression(_lambda.Body, flags);
+ }
+
+ // Return must be the last instruction in a CLI method.
+ // But if we're inlining the lambda, we want to leave the return
+ // value on the IL stack.
+ if (!inlined) {
+ _ilg.Emit(OpCodes.Ret);
+ }
+
+ _scope.Exit();
+
+ // Validate labels
+ Debug.Assert(_labelBlock.Parent == null && _labelBlock.Kind == LabelScopeKind.Lambda);
+ foreach (LabelInfo label in _labelInfo.Values) {
+ label.ValidateFinish();
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Logical.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Logical.cs
new file mode 100644
index 00000000000..2dd68e61706
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Logical.cs
@@ -0,0 +1,651 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ partial class LambdaCompiler {
+
+ #region Conditional
+
+ private void EmitConditionalExpression(Expression expr, CompilationFlags flags) {
+ ConditionalExpression node = (ConditionalExpression)expr;
+ Debug.Assert(node.Test.Type == typeof(bool));
+ Label labFalse = _ilg.DefineLabel();
+ EmitExpressionAndBranch(false, node.Test, labFalse);
+ EmitExpressionAsType(node.IfTrue, node.Type, flags);
+
+ if (NotEmpty(node.IfFalse)) {
+ Label labEnd = _ilg.DefineLabel();
+ if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail) {
+ // We know the conditional expression is at the end of the lambda,
+ // so it is safe to emit Ret here.
+ _ilg.Emit(OpCodes.Ret);
+ } else {
+ _ilg.Emit(OpCodes.Br, labEnd);
+ }
+ _ilg.MarkLabel(labFalse);
+ EmitExpressionAsType(node.IfFalse, node.Type, flags);
+ _ilg.MarkLabel(labEnd);
+ } else {
+ _ilg.MarkLabel(labFalse);
+ }
+ }
+
+ /// <summary>
+ /// returns true if the expression is not empty, otherwise false.
+ /// </summary>
+ private static bool NotEmpty(Expression node) {
+ var empty = node as DefaultExpression;
+ if (empty == null || empty.Type != typeof(void)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// returns true if the expression is NOT empty and is not debug info,
+ /// or a block that contains only insignificant expressions.
+ /// </summary>
+ private static bool Significant(Expression node) {
+ var block = node as BlockExpression;
+ if (block != null) {
+ for (int i = 0; i < block.ExpressionCount; i++) {
+ if (Significant(block.GetExpression(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return NotEmpty(node) && !(node is DebugInfoExpression);
+ }
+
+ #endregion
+
+ #region Coalesce
+
+
+ private void EmitCoalesceBinaryExpression(Expression expr) {
+ BinaryExpression b = (BinaryExpression)expr;
+ Debug.Assert(b.Method == null);
+
+ if (TypeUtils.IsNullableType(b.Left.Type)) {
+ EmitNullableCoalesce(b);
+ } else if (b.Left.Type.IsValueType) {
+ throw Error.CoalesceUsedOnNonNullType();
+ } else if (b.Conversion != null) {
+ EmitLambdaReferenceCoalesce(b);
+ } else {
+ EmitReferenceCoalesceWithoutConversion(b);
+ }
+ }
+
+
+ private void EmitNullableCoalesce(BinaryExpression b) {
+ Debug.Assert(b.Method == null);
+
+ LocalBuilder loc = GetLocal(b.Left.Type);
+ Label labIfNull = _ilg.DefineLabel();
+ Label labEnd = _ilg.DefineLabel();
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitHasValue(b.Left.Type);
+ _ilg.Emit(OpCodes.Brfalse, labIfNull);
+
+ Type nnLeftType = TypeUtils.GetNonNullableType(b.Left.Type);
+ if (b.Conversion != null) {
+ Debug.Assert(b.Conversion.Parameters.Count == 1);
+ ParameterExpression p = b.Conversion.Parameters[0];
+ Debug.Assert(p.Type.IsAssignableFrom(b.Left.Type) ||
+ p.Type.IsAssignableFrom(nnLeftType));
+
+ // emit the delegate instance
+ EmitLambdaExpression(b.Conversion);
+
+ // emit argument
+ if (!p.Type.IsAssignableFrom(b.Left.Type)) {
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitGetValueOrDefault(b.Left.Type);
+ } else {
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ }
+
+ // emit call to invoke
+ _ilg.Emit(OpCodes.Callvirt, b.Conversion.Type.GetMethod("Invoke"));
+ } else if (!TypeUtils.AreEquivalent(b.Type, nnLeftType)) {
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitGetValueOrDefault(b.Left.Type);
+ _ilg.EmitConvertToType(nnLeftType, b.Type, true);
+ } else {
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitGetValueOrDefault(b.Left.Type);
+ }
+ FreeLocal(loc);
+
+ _ilg.Emit(OpCodes.Br, labEnd);
+ _ilg.MarkLabel(labIfNull);
+ EmitExpression(b.Right);
+ if (!TypeUtils.AreEquivalent(b.Right.Type, b.Type)) {
+ _ilg.EmitConvertToType(b.Right.Type, b.Type, true);
+ }
+ _ilg.MarkLabel(labEnd);
+ }
+
+
+ private void EmitLambdaReferenceCoalesce(BinaryExpression b) {
+ LocalBuilder loc = GetLocal(b.Left.Type);
+ Label labEnd = _ilg.DefineLabel();
+ Label labNotNull = _ilg.DefineLabel();
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse, labNotNull);
+ EmitExpression(b.Right);
+ _ilg.Emit(OpCodes.Br, labEnd);
+
+ // if not null, call conversion
+ _ilg.MarkLabel(labNotNull);
+ Debug.Assert(b.Conversion.Parameters.Count == 1);
+ ParameterExpression p = b.Conversion.Parameters[0];
+
+ // emit the delegate instance
+ EmitLambdaExpression(b.Conversion);
+
+ // emit argument
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ FreeLocal(loc);
+
+ // emit call to invoke
+ _ilg.Emit(OpCodes.Callvirt, b.Conversion.Type.GetMethod("Invoke"));
+
+ _ilg.MarkLabel(labEnd);
+ }
+
+
+ private void EmitReferenceCoalesceWithoutConversion(BinaryExpression b) {
+ Label labEnd = _ilg.DefineLabel();
+ Label labCast = _ilg.DefineLabel();
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Ldnull);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse, labCast);
+ _ilg.Emit(OpCodes.Pop);
+ EmitExpression(b.Right);
+ if (!TypeUtils.AreEquivalent(b.Right.Type, b.Type)) {
+ if (b.Right.Type.IsValueType) {
+ _ilg.Emit(OpCodes.Box, b.Right.Type);
+ }
+ _ilg.Emit(OpCodes.Castclass, b.Type);
+ }
+ _ilg.Emit(OpCodes.Br_S, labEnd);
+ _ilg.MarkLabel(labCast);
+ if (!TypeUtils.AreEquivalent(b.Left.Type, b.Type)) {
+ Debug.Assert(!b.Left.Type.IsValueType);
+ _ilg.Emit(OpCodes.Castclass, b.Type);
+ }
+ _ilg.MarkLabel(labEnd);
+ }
+
+ #endregion
+
+ #region AndAlso
+
+ private void EmitLiftedAndAlso(BinaryExpression b) {
+ Type type = typeof(bool?);
+ Label labComputeRight = _ilg.DefineLabel();
+ Label labReturnFalse = _ilg.DefineLabel();
+ Label labReturnNull = _ilg.DefineLabel();
+ Label labReturnValue = _ilg.DefineLabel();
+ Label labExit = _ilg.DefineLabel();
+ LocalBuilder locLeft = GetLocal(type);
+ LocalBuilder locRight = GetLocal(type);
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labComputeRight);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brtrue, labReturnFalse);
+ // compute right
+ _ilg.MarkLabel(labComputeRight);
+ EmitExpression(b.Right);
+ _ilg.Emit(OpCodes.Stloc, locRight);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse_S, labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brtrue_S, labReturnFalse);
+ // check left for null again
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labReturnNull);
+ // return true
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+ // return false
+ _ilg.MarkLabel(labReturnFalse);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+ _ilg.MarkLabel(labReturnValue);
+ ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(bool) });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+ _ilg.Emit(OpCodes.Br, labExit);
+ // return null
+ _ilg.MarkLabel(labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.Emit(OpCodes.Initobj, type);
+ _ilg.MarkLabel(labExit);
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+ FreeLocal(locLeft);
+ FreeLocal(locRight);
+ }
+
+ private void EmitMethodAndAlso(BinaryExpression b, CompilationFlags flags) {
+ Label labEnd = _ilg.DefineLabel();
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Dup);
+ MethodInfo opFalse = TypeUtils.GetBooleanOperator(b.Method.DeclaringType, "op_False");
+ Debug.Assert(opFalse != null, "factory should check that the method exists");
+ _ilg.Emit(OpCodes.Call, opFalse);
+ _ilg.Emit(OpCodes.Brtrue, labEnd);
+
+ //store the value of the left value before emitting b.Right to empty the evaluation stack
+ LocalBuilder locLeft = GetLocal(b.Left.Type);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+
+ EmitExpression(b.Right);
+ //store the right value to local
+ LocalBuilder locRight = GetLocal(b.Right.Type);
+ _ilg.Emit(OpCodes.Stloc, locRight);
+
+ Debug.Assert(b.Method.IsStatic);
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+ _ilg.Emit(OpCodes.Ldloc, locRight);
+ if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail) {
+ _ilg.Emit(OpCodes.Tailcall);
+ }
+ _ilg.Emit(OpCodes.Call, b.Method);
+ FreeLocal(locLeft);
+ FreeLocal(locRight);
+ _ilg.MarkLabel(labEnd);
+ }
+
+ private void EmitUnliftedAndAlso(BinaryExpression b) {
+ Label @else = _ilg.DefineLabel();
+ Label end = _ilg.DefineLabel();
+ EmitExpressionAndBranch(false, b.Left, @else);
+ EmitExpression(b.Right);
+ _ilg.Emit(OpCodes.Br, end);
+ _ilg.MarkLabel(@else);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.MarkLabel(end);
+ }
+
+ private void EmitAndAlsoBinaryExpression(Expression expr, CompilationFlags flags) {
+ BinaryExpression b = (BinaryExpression)expr;
+
+ if (b.Method != null && !b.IsLiftedLogical) {
+ EmitMethodAndAlso(b, flags);
+ } else if (b.Left.Type == typeof(bool?)) {
+ EmitLiftedAndAlso(b);
+ } else if (b.IsLiftedLogical) {
+ EmitExpression(b.ReduceUserdefinedLifted());
+ } else {
+ EmitUnliftedAndAlso(b);
+ }
+ }
+
+ #endregion
+
+ #region OrElse
+
+ private void EmitLiftedOrElse(BinaryExpression b) {
+ Type type = typeof(bool?);
+ Label labComputeRight = _ilg.DefineLabel();
+ Label labReturnTrue = _ilg.DefineLabel();
+ Label labReturnNull = _ilg.DefineLabel();
+ Label labReturnValue = _ilg.DefineLabel();
+ Label labExit = _ilg.DefineLabel();
+ LocalBuilder locLeft = GetLocal(type);
+ LocalBuilder locRight = GetLocal(type);
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labComputeRight);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse, labReturnTrue);
+ // compute right
+ _ilg.MarkLabel(labComputeRight);
+ EmitExpression(b.Right);
+ _ilg.Emit(OpCodes.Stloc, locRight);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse_S, labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locRight);
+ _ilg.EmitGetValueOrDefault(type);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse_S, labReturnTrue);
+ // check left for null again
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.EmitHasValue(type);
+ _ilg.Emit(OpCodes.Brfalse, labReturnNull);
+ // return false
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+ // return true
+ _ilg.MarkLabel(labReturnTrue);
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Br_S, labReturnValue);
+ _ilg.MarkLabel(labReturnValue);
+ ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(bool) });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+ _ilg.Emit(OpCodes.Br, labExit);
+ // return null
+ _ilg.MarkLabel(labReturnNull);
+ _ilg.Emit(OpCodes.Ldloca, locLeft);
+ _ilg.Emit(OpCodes.Initobj, type);
+ _ilg.MarkLabel(labExit);
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+ FreeLocal(locLeft);
+ FreeLocal(locRight);
+ }
+
+ private void EmitUnliftedOrElse(BinaryExpression b) {
+ Label @else = _ilg.DefineLabel();
+ Label end = _ilg.DefineLabel();
+ EmitExpressionAndBranch(false, b.Left, @else);
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Br, end);
+ _ilg.MarkLabel(@else);
+ EmitExpression(b.Right);
+ _ilg.MarkLabel(end);
+ }
+
+ private void EmitMethodOrElse(BinaryExpression b, CompilationFlags flags) {
+ Label labEnd = _ilg.DefineLabel();
+ EmitExpression(b.Left);
+ _ilg.Emit(OpCodes.Dup);
+ MethodInfo opTrue = TypeUtils.GetBooleanOperator(b.Method.DeclaringType, "op_True");
+ Debug.Assert(opTrue != null, "factory should check that the method exists");
+ _ilg.Emit(OpCodes.Call, opTrue);
+ _ilg.Emit(OpCodes.Brtrue, labEnd);
+
+ //store the value of the left value before emitting b.Right to empty the evaluation stack
+ LocalBuilder locLeft = GetLocal(b.Left.Type);
+ _ilg.Emit(OpCodes.Stloc, locLeft);
+
+ EmitExpression(b.Right);
+ //store the right value to local
+ LocalBuilder locRight = GetLocal(b.Right.Type);
+ _ilg.Emit(OpCodes.Stloc, locRight);
+
+ Debug.Assert(b.Method.IsStatic);
+ _ilg.Emit(OpCodes.Ldloc, locLeft);
+ _ilg.Emit(OpCodes.Ldloc, locRight);
+ if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail) {
+ _ilg.Emit(OpCodes.Tailcall);
+ }
+ _ilg.Emit(OpCodes.Call, b.Method);
+ FreeLocal(locLeft);
+ FreeLocal(locRight);
+ _ilg.MarkLabel(labEnd);
+ }
+
+ private void EmitOrElseBinaryExpression(Expression expr, CompilationFlags flags) {
+ BinaryExpression b = (BinaryExpression)expr;
+
+ if (b.Method != null && !b.IsLiftedLogical) {
+ EmitMethodOrElse(b, flags);
+ } else if (b.Left.Type == typeof(bool?)) {
+ EmitLiftedOrElse(b);
+ } else if (b.IsLiftedLogical) {
+ EmitExpression(b.ReduceUserdefinedLifted());
+ } else {
+ EmitUnliftedOrElse(b);
+ }
+ }
+
+ #endregion
+
+ #region Optimized branching
+
+ /// <summary>
+ /// Emits the expression and then either brtrue/brfalse to the label.
+ /// </summary>
+ /// <param name="branchValue">True for brtrue, false for brfalse.</param>
+ /// <param name="node">The expression to emit.</param>
+ /// <param name="label">The label to conditionally branch to.</param>
+ /// <remarks>
+ /// This function optimizes equality and short circuiting logical
+ /// operators to avoid double-branching, minimize instruction count,
+ /// and generate similar IL to the C# compiler. This is important for
+ /// the JIT to optimize patterns like:
+ /// x != null AndAlso x.GetType() == typeof(SomeType)
+ ///
+ /// One optimization we don't do: we always emits at least one
+ /// conditional branch to the label, and always possibly falls through,
+ /// even if we know if the branch will always succeed or always fail.
+ /// We do this to avoid generating unreachable code, which is fine for
+ /// the CLR JIT, but doesn't verify with peverify.
+ ///
+ /// This kind of optimization could be implemented safely, by doing
+ /// constant folding over conditionals and logical expressions at the
+ /// tree level.
+ /// </remarks>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
+ private void EmitExpressionAndBranch(bool branchValue, Expression node, Label label) {
+ CompilationFlags startEmitted = EmitExpressionStart(node);
+ try {
+ if (node.Type == typeof(bool)) {
+ switch (node.NodeType) {
+ case ExpressionType.Not:
+ EmitBranchNot(branchValue, (UnaryExpression)node, label);
+ return;
+ case ExpressionType.AndAlso:
+ case ExpressionType.OrElse:
+ EmitBranchLogical(branchValue, (BinaryExpression)node, label);
+ return;
+ case ExpressionType.Block:
+ EmitBranchBlock(branchValue, (BlockExpression)node, label);
+ return;
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ EmitBranchComparison(branchValue, (BinaryExpression)node, label);
+ return;
+ }
+ }
+ EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
+ EmitBranchOp(branchValue, label);
+ } finally {
+ EmitExpressionEnd(startEmitted);
+ }
+ }
+
+ private void EmitBranchOp(bool branch, Label label) {
+ _ilg.Emit(branch ? OpCodes.Brtrue : OpCodes.Brfalse, label);
+ }
+
+ private void EmitBranchNot(bool branch, UnaryExpression node, Label label) {
+ if (node.Method != null) {
+ EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart);
+ EmitBranchOp(branch, label);
+ return;
+ }
+ EmitExpressionAndBranch(!branch, node.Operand, label);
+ }
+
+ private void EmitBranchComparison(bool branch, BinaryExpression node, Label label) {
+ Debug.Assert(node.NodeType == ExpressionType.Equal || node.NodeType == ExpressionType.NotEqual);
+ Debug.Assert(!node.IsLiftedToNull);
+
+ // To share code paths, we want to treat NotEqual as an inverted Equal
+ bool branchWhenEqual = branch == (node.NodeType == ExpressionType.Equal);
+
+ if (node.Method != null) {
+ EmitBinaryMethod(node, CompilationFlags.EmitAsNoTail);
+ // EmitBinaryMethod takes into account the Equal/NotEqual
+ // node kind, so use the original branch value
+ EmitBranchOp(branch, label);
+ } else if (ConstantCheck.IsNull(node.Left)) {
+ if (TypeUtils.IsNullableType(node.Right.Type)) {
+ EmitAddress(node.Right, node.Right.Type);
+ _ilg.EmitHasValue(node.Right.Type);
+ } else {
+ Debug.Assert(!node.Right.Type.IsValueType);
+ EmitExpression(GetEqualityOperand(node.Right));
+ }
+ EmitBranchOp(!branchWhenEqual, label);
+ } else if (ConstantCheck.IsNull(node.Right)) {
+ if (TypeUtils.IsNullableType(node.Left.Type)) {
+ EmitAddress(node.Left, node.Left.Type);
+ _ilg.EmitHasValue(node.Left.Type);
+ } else {
+ Debug.Assert(!node.Left.Type.IsValueType);
+ EmitExpression(GetEqualityOperand(node.Left));
+ }
+ EmitBranchOp(!branchWhenEqual, label);
+ } else if (TypeUtils.IsNullableType(node.Left.Type) || TypeUtils.IsNullableType(node.Right.Type)) {
+ EmitBinaryExpression(node);
+ // EmitBinaryExpression takes into account the Equal/NotEqual
+ // node kind, so use the original branch value
+ EmitBranchOp(branch, label);
+ } else {
+ EmitExpression(GetEqualityOperand(node.Left));
+ EmitExpression(GetEqualityOperand(node.Right));
+ if (branchWhenEqual) {
+ _ilg.Emit(OpCodes.Beq, label);
+ } else {
+ _ilg.Emit(OpCodes.Ceq);
+ _ilg.Emit(OpCodes.Brfalse, label);
+ }
+ }
+ }
+
+ // For optimized Equal/NotEqual, we can eliminate reference
+ // conversions. IL allows comparing managed pointers regardless of
+ // type. See ECMA-335 "Binary Comparison or Branch Operations", in
+ // Partition III, Section 1.5 Table 4.
+ private static Expression GetEqualityOperand(Expression expression) {
+ if (expression.NodeType == ExpressionType.Convert) {
+ var convert = (UnaryExpression)expression;
+ if (TypeUtils.AreReferenceAssignable(convert.Type, convert.Operand.Type)) {
+ return convert.Operand;
+ }
+ }
+ return expression;
+ }
+
+ private void EmitBranchLogical(bool branch, BinaryExpression node, Label label) {
+ Debug.Assert(node.NodeType == ExpressionType.AndAlso || node.NodeType == ExpressionType.OrElse);
+ Debug.Assert(!node.IsLiftedToNull);
+
+ if (node.Method != null || node.IsLifted) {
+ EmitExpression(node);
+ EmitBranchOp(branch, label);
+ return;
+ }
+
+
+ bool isAnd = node.NodeType == ExpressionType.AndAlso;
+
+ // To share code, we make the following substitutions:
+ // if (!(left || right)) branch value
+ // becomes:
+ // if (!left && !right) branch value
+ // and:
+ // if (!(left && right)) branch value
+ // becomes:
+ // if (!left || !right) branch value
+ //
+ // The observation is that "brtrue(x && y)" has the same codegen as
+ // "brfalse(x || y)" except the branches have the opposite sign.
+ // Same for "brfalse(x && y)" and "brtrue(x || y)".
+ //
+ if (branch == isAnd) {
+ EmitBranchAnd(branch, node, label);
+ } else {
+ EmitBranchOr(branch, node, label);
+ }
+ }
+
+ // Generates optimized AndAlso with branch == true
+ // or optimized OrElse with branch == false
+ private void EmitBranchAnd(bool branch, BinaryExpression node, Label label) {
+ // if (left) then
+ // if (right) branch label
+ // endif
+
+ Label endif = _ilg.DefineLabel();
+ EmitExpressionAndBranch(!branch, node.Left, endif);
+ EmitExpressionAndBranch(branch, node.Right, label);
+ _ilg.MarkLabel(endif);
+ }
+
+ // Generates optimized OrElse with branch == true
+ // or optimized AndAlso with branch == false
+ private void EmitBranchOr(bool branch, BinaryExpression node, Label label) {
+ // if (left OR right) branch label
+
+ EmitExpressionAndBranch(branch, node.Left, label);
+ EmitExpressionAndBranch(branch, node.Right, label);
+ }
+
+ private void EmitBranchBlock(bool branch, BlockExpression node, Label label) {
+ EnterScope(node);
+
+ int count = node.ExpressionCount;
+ for (int i = 0; i < count - 1; i++) {
+ EmitExpressionAsVoid(node.GetExpression(i));
+ }
+ EmitExpressionAndBranch(branch, node.GetExpression(count - 1), label);
+
+ ExitScope(node);
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Statements.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Statements.cs
new file mode 100644
index 00000000000..530bda3a03d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Statements.cs
@@ -0,0 +1,824 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Globalization;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ partial class LambdaCompiler {
+ private void EmitBlockExpression(Expression expr, CompilationFlags flags) {
+ // emit body
+ Emit((BlockExpression)expr, UpdateEmitAsTypeFlag(flags, CompilationFlags.EmitAsDefaultType));
+ }
+
+ private void Emit(BlockExpression node, CompilationFlags flags) {
+ EnterScope(node);
+
+ CompilationFlags emitAs = flags & CompilationFlags.EmitAsTypeMask;
+
+ int count = node.ExpressionCount;
+ CompilationFlags tailCall = flags & CompilationFlags.EmitAsTailCallMask;
+ CompilationFlags middleTailCall = tailCall == CompilationFlags.EmitAsNoTail ? CompilationFlags.EmitAsNoTail : CompilationFlags.EmitAsMiddle;
+
+ for (int index = 0; index < count - 1; index++) {
+ var e = node.GetExpression(index);
+ var next = node.GetExpression(index + 1);
+
+ if (EmitDebugSymbols) {
+ // No need to emit a clearance if the next expression in the block is also a
+ // DebugInfoExprssion.
+ var debugInfo = e as DebugInfoExpression;
+ if (debugInfo != null && debugInfo.IsClear && next is DebugInfoExpression) {
+ continue;
+ }
+ }
+ // In the middle of the block.
+ // We may do better here by marking it as Tail if the following expressions are not going to emit any IL.
+ var tailCallFlag = middleTailCall;
+
+ var g = next as GotoExpression;
+ if (g != null && (g.Value == null || !Significant(g.Value))) {
+ var labelInfo = ReferenceLabel(g.Target);
+ if (labelInfo.CanReturn) {
+ // Since tail call flags are not passed into EmitTryExpression, CanReturn means the goto will be emitted
+ // as Ret. Therefore we can emit the current expression with tail call.
+ tailCallFlag = CompilationFlags.EmitAsTail;
+ }
+ }
+ flags = UpdateEmitAsTailCallFlag(flags, tailCallFlag);
+ EmitExpressionAsVoid(e, flags);
+ }
+
+ // if the type of Block it means this is not a Comma
+ // so we will force the last expression to emit as void.
+ // We don't need EmitAsType flag anymore, should only pass
+ // the EmitTailCall field in flags to emitting the last expression.
+ if (emitAs == CompilationFlags.EmitAsVoidType || node.Type == typeof(void)) {
+ EmitExpressionAsVoid(node.GetExpression(count - 1), tailCall);
+ } else {
+ EmitExpressionAsType(node.GetExpression(count - 1), node.Type, tailCall);
+ }
+
+ ExitScope(node);
+ }
+
+ private void EnterScope(object node) {
+ if (HasVariables(node) &&
+ (_scope.MergedScopes == null || !_scope.MergedScopes.Contains(node))) {
+
+ CompilerScope scope;
+ if (!_tree.Scopes.TryGetValue(node, out scope)) {
+ //
+ // Very often, we want to compile nodes as reductions
+ // rather than as IL, but usually they need to allocate
+ // some IL locals. To support this, we allow emitting a
+ // BlockExpression that was not bound by VariableBinder.
+ // This works as long as the variables are only used
+ // locally -- i.e. not closed over.
+ //
+ // User-created blocks will never hit this case; only our
+ // internally reduced nodes will.
+ //
+ scope = new CompilerScope(node, false) { NeedsClosure = _scope.NeedsClosure };
+ }
+
+ _scope = scope.Enter(this, _scope);
+ Debug.Assert(_scope.Node == node);
+ }
+ }
+
+ private static bool HasVariables(object node) {
+ var block = node as BlockExpression;
+ if (block != null) {
+ return block.Variables.Count > 0;
+ }
+ return ((CatchBlock)node).Variable != null;
+ }
+
+ private void ExitScope(object node) {
+ if (_scope.Node == node) {
+ _scope = _scope.Exit();
+ }
+ }
+
+ private void EmitDefaultExpression(Expression expr) {
+ var node = (DefaultExpression)expr;
+ if (node.Type != typeof(void)) {
+ // emit default(T)
+ _ilg.EmitDefault(node.Type);
+ }
+ }
+
+ private void EmitLoopExpression(Expression expr) {
+ LoopExpression node = (LoopExpression)expr;
+
+ PushLabelBlock(LabelScopeKind.Statement);
+ LabelInfo breakTarget = DefineLabel(node.BreakLabel);
+ LabelInfo continueTarget = DefineLabel(node.ContinueLabel);
+
+ continueTarget.MarkWithEmptyStack();
+
+ EmitExpressionAsVoid(node.Body);
+
+ _ilg.Emit(OpCodes.Br, continueTarget.Label);
+
+ PopLabelBlock(LabelScopeKind.Statement);
+
+ breakTarget.MarkWithEmptyStack();
+ }
+
+ #region SwitchExpression
+
+ private void EmitSwitchExpression(Expression expr, CompilationFlags flags) {
+ SwitchExpression node = (SwitchExpression)expr;
+
+ // Try to emit it as an IL switch. Works for integer types.
+ if (TryEmitSwitchInstruction(node, flags)) {
+ return;
+ }
+
+ // Try to emit as a hashtable lookup. Works for strings.
+ if (TryEmitHashtableSwitch(node, flags)) {
+ return;
+ }
+
+ //
+ // Fall back to a series of tests. We need to IL gen instead of
+ // transform the tree to avoid stack overflow on a big switch.
+ //
+
+ var switchValue = Expression.Parameter(node.SwitchValue.Type, "switchValue");
+ var testValue = Expression.Parameter(GetTestValueType(node), "testValue");
+ _scope.AddLocal(this, switchValue);
+ _scope.AddLocal(this, testValue);
+
+ EmitExpression(node.SwitchValue);
+ _scope.EmitSet(switchValue);
+
+ // Emit tests
+ var labels = new Label[node.Cases.Count];
+ var isGoto = new bool[node.Cases.Count];
+ for (int i = 0, n = node.Cases.Count; i < n; i++) {
+ DefineSwitchCaseLabel(node.Cases[i], out labels[i], out isGoto[i]);
+ foreach (Expression test in node.Cases[i].TestValues) {
+ // Pull the test out into a temp so it runs on the same
+ // stack as the switch. This simplifies spilling.
+ EmitExpression(test);
+ _scope.EmitSet(testValue);
+ Debug.Assert(TypeUtils.AreReferenceAssignable(testValue.Type, test.Type));
+ EmitExpressionAndBranch(true, Expression.Equal(switchValue, testValue, false, node.Comparison), labels[i]);
+ }
+ }
+
+ // Define labels
+ Label end = _ilg.DefineLabel();
+ Label @default = (node.DefaultBody == null) ? end : _ilg.DefineLabel();
+
+ // Emit the case and default bodies
+ EmitSwitchCases(node, labels, isGoto, @default, end, flags);
+ }
+
+ /// <summary>
+ /// Gets the common test test value type of the SwitchExpression.
+ /// </summary>
+ private static Type GetTestValueType(SwitchExpression node) {
+ if (node.Comparison == null) {
+ // If we have no comparison, all right side types must be the
+ // same.
+ return node.Cases[0].TestValues[0].Type;
+ }
+
+ // Otherwise, get the type from the method.
+ Type result = node.Comparison.GetParametersCached()[1].ParameterType.GetNonRefType();
+ if (node.IsLifted) {
+ result = TypeUtils.GetNullableType(result);
+ }
+ return result;
+ }
+
+ private sealed class SwitchLabel {
+ internal readonly decimal Key;
+ internal readonly Label Label;
+
+ // Boxed version of Key, preseving the original type.
+ internal readonly object Constant;
+
+ internal SwitchLabel(decimal key, object @constant, Label label) {
+ Key = key;
+ Constant = @constant;
+ Label = label;
+ }
+ }
+
+ private sealed class SwitchInfo {
+ internal readonly SwitchExpression Node;
+ internal readonly LocalBuilder Value;
+ internal readonly Label Default;
+ internal readonly Type Type;
+ internal readonly bool IsUnsigned;
+ internal readonly bool Is64BitSwitch;
+
+ internal SwitchInfo(SwitchExpression node, LocalBuilder value, Label @default) {
+ Node = node;
+ Value = value;
+ Default = @default;
+ Type = Node.SwitchValue.Type;
+ IsUnsigned = TypeUtils.IsUnsigned(Type);
+ var code = Type.GetTypeCode(Type);
+ Is64BitSwitch = code == TypeCode.UInt64 || code == TypeCode.Int64;
+ }
+ }
+
+ private static bool FitsInBucket(List<SwitchLabel> buckets, decimal key, int count) {
+ Debug.Assert(key > buckets[buckets.Count - 1].Key);
+ decimal jumpTableSlots = key - buckets[0].Key + 1;
+ if (jumpTableSlots > int.MaxValue) {
+ return false;
+ }
+ // density must be > 50%
+ return (buckets.Count + count) * 2 > jumpTableSlots;
+ }
+
+ private static void MergeBuckets(List<List<SwitchLabel>> buckets) {
+ while (buckets.Count > 1) {
+ List<SwitchLabel> first = buckets[buckets.Count - 2];
+ List<SwitchLabel> second = buckets[buckets.Count - 1];
+
+ if (!FitsInBucket(first, second[second.Count - 1].Key, second.Count)) {
+ return;
+ }
+
+ // Merge them
+ first.AddRange(second);
+ buckets.RemoveAt(buckets.Count - 1);
+ }
+ }
+
+ // Add key to a new or existing bucket
+ private static void AddToBuckets(List<List<SwitchLabel>> buckets, SwitchLabel key) {
+ if (buckets.Count > 0) {
+ List<SwitchLabel> last = buckets[buckets.Count - 1];
+ if (FitsInBucket(last, key.Key, 1)) {
+ last.Add(key);
+ // we might be able to merge now
+ MergeBuckets(buckets);
+ return;
+ }
+ }
+ // else create a new bucket
+ buckets.Add(new List<SwitchLabel> { key });
+ }
+
+ // Determines if the type is an integer we can switch on.
+ private static bool CanOptimizeSwitchType(Type valueType) {
+ // enums & char are allowed
+ switch (Type.GetTypeCode(valueType)) {
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Char:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // Tries to emit switch as a jmp table
+ private bool TryEmitSwitchInstruction(SwitchExpression node, CompilationFlags flags) {
+ // If we have a comparison, bail
+ if (node.Comparison != null) {
+ return false;
+ }
+
+ // Make sure the switch value type and the right side type
+ // are types we can optimize
+ Type type = node.SwitchValue.Type;
+ if (!CanOptimizeSwitchType(type) ||
+ !TypeUtils.AreEquivalent(type, node.Cases[0].TestValues[0].Type)) {
+ return false;
+ }
+
+ // Make sure all test values are constant, or we can't emit the
+ // jump table.
+ if (!node.Cases.All(c => c.TestValues.All(t => t is ConstantExpression))) {
+ return false;
+ }
+
+ //
+ // We can emit the optimized switch, let's do it.
+ //
+
+ // Build target labels, collect keys.
+ var labels = new Label[node.Cases.Count];
+ var isGoto = new bool[node.Cases.Count];
+
+ var uniqueKeys = new Set<decimal>();
+ var keys = new List<SwitchLabel>();
+ for (int i = 0; i < node.Cases.Count; i++) {
+
+ DefineSwitchCaseLabel(node.Cases[i], out labels[i], out isGoto[i]);
+
+ foreach (ConstantExpression test in node.Cases[i].TestValues) {
+ // Guarenteed to work thanks to CanOptimizeSwitchType.
+ //
+ // Use decimal because it can hold Int64 or UInt64 without
+ // precision loss or signed/unsigned conversions.
+ decimal key = ConvertSwitchValue(test.Value);
+
+ // Only add each key once. If it appears twice, it's
+ // allowed, but can't be reached.
+ if (!uniqueKeys.Contains(key)) {
+ keys.Add(new SwitchLabel(key, test.Value, labels[i]));
+ uniqueKeys.Add(key);
+ }
+ }
+ }
+
+ // Sort the keys, and group them into buckets.
+ keys.Sort((x, y) => Math.Sign(x.Key - y.Key));
+ var buckets = new List<List<SwitchLabel>>();
+ foreach (var key in keys) {
+ AddToBuckets(buckets, key);
+ }
+
+ // Emit the switchValue
+ LocalBuilder value = GetLocal(node.SwitchValue.Type);
+ EmitExpression(node.SwitchValue);
+ _ilg.Emit(OpCodes.Stloc, value);
+
+ // Create end label, and default label if needed
+ Label end = _ilg.DefineLabel();
+ Label @default = (node.DefaultBody == null) ? end : _ilg.DefineLabel();
+
+ // Emit the switch
+ var info = new SwitchInfo(node, value, @default);
+ EmitSwitchBuckets(info, buckets, 0, buckets.Count - 1);
+
+ // Emit the case bodies and default
+ EmitSwitchCases(node, labels, isGoto, @default, end, flags);
+
+ FreeLocal(value);
+ return true;
+ }
+
+ private static decimal ConvertSwitchValue(object value) {
+ if (value is char) {
+ return (int)(char)value;
+ }
+ return Convert.ToDecimal(value, CultureInfo.InvariantCulture);
+ }
+
+ /// <summary>
+ /// Creates the label for this case.
+ /// Optimization: if the body is just a goto, and we can branch
+ /// to it, put the goto target directly in the jump table.
+ /// </summary>
+ private void DefineSwitchCaseLabel(SwitchCase @case, out Label label, out bool isGoto) {
+ var jump = @case.Body as GotoExpression;
+ // if it's a goto with no value
+ if (jump != null && jump.Value == null) {
+ // Reference the label from the switch. This will cause us to
+ // analyze the jump target and determine if it is safe.
+ LabelInfo jumpInfo = ReferenceLabel(jump.Target);
+
+ // If we have are allowed to emit the "branch" opcode, then we
+ // can jump directly there from the switch's jump table.
+ // (Otherwise, we need to emit the goto later as a "leave".)
+ if (jumpInfo.CanBranch) {
+ label = jumpInfo.Label;
+ isGoto = true;
+ return;
+ }
+ }
+ // otherwise, just define a new label
+ label = _ilg.DefineLabel();
+ isGoto = false;
+ }
+
+ private void EmitSwitchCases(SwitchExpression node, Label[] labels, bool[] isGoto, Label @default, Label end, CompilationFlags flags) {
+ // Jump to default (to handle the fallthrough case)
+ _ilg.Emit(OpCodes.Br, @default);
+
+ // Emit the cases
+ for (int i = 0, n = node.Cases.Count; i < n; i++) {
+ // If the body is a goto, we already emitted an optimized
+ // branch directly to it. No need to emit anything else.
+ if (isGoto[i]) {
+ continue;
+ }
+
+ _ilg.MarkLabel(labels[i]);
+ EmitExpressionAsType(node.Cases[i].Body, node.Type, flags);
+
+ // Last case doesn't need branch
+ if (node.DefaultBody != null || i < n - 1) {
+ if ((flags & CompilationFlags.EmitAsTailCallMask) == CompilationFlags.EmitAsTail) {
+ //The switch case is at the tail of the lambda so
+ //it is safe to emit a Ret.
+ _ilg.Emit(OpCodes.Ret);
+ } else {
+ _ilg.Emit(OpCodes.Br, end);
+ }
+ }
+ }
+
+ // Default value
+ if (node.DefaultBody != null) {
+ _ilg.MarkLabel(@default);
+ EmitExpressionAsType(node.DefaultBody, node.Type, flags);
+ }
+
+ _ilg.MarkLabel(end);
+ }
+
+ private void EmitSwitchBuckets(SwitchInfo info, List<List<SwitchLabel>> buckets, int first, int last) {
+ if (first == last) {
+ EmitSwitchBucket(info, buckets[first]);
+ return;
+ }
+
+ // Split the buckets into two groups, and use an if test to find
+ // the right bucket. This ensures we'll only need O(lg(B)) tests
+ // where B is the number of buckets
+ int mid = (int)(((long)first + last + 1) / 2);
+
+ if (first == mid - 1) {
+ EmitSwitchBucket(info, buckets[first]);
+ } else {
+ // If the first half contains more than one, we need to emit an
+ // explicit guard
+ Label secondHalf = _ilg.DefineLabel();
+ _ilg.Emit(OpCodes.Ldloc, info.Value);
+ _ilg.EmitConstant(buckets[mid - 1].Last().Constant);
+ _ilg.Emit(info.IsUnsigned ? OpCodes.Bgt_Un : OpCodes.Bgt, secondHalf);
+ EmitSwitchBuckets(info, buckets, first, mid - 1);
+ _ilg.MarkLabel(secondHalf);
+ }
+
+ EmitSwitchBuckets(info, buckets, mid, last);
+ }
+
+ private void EmitSwitchBucket(SwitchInfo info, List<SwitchLabel> bucket) {
+ // No need for switch if we only have one value
+ if (bucket.Count == 1) {
+ _ilg.Emit(OpCodes.Ldloc, info.Value);
+ _ilg.EmitConstant(bucket[0].Constant);
+ _ilg.Emit(OpCodes.Beq, bucket[0].Label);
+ return;
+ }
+
+ //
+ // If we're switching off of Int64/UInt64, we need more guards here
+ // because we'll have to narrow the switch value to an Int32, and
+ // we can't do that unless the value is in the right range.
+ //
+ Label? after = null;
+ if (info.Is64BitSwitch) {
+ after = _ilg.DefineLabel();
+ _ilg.Emit(OpCodes.Ldloc, info.Value);
+ _ilg.EmitConstant(bucket.Last().Constant);
+ _ilg.Emit(info.IsUnsigned ? OpCodes.Bgt_Un : OpCodes.Bgt, after.Value);
+ _ilg.Emit(OpCodes.Ldloc, info.Value);
+ _ilg.EmitConstant(bucket[0].Constant);
+ _ilg.Emit(info.IsUnsigned ? OpCodes.Blt_Un : OpCodes.Blt, after.Value);
+ }
+
+ _ilg.Emit(OpCodes.Ldloc, info.Value);
+
+ // Normalize key
+ decimal key = bucket[0].Key;
+ if (key != 0) {
+ _ilg.EmitConstant(bucket[0].Constant);
+ _ilg.Emit(OpCodes.Sub);
+ }
+
+ if (info.Is64BitSwitch) {
+ _ilg.Emit(OpCodes.Conv_I4);
+ }
+
+ // Collect labels
+ int len = (int)(bucket[bucket.Count - 1].Key - bucket[0].Key + 1);
+ Label[] jmpLabels = new Label[len];
+
+ // Initialize all labels to the default
+ int slot = 0;
+ foreach (SwitchLabel label in bucket) {
+ while (key++ != label.Key) {
+ jmpLabels[slot++] = info.Default;
+ }
+ jmpLabels[slot++] = label.Label;
+ }
+
+ // check we used all keys and filled all slots
+ Debug.Assert(key == bucket[bucket.Count - 1].Key + 1);
+ Debug.Assert(slot == jmpLabels.Length);
+
+ // Finally, emit the switch instruction
+ _ilg.Emit(OpCodes.Switch, jmpLabels);
+
+ if (info.Is64BitSwitch) {
+ _ilg.MarkLabel(after.Value);
+ }
+ }
+
+ private bool TryEmitHashtableSwitch(SwitchExpression node, CompilationFlags flags) {
+ // If we have a comparison other than string equality, bail
+ if (node.Comparison != typeof(string).GetMethod("op_Equality", BindingFlags.Public | BindingFlags.Static | BindingFlags.ExactBinding, null, new[] { typeof(string), typeof(string) }, null)) {
+ return false;
+ }
+
+ // All test values must be constant.
+ int tests = 0;
+ foreach (SwitchCase c in node.Cases) {
+ foreach (Expression t in c.TestValues) {
+ if (!(t is ConstantExpression)) {
+ return false;
+ }
+ tests++;
+ }
+ }
+
+ // Must have >= 7 labels for it to be worth it.
+ if (tests < 7) {
+ return false;
+ }
+
+ // If we're in a DynamicMethod, we could just build the dictionary
+ // immediately. But that would cause the two code paths to be more
+ // different than they really need to be.
+ var initializers = new List<ElementInit>(tests);
+ var cases = new List<SwitchCase>(node.Cases.Count);
+
+ int nullCase = -1;
+ MethodInfo add = typeof(Dictionary<string, int>).GetMethod("Add", new[] { typeof(string), typeof(int) });
+ for (int i = 0, n = node.Cases.Count; i < n; i++) {
+ foreach (ConstantExpression t in node.Cases[i].TestValues) {
+ if (t.Value != null) {
+ initializers.Add(Expression.ElementInit(add, t, Expression.Constant(i)));
+ } else {
+ nullCase = i;
+ }
+ }
+ cases.Add(Expression.SwitchCase(node.Cases[i].Body, Expression.Constant(i)));
+ }
+
+ // Create the field to hold the lazily initialized dictionary
+ MemberExpression dictField = CreateLazyInitializedField<Dictionary<string, int>>("dictionarySwitch");
+
+ // If we happen to initialize it twice (multithreaded case), it's
+ // not the end of the world. The C# compiler does better here by
+ // emitting a volatile access to the field.
+ Expression dictInit = Expression.Condition(
+ Expression.Equal(dictField, Expression.Constant(null, dictField.Type)),
+ Expression.Assign(
+ dictField,
+ Expression.ListInit(
+ Expression.New(
+ typeof(Dictionary<string, int>).GetConstructor(new[] { typeof(int) }),
+ Expression.Constant(initializers.Count)
+ ),
+ initializers
+ )
+ ),
+ dictField
+ );
+
+ //
+ // Create a tree like:
+ //
+ // switchValue = switchValueExpression;
+ // if (switchValue == null) {
+ // switchIndex = nullCase;
+ // } else {
+ // if (_dictField == null) {
+ // _dictField = new Dictionary<string, int>(count) { { ... }, ... };
+ // }
+ // if (!_dictField.TryGetValue(switchValue, out switchIndex)) {
+ // switchIndex = -1;
+ // }
+ // }
+ // switch (switchIndex) {
+ // case 0: ...
+ // case 1: ...
+ // ...
+ // default:
+ // }
+ //
+ var switchValue = Expression.Variable(typeof(string), "switchValue");
+ var switchIndex = Expression.Variable(typeof(int), "switchIndex");
+ var reduced = Expression.Block(
+ new[] { switchIndex, switchValue },
+ Expression.Assign(switchValue, node.SwitchValue),
+ Expression.IfThenElse(
+ Expression.Equal(switchValue, Expression.Constant(null, typeof(string))),
+ Expression.Assign(switchIndex, Expression.Constant(nullCase)),
+ Expression.IfThenElse(
+ Expression.Call(dictInit, "TryGetValue", null, switchValue, switchIndex),
+ Expression.Empty(),
+ Expression.Assign(switchIndex, Expression.Constant(-1))
+ )
+ ),
+ Expression.Switch(node.Type, switchIndex, node.DefaultBody, null, cases)
+ );
+
+ EmitExpression(reduced, flags);
+ return true;
+ }
+
+ #endregion
+
+ private void CheckRethrow() {
+ // Rethrow is only valid inside a catch.
+ for (LabelScopeInfo j = _labelBlock; j != null; j = j.Parent) {
+ if (j.Kind == LabelScopeKind.Catch) {
+ return;
+ } else if (j.Kind == LabelScopeKind.Finally) {
+ // Rethrow from inside finally is not verifiable
+ break;
+ }
+ }
+ throw Error.RethrowRequiresCatch();
+ }
+
+ #region TryStatement
+
+ private void CheckTry() {
+ // Try inside a filter is not verifiable
+ for (LabelScopeInfo j = _labelBlock; j != null; j = j.Parent) {
+ if (j.Kind == LabelScopeKind.Filter) {
+ throw Error.TryNotAllowedInFilter();
+ }
+ }
+ }
+
+ private void EmitSaveExceptionOrPop(CatchBlock cb) {
+ if (cb.Variable != null) {
+ // If the variable is present, store the exception
+ // in the variable.
+ _scope.EmitSet(cb.Variable);
+ } else {
+ // Otherwise, pop it off the stack.
+ _ilg.Emit(OpCodes.Pop);
+ }
+ }
+
+ private void EmitTryExpression(Expression expr) {
+ var node = (TryExpression)expr;
+
+ CheckTry();
+
+ //******************************************************************
+ // 1. ENTERING TRY
+ //******************************************************************
+
+ PushLabelBlock(LabelScopeKind.Try);
+ _ilg.BeginExceptionBlock();
+
+ //******************************************************************
+ // 2. Emit the try statement body
+ //******************************************************************
+
+ EmitExpression(node.Body);
+
+ Type tryType = expr.Type;
+ LocalBuilder value = null;
+ if (tryType != typeof(void)) {
+ //store the value of the try body
+ value = GetLocal(tryType);
+ _ilg.Emit(OpCodes.Stloc, value);
+ }
+ //******************************************************************
+ // 3. Emit the catch blocks
+ //******************************************************************
+
+ foreach (CatchBlock cb in node.Handlers) {
+ PushLabelBlock(LabelScopeKind.Catch);
+
+ // Begin the strongly typed exception block
+ if (cb.Filter == null) {
+ _ilg.BeginCatchBlock(cb.Test);
+ } else {
+ _ilg.BeginExceptFilterBlock();
+ }
+
+ EnterScope(cb);
+
+ EmitCatchStart(cb);
+
+ //
+ // Emit the catch block body
+ //
+ EmitExpression(cb.Body);
+ if (tryType != typeof(void)) {
+ //store the value of the catch block body
+ _ilg.Emit(OpCodes.Stloc, value);
+ }
+
+ ExitScope(cb);
+
+ PopLabelBlock(LabelScopeKind.Catch);
+ }
+
+ //******************************************************************
+ // 4. Emit the finally block
+ //******************************************************************
+
+ if (node.Finally != null || node.Fault != null) {
+ PushLabelBlock(LabelScopeKind.Finally);
+
+ if (node.Finally != null) {
+ _ilg.BeginFinallyBlock();
+ } else {
+ _ilg.BeginFaultBlock();
+ }
+
+ // Emit the body
+ EmitExpressionAsVoid(node.Finally ?? node.Fault);
+
+ _ilg.EndExceptionBlock();
+ PopLabelBlock(LabelScopeKind.Finally);
+ } else {
+ _ilg.EndExceptionBlock();
+ }
+
+ if (tryType != typeof(void)) {
+ _ilg.Emit(OpCodes.Ldloc, value);
+ FreeLocal(value);
+ }
+ PopLabelBlock(LabelScopeKind.Try);
+ }
+
+ /// <summary>
+ /// Emits the start of a catch block. The exception value that is provided by the
+ /// CLR is stored in the variable specified by the catch block or popped if no
+ /// variable is provided.
+ /// </summary>
+ private void EmitCatchStart(CatchBlock cb) {
+ if (cb.Filter == null) {
+ EmitSaveExceptionOrPop(cb);
+ return;
+ }
+
+ // emit filter block. Filter blocks are untyped so we need to do
+ // the type check ourselves.
+ Label endFilter = _ilg.DefineLabel();
+ Label rightType = _ilg.DefineLabel();
+
+ // skip if it's not our exception type, but save
+ // the exception if it is so it's available to the
+ // filter
+ _ilg.Emit(OpCodes.Isinst, cb.Test);
+ _ilg.Emit(OpCodes.Dup);
+ _ilg.Emit(OpCodes.Brtrue, rightType);
+ _ilg.Emit(OpCodes.Pop);
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Br, endFilter);
+
+ // it's our type, save it and emit the filter.
+ _ilg.MarkLabel(rightType);
+ EmitSaveExceptionOrPop(cb);
+ PushLabelBlock(LabelScopeKind.Filter);
+ EmitExpression(cb.Filter);
+ PopLabelBlock(LabelScopeKind.Filter);
+
+ // begin the catch, clear the exception, we've
+ // already saved it
+ _ilg.MarkLabel(endFilter);
+ _ilg.BeginCatchBlock(null);
+ _ilg.Emit(OpCodes.Pop);
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Unary.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Unary.cs
new file mode 100644
index 00000000000..d63a1f14561
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Unary.cs
@@ -0,0 +1,354 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ partial class LambdaCompiler {
+
+ private void EmitQuoteUnaryExpression(Expression expr) {
+ EmitQuote((UnaryExpression)expr);
+ }
+
+
+ private void EmitQuote(UnaryExpression quote) {
+ // emit the quoted expression as a runtime constant
+ EmitConstant(quote.Operand, quote.Type);
+
+ // Heuristic: only emit the tree rewrite logic if we have hoisted
+ // locals.
+ if (_scope.NearestHoistedLocals != null) {
+ // HoistedLocals is internal so emit as System.Object
+ EmitConstant(_scope.NearestHoistedLocals, typeof(object));
+ _scope.EmitGet(_scope.NearestHoistedLocals.SelfVariable);
+ _ilg.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("Quote"));
+
+ if (quote.Type != typeof(Expression)) {
+ _ilg.Emit(OpCodes.Castclass, quote.Type);
+ }
+ }
+ }
+
+ private void EmitThrowUnaryExpression(Expression expr) {
+ EmitThrow((UnaryExpression)expr, CompilationFlags.EmitAsDefaultType);
+ }
+
+ private void EmitThrow(UnaryExpression expr, CompilationFlags flags) {
+ if (expr.Operand == null) {
+ CheckRethrow();
+
+ _ilg.Emit(OpCodes.Rethrow);
+ } else {
+ EmitExpression(expr.Operand);
+ _ilg.Emit(OpCodes.Throw);
+ }
+
+ EmitUnreachable(expr, flags);
+ }
+
+ private void EmitUnaryExpression(Expression expr, CompilationFlags flags) {
+ EmitUnary((UnaryExpression)expr, flags);
+ }
+
+ private void EmitUnary(UnaryExpression node, CompilationFlags flags) {
+ if (node.Method != null) {
+ EmitUnaryMethod(node, flags);
+ } else if (node.NodeType == ExpressionType.NegateChecked && TypeUtils.IsInteger(node.Operand.Type)) {
+ EmitExpression(node.Operand);
+ LocalBuilder loc = GetLocal(node.Operand.Type);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.EmitInt(0);
+ _ilg.EmitConvertToType(typeof(int), node.Operand.Type, false);
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ FreeLocal(loc);
+ EmitBinaryOperator(ExpressionType.SubtractChecked, node.Operand.Type, node.Operand.Type, node.Type, false);
+ } else {
+ EmitExpression(node.Operand);
+ EmitUnaryOperator(node.NodeType, node.Operand.Type, node.Type);
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private void EmitUnaryOperator(ExpressionType op, Type operandType, Type resultType) {
+ bool operandIsNullable = TypeUtils.IsNullableType(operandType);
+
+ if (op == ExpressionType.ArrayLength) {
+ _ilg.Emit(OpCodes.Ldlen);
+ return;
+ }
+
+ if (operandIsNullable) {
+ switch (op) {
+ case ExpressionType.Not: {
+ if (operandType != typeof(bool?))
+ goto case ExpressionType.Negate;
+
+ Label labIfNull = _ilg.DefineLabel();
+ Label labEnd = _ilg.DefineLabel();
+ LocalBuilder loc = GetLocal(operandType);
+
+ // store values (reverse order since they are already on the stack)
+ _ilg.Emit(OpCodes.Stloc, loc);
+
+ // test for null
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitHasValue(operandType);
+ _ilg.Emit(OpCodes.Brfalse_S, labEnd);
+
+ // do op on non-null value
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitGetValueOrDefault(operandType);
+ Type nnOperandType = TypeUtils.GetNonNullableType(operandType);
+ EmitUnaryOperator(op, nnOperandType, typeof(bool));
+
+ // construct result
+ ConstructorInfo ci = resultType.GetConstructor(new Type[] { typeof(bool) });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, loc);
+
+ _ilg.MarkLabel(labEnd);
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ FreeLocal(loc);
+ return;
+ }
+ case ExpressionType.UnaryPlus:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.Negate:
+ case ExpressionType.Increment:
+ case ExpressionType.Decrement:
+ case ExpressionType.OnesComplement:
+ case ExpressionType.IsFalse:
+ case ExpressionType.IsTrue: {
+ Debug.Assert(TypeUtils.AreEquivalent(operandType, resultType));
+ Label labIfNull = _ilg.DefineLabel();
+ Label labEnd = _ilg.DefineLabel();
+ LocalBuilder loc = GetLocal(operandType);
+
+ // check for null
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitHasValue(operandType);
+ _ilg.Emit(OpCodes.Brfalse_S, labIfNull);
+
+ // apply operator to non-null value
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.EmitGetValueOrDefault(operandType);
+ Type nnOperandType = TypeUtils.GetNonNullableType(resultType);
+ EmitUnaryOperator(op, nnOperandType, nnOperandType);
+
+ // construct result
+ ConstructorInfo ci = resultType.GetConstructor(new Type[] { nnOperandType });
+ _ilg.Emit(OpCodes.Newobj, ci);
+ _ilg.Emit(OpCodes.Stloc, loc);
+ _ilg.Emit(OpCodes.Br_S, labEnd);
+
+ // if null then create a default one
+ _ilg.MarkLabel(labIfNull);
+ _ilg.Emit(OpCodes.Ldloca, loc);
+ _ilg.Emit(OpCodes.Initobj, resultType);
+
+ _ilg.MarkLabel(labEnd);
+ _ilg.Emit(OpCodes.Ldloc, loc);
+ FreeLocal(loc);
+ return;
+ }
+ case ExpressionType.TypeAs:
+ _ilg.Emit(OpCodes.Box, operandType);
+ _ilg.Emit(OpCodes.Isinst, resultType);
+ if (TypeUtils.IsNullableType(resultType)) {
+ _ilg.Emit(OpCodes.Unbox_Any, resultType);
+ }
+ return;
+ default:
+ throw Error.UnhandledUnary(op);
+ }
+ } else {
+ switch (op) {
+ case ExpressionType.Not:
+ if (operandType == typeof(bool)) {
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ } else {
+ _ilg.Emit(OpCodes.Not);
+ }
+ break;
+ case ExpressionType.OnesComplement:
+ _ilg.Emit(OpCodes.Not);
+ break;
+ case ExpressionType.IsFalse:
+ _ilg.Emit(OpCodes.Ldc_I4_0);
+ _ilg.Emit(OpCodes.Ceq);
+ // Not an arithmetic operation -> no conversion
+ return;
+ case ExpressionType.IsTrue:
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ _ilg.Emit(OpCodes.Ceq);
+ // Not an arithmetic operation -> no conversion
+ return;
+ case ExpressionType.UnaryPlus:
+ _ilg.Emit(OpCodes.Nop);
+ break;
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ _ilg.Emit(OpCodes.Neg);
+ break;
+ case ExpressionType.TypeAs:
+ if (operandType.IsValueType) {
+ _ilg.Emit(OpCodes.Box, operandType);
+ }
+ _ilg.Emit(OpCodes.Isinst, resultType);
+ if (TypeUtils.IsNullableType(resultType)) {
+ _ilg.Emit(OpCodes.Unbox_Any, resultType);
+ }
+ // Not an arithmetic operation -> no conversion
+ return;
+ case ExpressionType.Increment:
+ EmitConstantOne(resultType);
+ _ilg.Emit(OpCodes.Add);
+ break;
+ case ExpressionType.Decrement:
+ EmitConstantOne(resultType);
+ _ilg.Emit(OpCodes.Sub);
+ break;
+ default:
+ throw Error.UnhandledUnary(op);
+ }
+
+ EmitConvertArithmeticResult(op, resultType);
+ }
+ }
+
+ private void EmitConstantOne(Type type) {
+ switch (Type.GetTypeCode(type)) {
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ _ilg.Emit(OpCodes.Ldc_I4_1);
+ break;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ _ilg.Emit(OpCodes.Ldc_I8, (long)1);
+ break;
+ case TypeCode.Single:
+ _ilg.Emit(OpCodes.Ldc_R4, 1.0f);
+ break;
+ case TypeCode.Double:
+ _ilg.Emit(OpCodes.Ldc_R8, 1.0d);
+ break;
+ default:
+ // we only have to worry about aritmetic types, see
+ // TypeUtils.IsArithmetic
+ throw ContractUtils.Unreachable;
+ }
+ }
+
+ private void EmitUnboxUnaryExpression(Expression expr) {
+ var node = (UnaryExpression)expr;
+ Debug.Assert(node.Type.IsValueType && !TypeUtils.IsNullableType(node.Type));
+
+ // Unbox_Any leaves the value on the stack
+ EmitExpression(node.Operand);
+ _ilg.Emit(OpCodes.Unbox_Any, node.Type);
+ }
+
+ private void EmitConvertUnaryExpression(Expression expr, CompilationFlags flags) {
+ EmitConvert((UnaryExpression)expr, flags);
+ }
+
+ private void EmitConvert(UnaryExpression node, CompilationFlags flags) {
+ if (node.Method != null) {
+ // User-defined conversions are only lifted if both source and
+ // destination types are value types. The C# compiler gets this wrong.
+ // In C#, if you have an implicit conversion from int->MyClass and you
+ // "lift" the conversion to int?->MyClass then a null int? goes to a
+ // null MyClass. This is contrary to the specification, which states
+ // that the correct behaviour is to unwrap the int?, throw an exception
+ // if it is null, and then call the conversion.
+ //
+ // We cannot fix this in C# but there is no reason why we need to
+ // propagate this bug into the expression tree API. Unfortunately
+ // this means that when the C# compiler generates the lambda
+ // (int? i)=>(MyClass)i, we will get different results for converting
+ // that lambda to a delegate directly and converting that lambda to
+ // an expression tree and then compiling it. We can live with this
+ // discrepancy however.
+
+ if (node.IsLifted && (!node.Type.IsValueType || !node.Operand.Type.IsValueType)) {
+ ParameterInfo[] pis = node.Method.GetParametersCached();
+ Debug.Assert(pis != null && pis.Length == 1);
+ Type paramType = pis[0].ParameterType;
+ if (paramType.IsByRef) {
+ paramType = paramType.GetElementType();
+ }
+
+ UnaryExpression e = Expression.Convert(
+ Expression.Call(
+ node.Method,
+ Expression.Convert(node.Operand, pis[0].ParameterType)
+ ),
+ node.Type
+ );
+
+ EmitConvert(e, flags);
+ } else {
+ EmitUnaryMethod(node, flags);
+ }
+ } else if (node.Type == typeof(void)) {
+ EmitExpressionAsVoid(node.Operand, flags);
+ } else {
+ if (TypeUtils.AreEquivalent(node.Operand.Type, node.Type)) {
+ EmitExpression(node.Operand, flags);
+ } else {
+ // A conversion is emitted after emitting the operand, no tail call is emitted
+ EmitExpression(node.Operand);
+ _ilg.EmitConvertToType(node.Operand.Type, node.Type, node.NodeType == ExpressionType.ConvertChecked);
+ }
+ }
+ }
+
+
+ private void EmitUnaryMethod(UnaryExpression node, CompilationFlags flags) {
+ if (node.IsLifted) {
+ ParameterExpression v = Expression.Variable(TypeUtils.GetNonNullableType(node.Operand.Type), null);
+ MethodCallExpression mc = Expression.Call(node.Method, v);
+
+ Type resultType = TypeUtils.GetNullableType(mc.Type);
+ EmitLift(node.NodeType, resultType, mc, new ParameterExpression[] { v }, new Expression[] { node.Operand });
+ _ilg.EmitConvertToType(resultType, node.Type, false);
+ } else {
+ EmitMethodCallExpression(Expression.Call(node.Method, node.Operand), flags);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.cs
new file mode 100644
index 00000000000..4139dec8beb
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.cs
@@ -0,0 +1,323 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#else
+using ILGenerator = Microsoft.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#endif
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Threading;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ /// <summary>
+ /// LambdaCompiler is responsible for compiling individual lambda (LambdaExpression). The complete tree may
+ /// contain multiple lambdas, the Compiler class is reponsible for compiling the whole tree, individual
+ /// lambdas are then compiled by the LambdaCompiler.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ internal sealed partial class LambdaCompiler {
+
+ private delegate void WriteBack();
+
+ // Information on the entire lambda tree currently being compiled
+ private readonly AnalyzedTree _tree;
+
+ private readonly ILGenerator _ilg;
+
+ // The TypeBuilder backing this method, if any
+ private readonly TypeBuilder _typeBuilder;
+
+ private readonly MethodInfo _method;
+
+ // Currently active LabelTargets and their mapping to IL labels
+ private LabelScopeInfo _labelBlock = new LabelScopeInfo(null, LabelScopeKind.Lambda);
+ // Mapping of labels used for "long" jumps (jumping out and into blocks)
+ private readonly Dictionary<LabelTarget, LabelInfo> _labelInfo = new Dictionary<LabelTarget, LabelInfo>();
+
+ // The currently active variable scope
+ private CompilerScope _scope;
+
+ // The lambda we are compiling
+ private readonly LambdaExpression _lambda;
+
+ // True if the method's first argument is of type Closure
+ private readonly bool _hasClosureArgument;
+
+ // True if we want to emitting debug symbols
+ private bool EmitDebugSymbols { get { return _tree.DebugInfoGenerator != null; } }
+
+ // Runtime constants bound to the delegate
+ private readonly BoundConstants _boundConstants;
+
+ // Free list of locals, so we reuse them rather than creating new ones
+ private readonly KeyedQueue<Type, LocalBuilder> _freeLocals = new KeyedQueue<Type, LocalBuilder>();
+
+ /// <summary>
+ /// The value is true if a clearance was emitted and no new sequence point
+ /// has been emitted since that.
+ /// </summary>
+ bool _sequencePointCleared;
+
+ /// <summary>
+ /// Creates a lambda compiler that will compile to a dynamic method
+ /// </summary>
+ private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda) {
+ Type[] parameterTypes = GetParameterTypes(lambda).AddFirst(typeof(Closure));
+
+#if SILVERLIGHT
+ var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes);
+#else
+ var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes, true);
+#endif
+
+ _tree = tree;
+ _lambda = lambda;
+ _method = method;
+
+ _ilg = new OffsetTrackingILGenerator(method.GetILGenerator());
+
+ _hasClosureArgument = true;
+
+ // These are populated by AnalyzeTree/VariableBinder
+ _scope = tree.Scopes[lambda];
+ _boundConstants = tree.Constants[lambda];
+
+ InitializeMethod();
+ }
+
+ /// <summary>
+ /// Creates a lambda compiler that will compile into the provided Methodbuilder
+ /// </summary>
+ private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method) {
+ _hasClosureArgument = tree.Scopes[lambda].NeedsClosure;
+ Type[] paramTypes = GetParameterTypes(lambda);
+ if (_hasClosureArgument) {
+ paramTypes = paramTypes.AddFirst(typeof(Closure));
+ }
+
+ method.SetReturnType(lambda.ReturnType);
+ method.SetParameters(paramTypes);
+ var paramNames = lambda.Parameters.Map(p => p.Name);
+ // parameters are index from 1, with closure argument we need to skip the first arg
+ int startIndex = _hasClosureArgument ? 2 : 1;
+ for (int i = 0; i < paramNames.Length; i++) {
+ method.DefineParameter(i + startIndex, ParameterAttributes.None, paramNames[i]);
+ }
+
+ _tree = tree;
+ _lambda = lambda;
+ _typeBuilder = (TypeBuilder)method.DeclaringType;
+ _method = method;
+
+ _ilg = new OffsetTrackingILGenerator(method.GetILGenerator());
+
+ // These are populated by AnalyzeTree/VariableBinder
+ _scope = tree.Scopes[lambda];
+ _boundConstants = tree.Constants[lambda];
+
+ InitializeMethod();
+ }
+
+ /// <summary>
+ /// Creates a lambda compiler for an inlined lambda
+ /// </summary>
+ private LambdaCompiler(LambdaCompiler parent, LambdaExpression lambda) {
+ _tree = parent._tree;
+ _lambda = lambda;
+ _method = parent._method;
+ _ilg = parent._ilg;
+ _hasClosureArgument = parent._hasClosureArgument;
+ _typeBuilder = parent._typeBuilder;
+ _scope = _tree.Scopes[lambda];
+ _boundConstants = parent._boundConstants;
+ }
+
+ private void InitializeMethod() {
+ // See if we can find a return label, so we can emit better IL
+ AddReturnLabel(_lambda);
+ _boundConstants.EmitCacheConstants(this);
+ }
+
+ public override string ToString() {
+ return _method.ToString();
+ }
+
+ internal ILGenerator IL {
+ get { return _ilg; }
+ }
+
+ internal ReadOnlyCollection<ParameterExpression> Parameters {
+ get { return _lambda.Parameters; }
+ }
+
+ internal bool CanEmitBoundConstants {
+ get { return _method is DynamicMethod; }
+ }
+
+ #region Compiler entry points
+
+ /// <summary>
+ /// Compiler entry point
+ /// </summary>
+ /// <param name="lambda">LambdaExpression to compile.</param>
+ /// <param name="debugInfoGenerator">Debug info generator.</param>
+ /// <returns>The compiled delegate.</returns>
+ internal static Delegate Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator) {
+ // 1. Bind lambda
+ AnalyzedTree tree = AnalyzeLambda(ref lambda);
+
+ tree.DebugInfoGenerator = debugInfoGenerator;
+
+ // 2. Create lambda compiler
+ LambdaCompiler c = new LambdaCompiler(tree, lambda);
+
+ // 3. Emit
+ c.EmitLambdaBody();
+
+ // 4. Return the delegate.
+ return c.CreateDelegate();
+ }
+
+ /// <summary>
+ /// Mutates the MethodBuilder parameter, filling in IL, parameters,
+ /// and return type.
+ ///
+ /// (probably shouldn't be modifying parameters/return type...)
+ /// </summary>
+ internal static void Compile(LambdaExpression lambda, MethodBuilder method, DebugInfoGenerator debugInfoGenerator) {
+ // 1. Bind lambda
+ AnalyzedTree tree = AnalyzeLambda(ref lambda);
+
+ tree.DebugInfoGenerator = debugInfoGenerator;
+
+ // 2. Create lambda compiler
+ LambdaCompiler c = new LambdaCompiler(tree, lambda, method);
+
+ // 3. Emit
+ c.EmitLambdaBody();
+ }
+
+ #endregion
+
+ private static AnalyzedTree AnalyzeLambda(ref LambdaExpression lambda) {
+ // Spill the stack for any exception handling blocks or other
+ // constructs which require entering with an empty stack
+ lambda = StackSpiller.AnalyzeLambda(lambda);
+
+ // Bind any variable references in this lambda
+ return VariableBinder.Bind(lambda);
+ }
+
+ internal LocalBuilder GetLocal(Type type) {
+ Debug.Assert(type != null);
+
+ LocalBuilder local;
+ if (_freeLocals.TryDequeue(type, out local)) {
+ Debug.Assert(type == local.LocalType);
+ return local;
+ }
+
+ return _ilg.DeclareLocal(type);
+ }
+
+ internal void FreeLocal(LocalBuilder local) {
+ if (local != null) {
+ _freeLocals.Enqueue(local.LocalType, local);
+ }
+ }
+
+ internal LocalBuilder GetNamedLocal(Type type, ParameterExpression variable) {
+ Debug.Assert(type != null && variable != null);
+
+ LocalBuilder lb = _ilg.DeclareLocal(type);
+ if (EmitDebugSymbols && variable.Name != null) {
+ _tree.DebugInfoGenerator.SetLocalName(lb, variable.Name);
+ }
+ return lb;
+ }
+
+ /// <summary>
+ /// Gets the argument slot corresponding to the parameter at the given
+ /// index. Assumes that the method takes a certain number of prefix
+ /// arguments, followed by the real parameters stored in Parameters
+ /// </summary>
+ internal int GetLambdaArgument(int index) {
+ return index + (_hasClosureArgument ? 1 : 0) + (_method.IsStatic ? 0 : 1);
+ }
+
+ /// <summary>
+ /// Returns the index-th argument. This method provides access to the actual arguments
+ /// defined on the lambda itself, and excludes the possible 0-th closure argument.
+ /// </summary>
+ internal void EmitLambdaArgument(int index) {
+ _ilg.EmitLoadArg(GetLambdaArgument(index));
+ }
+
+ internal void EmitClosureArgument() {
+ Debug.Assert(_hasClosureArgument, "must have a Closure argument");
+ Debug.Assert(_method.IsStatic, "must be a static method");
+ _ilg.EmitLoadArg(0);
+ }
+
+ private Delegate CreateDelegate() {
+ Debug.Assert(_method is DynamicMethod);
+
+ return _method.CreateDelegate(_lambda.Type, new Closure(_boundConstants.ToArray(), null));
+ }
+
+ private FieldBuilder CreateStaticField(string name, Type type) {
+ // We are emitting into someone else's type. We don't want name
+ // conflicts, so choose a long name that is unlikely to confict.
+ // Naming scheme chosen here is similar to what the C# compiler
+ // uses.
+ return _typeBuilder.DefineField("<ExpressionCompilerImplementationDetails>{" + Interlocked.Increment(ref _Counter) + "}" + name, type, FieldAttributes.Static | FieldAttributes.Private);
+ }
+
+ /// <summary>
+ /// Creates an unitialized field suitible for private implementation details
+ /// Works with DynamicMethods or TypeBuilders.
+ /// </summary>
+ private MemberExpression CreateLazyInitializedField<T>(string name) {
+ if (_method is DynamicMethod) {
+ return Expression.Field(Expression.Constant(new StrongBox<T>()), "Value");
+ } else {
+ return Expression.Field(null, CreateStaticField(name, typeof(T)));
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/OffsetTrackingILGenerator.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/OffsetTrackingILGenerator.cs
new file mode 100644
index 00000000000..f3f251977a9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/OffsetTrackingILGenerator.cs
@@ -0,0 +1,363 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics.SymbolStore;
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ /// <summary>
+ /// Wraps ILGenerator with code that tracks the current IL offset as instructions are emitted into the IL stream.
+ /// We can conditionally compile this for non-Dev10 release only (using #ifdef MICROSOFT_SCRIPTING)
+ /// as soon as Dev10 feature request (http://vstfdevdiv:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=599427) gets implemented.
+ /// </summary>
+ internal sealed class OffsetTrackingILGenerator {
+ private readonly ILGenerator _ilg;
+ internal int _offset;
+
+ internal int CurrentOffset { get { return _offset; } }
+
+ internal OffsetTrackingILGenerator(ILGenerator ilg) {
+ Debug.Assert(ilg != null);
+ _ilg = ilg;
+ }
+
+ private void AdvanceOffset(OpCode opcode) {
+ _offset += opcode.Size;
+ }
+
+ private void AdvanceOffsetWithLabel(OpCode opcode) {
+ AdvanceOffset(opcode);
+ if (OpCodes.TakesSingleByteArgument(opcode)) {
+ _offset++;
+ } else {
+ _offset += 4;
+ }
+ }
+
+ #region Simple Instructions
+
+ internal void Emit(OpCode opcode) {
+ _ilg.Emit(opcode);
+ AdvanceOffset(opcode);
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, byte arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset++;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, sbyte arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset++;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, int arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, MethodInfo meth) {
+ _ilg.Emit(opcode, meth);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) {
+ _ilg.EmitCall(opcode, methodInfo, optionalParameterTypes);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, ConstructorInfo con) {
+ _ilg.Emit(opcode, con);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, Type cls) {
+ _ilg.Emit(opcode, cls);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, long arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 8;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, float arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, double arg) {
+ _ilg.Emit(opcode, arg);
+ AdvanceOffset(opcode);
+ _offset += 8;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, Label label) {
+ _ilg.Emit(opcode, label);
+ AdvanceOffsetWithLabel(opcode);
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, Label[] labels) {
+ _ilg.Emit(opcode, labels);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ for (int remaining = labels.Length * 4, i = 0; remaining > 0; remaining -= 4, i++) {
+ _offset += 4;
+ }
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, FieldInfo field) {
+ _ilg.Emit(opcode, field);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, String str) {
+ _ilg.Emit(opcode, str);
+ AdvanceOffset(opcode);
+ _offset += 4;
+ AssertOffsetMatches();
+ }
+
+ internal void Emit(OpCode opcode, LocalBuilder local) {
+ _ilg.Emit(opcode, local);
+ int tempVal = local.LocalIndex;
+ if (opcode.Equals(OpCodes.Ldloc)) {
+ switch (tempVal) {
+ case 0:
+ opcode = OpCodes.Ldloc_0;
+ break;
+ case 1:
+ opcode = OpCodes.Ldloc_1;
+ break;
+ case 2:
+ opcode = OpCodes.Ldloc_2;
+ break;
+ case 3:
+ opcode = OpCodes.Ldloc_3;
+ break;
+ default:
+ if (tempVal <= 255)
+ opcode = OpCodes.Ldloc_S;
+ break;
+ }
+ } else if (opcode.Equals(OpCodes.Stloc)) {
+ switch (tempVal) {
+ case 0:
+ opcode = OpCodes.Stloc_0;
+ break;
+ case 1:
+ opcode = OpCodes.Stloc_1;
+ break;
+ case 2:
+ opcode = OpCodes.Stloc_2;
+ break;
+ case 3:
+ opcode = OpCodes.Stloc_3;
+ break;
+ default:
+ if (tempVal <= 255)
+ opcode = OpCodes.Stloc_S;
+ break;
+ }
+ } else if (opcode.Equals(OpCodes.Ldloca)) {
+ if (tempVal <= 255)
+ opcode = OpCodes.Ldloca_S;
+ }
+
+ AdvanceOffset(opcode);
+
+ if (opcode.OperandType == OperandType.InlineNone)
+ return;
+ else if (!OpCodes.TakesSingleByteArgument(opcode)) {
+ _offset += 2;
+ } else {
+ _offset++;
+ }
+ AssertOffsetMatches();
+ }
+
+ #endregion
+
+ #region Exception Handling
+
+ private enum ExceptionState {
+ Try = 0,
+ Filter = 1,
+ Catch = 2,
+ Finally = 3,
+ Fault = 4,
+ }
+
+ private Stack<ExceptionState> _exceptionState = new Stack<ExceptionState>();
+
+ internal void BeginExceptionBlock() {
+ _ilg.BeginExceptionBlock();
+ _exceptionState.Push(ExceptionState.Try);
+ AssertOffsetMatches();
+ }
+
+ internal void EndExceptionBlock() {
+ _ilg.EndExceptionBlock();
+
+ ExceptionState state = _exceptionState.Pop();
+ if (state == ExceptionState.Catch) {
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ } else if (state == ExceptionState.Finally || state == ExceptionState.Fault) {
+ AdvanceOffset(OpCodes.Endfinally);
+ }
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginExceptFilterBlock() {
+ _ilg.BeginExceptFilterBlock();
+
+ _exceptionState.Pop();
+ _exceptionState.Push(ExceptionState.Filter);
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginCatchBlock(Type exceptionType) {
+ _ilg.BeginCatchBlock(exceptionType);
+
+ ExceptionState state = _exceptionState.Pop();
+ if (state == ExceptionState.Filter) {
+ AdvanceOffset(OpCodes.Endfilter);
+ } else {
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ }
+
+ _exceptionState.Push(ExceptionState.Catch);
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginFaultBlock() {
+ _ilg.BeginFaultBlock();
+
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ _exceptionState.Pop();
+ _exceptionState.Push(ExceptionState.Fault);
+
+ AssertOffsetMatches();
+ }
+
+ internal void BeginFinallyBlock() {
+ _ilg.BeginFinallyBlock();
+
+ ExceptionState state = _exceptionState.Pop();
+ if (state != ExceptionState.Try) {
+ // leave for any preceeding catch clause
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ }
+
+ // leave for try clause
+ AdvanceOffsetWithLabel(OpCodes.Leave);
+ _exceptionState.Push(ExceptionState.Finally);
+
+ AssertOffsetMatches();
+ }
+
+ #endregion
+
+ #region Labels and Locals
+
+ internal Label DefineLabel() {
+ return _ilg.DefineLabel();
+ }
+
+ internal void MarkLabel(Label loc) {
+ _ilg.MarkLabel(loc);
+ }
+
+ internal LocalBuilder DeclareLocal(Type localType) {
+ return _ilg.DeclareLocal(localType);
+ }
+
+ internal void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) {
+ _ilg.MarkSequencePoint(document, startLine, startColumn, endLine, endColumn);
+ }
+
+ #endregion
+
+ #region Assertions
+
+#if STRESS_DEBUG
+ private FieldInfo _ilgOffsetField;
+ private bool _checkOffset = true;
+#endif
+
+ [Conditional("STRESS_DEBUG")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ private void AssertOffsetMatches() {
+#if STRESS_DEBUG
+ if (!_checkOffset) {
+ return;
+ }
+
+ int m_length = -1;
+ try {
+ if (_ilgOffsetField == null) {
+ _ilgOffsetField = typeof(ILGenerator).GetField("m_length", BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+ m_length = (int)_ilgOffsetField.GetValue(_ilg);
+ } catch (Exception) {
+ _checkOffset = false;
+ }
+
+ if (_checkOffset) {
+ Debug.Assert(m_length == _offset);
+ }
+#endif
+ }
+
+ #endregion
+ }
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/RuntimeVariableList.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/RuntimeVariableList.cs
new file mode 100644
index 00000000000..bb28100a6b6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/RuntimeVariableList.cs
@@ -0,0 +1,128 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.ComponentModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+
+ /// <summary>
+ /// This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+ /// Contains helper methods called from dynamically generated methods.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never), DebuggerStepThrough]
+ public static partial class RuntimeOps {
+ /// <summary>
+ /// Creates an interface that can be used to modify closed over variables at runtime.
+ /// </summary>
+ /// <param name="data">The closure array.</param>
+ /// <param name="indexes">An array of indicies into the closure array where variables are found.</param>
+ /// <returns>An interface to access variables.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static IRuntimeVariables CreateRuntimeVariables(object[] data, long[] indexes) {
+ return new RuntimeVariableList(data, indexes);
+ }
+
+ /// <summary>
+ /// Creates an interface that can be used to modify closed over variables at runtime.
+ /// </summary>
+ /// <returns>An interface to access variables.</returns>
+ [Obsolete("do not use this method", true), EditorBrowsable(EditorBrowsableState.Never)]
+ public static IRuntimeVariables CreateRuntimeVariables() {
+ return new EmptyRuntimeVariables();
+ }
+
+ private sealed class EmptyRuntimeVariables : IRuntimeVariables {
+ int IRuntimeVariables.Count {
+ get { return 0; }
+ }
+
+ object IRuntimeVariables.this[int index] {
+ get {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ set {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provides a list of variables, supporing read/write of the values
+ /// Exposed via RuntimeVariablesExpression
+ /// </summary>
+ private sealed class RuntimeVariableList : IRuntimeVariables {
+ // The top level environment. It contains pointers to parent
+ // environments, which are always in the first element
+ private readonly object[] _data;
+
+ // An array of (int, int) pairs, each representing how to find a
+ // variable in the environment data struction.
+ //
+ // The first integer indicates the number of times to go up in the
+ // closure chain, the second integer indicates the index into that
+ // closure chain.
+ private readonly long[] _indexes;
+
+ internal RuntimeVariableList(object[] data, long[] indexes) {
+ Debug.Assert(data != null);
+ Debug.Assert(indexes != null);
+
+ _data = data;
+ _indexes = indexes;
+ }
+
+ public int Count {
+ get { return _indexes.Length; }
+ }
+
+ public object this[int index] {
+ get {
+ return GetStrongBox(index).Value;
+ }
+ set {
+ GetStrongBox(index).Value = value;
+ }
+ }
+
+ private IStrongBox GetStrongBox(int index) {
+ // We lookup the closure using two ints:
+ // 1. The high dword is the number of parents to go up
+ // 2. The low dword is the index into that array
+ long closureKey = _indexes[index];
+
+ // walk up the parent chain to find the real environment
+ object[] result = _data;
+ for (int parents = (int)(closureKey >> 32); parents > 0; parents--) {
+ result = HoistedLocals.GetParent(result);
+ }
+
+ // Return the variable storage
+ return (IStrongBox)result[(int)closureKey];
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Set.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Set.cs
new file mode 100644
index 00000000000..6af4d573c64
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/Set.cs
@@ -0,0 +1,97 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections;
+using System.Collections.Generic;
+
+#if CODEPLEX_40
+// Note: can't move to Utils because name conflicts with System.Linq.Set
+namespace System.Linq.Expressions {
+#else
+// Note: can't move to Utils because name conflicts with Microsoft.Linq.Set
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ /// <summary>
+ /// A simple hashset, built on Dictionary{K, V}
+ /// </summary>
+ internal sealed class Set<T> : ICollection<T> {
+ private readonly Dictionary<T, object> _data;
+
+ internal Set() {
+ _data = new Dictionary<T, object>();
+ }
+
+ internal Set(IEqualityComparer<T> comparer) {
+ _data = new Dictionary<T, object>(comparer);
+ }
+
+ internal Set(IList<T> list) {
+ _data = new Dictionary<T, object>(list.Count);
+ foreach (T t in list) {
+ Add(t);
+ }
+ }
+
+ internal Set(IEnumerable<T> list) {
+ _data = new Dictionary<T, object>();
+ foreach (T t in list) {
+ Add(t);
+ }
+ }
+
+ internal Set(int capacity) {
+ _data = new Dictionary<T, object>(capacity);
+ }
+
+ public void Add(T item) {
+ _data[item] = null;
+ }
+
+ public void Clear() {
+ _data.Clear();
+ }
+
+ public bool Contains(T item) {
+ return _data.ContainsKey(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex) {
+ _data.Keys.CopyTo(array, arrayIndex);
+ }
+
+ public int Count {
+ get { return _data.Count; }
+ }
+
+ public bool IsReadOnly {
+ get { return false; }
+ }
+
+ public bool Remove(T item) {
+ return _data.Remove(item);
+ }
+
+ public IEnumerator<T> GetEnumerator() {
+ return _data.Keys.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return _data.Keys.GetEnumerator();
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Bindings.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Bindings.cs
new file mode 100644
index 00000000000..e102b5a03ad
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Bindings.cs
@@ -0,0 +1,238 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ internal partial class StackSpiller {
+
+ private abstract class BindingRewriter {
+ protected MemberBinding _binding;
+ protected RewriteAction _action;
+ protected StackSpiller _spiller;
+
+ internal BindingRewriter(MemberBinding binding, StackSpiller spiller) {
+ _binding = binding;
+ _spiller = spiller;
+ }
+
+ internal RewriteAction Action {
+ get { return _action; }
+ }
+
+ internal abstract MemberBinding AsBinding();
+ internal abstract Expression AsExpression(Expression target);
+
+ internal static BindingRewriter Create(MemberBinding binding, StackSpiller spiller, Stack stack) {
+ switch (binding.BindingType) {
+ case MemberBindingType.Assignment:
+ MemberAssignment assign = (MemberAssignment)binding;
+ return new MemberAssignmentRewriter(assign, spiller, stack);
+ case MemberBindingType.ListBinding:
+ MemberListBinding list = (MemberListBinding)binding;
+ return new ListBindingRewriter(list, spiller, stack);
+ case MemberBindingType.MemberBinding:
+ MemberMemberBinding member = (MemberMemberBinding)binding;
+ return new MemberMemberBindingRewriter(member, spiller, stack);
+ }
+ throw Error.UnhandledBinding();
+ }
+ }
+
+ private class MemberMemberBindingRewriter : BindingRewriter {
+ ReadOnlyCollection<MemberBinding> _bindings;
+ BindingRewriter[] _bindingRewriters;
+
+ internal MemberMemberBindingRewriter(MemberMemberBinding binding, StackSpiller spiller, Stack stack) :
+ base(binding, spiller) {
+
+ _bindings = binding.Bindings;
+ _bindingRewriters = new BindingRewriter[_bindings.Count];
+ for (int i = 0; i < _bindings.Count; i++) {
+ BindingRewriter br = BindingRewriter.Create(_bindings[i], spiller, stack);
+ _action |= br.Action;
+ _bindingRewriters[i] = br;
+ }
+ }
+
+ internal override MemberBinding AsBinding() {
+ switch (_action) {
+ case RewriteAction.None:
+ return _binding;
+ case RewriteAction.Copy:
+ MemberBinding[] newBindings = new MemberBinding[_bindings.Count];
+ for (int i = 0; i < _bindings.Count; i++) {
+ newBindings[i] = _bindingRewriters[i].AsBinding();
+ }
+ return Expression.MemberBind(_binding.Member, new TrueReadOnlyCollection<MemberBinding>(newBindings));
+ }
+ throw ContractUtils.Unreachable;
+ }
+
+ internal override Expression AsExpression(Expression target) {
+ if (target.Type.IsValueType && _binding.Member is System.Reflection.PropertyInfo) {
+ throw Error.CannotAutoInitializeValueTypeMemberThroughProperty(_binding.Member);
+ }
+ RequireNotRefInstance(target);
+
+ MemberExpression member = Expression.MakeMemberAccess(target, _binding.Member);
+ ParameterExpression memberTemp = _spiller.MakeTemp(member.Type);
+
+ Expression[] block = new Expression[_bindings.Count + 2];
+ block[0] = Expression.Assign(memberTemp, member);
+
+ for (int i = 0; i < _bindings.Count; i++) {
+ BindingRewriter br = _bindingRewriters[i];
+ block[i + 1] = br.AsExpression(memberTemp);
+ }
+
+ // We need to copy back value types
+ if (memberTemp.Type.IsValueType) {
+ block[_bindings.Count + 1] = Expression.Block(
+ typeof(void),
+ Expression.Assign(Expression.MakeMemberAccess(target, _binding.Member), memberTemp)
+ );
+ } else {
+ block[_bindings.Count + 1] = Expression.Empty();
+ }
+ return MakeBlock(block);
+ }
+ }
+
+ private class ListBindingRewriter : BindingRewriter {
+ ReadOnlyCollection<ElementInit> _inits;
+ ChildRewriter[] _childRewriters;
+
+ internal ListBindingRewriter(MemberListBinding binding, StackSpiller spiller, Stack stack) :
+ base(binding, spiller) {
+
+ _inits = binding.Initializers;
+
+ _childRewriters = new ChildRewriter[_inits.Count];
+ for (int i = 0; i < _inits.Count; i++) {
+ ElementInit init = _inits[i];
+
+ ChildRewriter cr = new ChildRewriter(spiller, stack, init.Arguments.Count);
+ cr.Add(init.Arguments);
+
+ _action |= cr.Action;
+ _childRewriters[i] = cr;
+ }
+ }
+
+ internal override MemberBinding AsBinding() {
+ switch (_action) {
+ case RewriteAction.None:
+ return _binding;
+ case RewriteAction.Copy:
+ ElementInit[] newInits = new ElementInit[_inits.Count];
+ for (int i = 0; i < _inits.Count; i++) {
+ ChildRewriter cr = _childRewriters[i];
+ if (cr.Action == RewriteAction.None) {
+ newInits[i] = _inits[i];
+ } else {
+ newInits[i] = Expression.ElementInit(_inits[i].AddMethod, cr[0, -1]);
+ }
+ }
+ return Expression.ListBind(_binding.Member, new TrueReadOnlyCollection<ElementInit>(newInits));
+ }
+ throw ContractUtils.Unreachable;
+ }
+
+ internal override Expression AsExpression(Expression target) {
+ if (target.Type.IsValueType && _binding.Member is System.Reflection.PropertyInfo) {
+ throw Error.CannotAutoInitializeValueTypeElementThroughProperty(_binding.Member);
+ }
+ RequireNotRefInstance(target);
+
+ MemberExpression member = Expression.MakeMemberAccess(target, _binding.Member);
+ ParameterExpression memberTemp = _spiller.MakeTemp(member.Type);
+
+ Expression[] block = new Expression[_inits.Count + 2];
+ block[0] = Expression.Assign(memberTemp, member);
+
+ for (int i = 0; i < _inits.Count; i++) {
+ ChildRewriter cr = _childRewriters[i];
+ Result add = cr.Finish(Expression.Call(memberTemp, _inits[i].AddMethod, cr[0, -1]));
+ block[i + 1] = add.Node;
+ }
+
+ // We need to copy back value types
+ if (memberTemp.Type.IsValueType) {
+ block[_inits.Count + 1] = Expression.Block(
+ typeof(void),
+ Expression.Assign(Expression.MakeMemberAccess(target, _binding.Member), memberTemp)
+ );
+ } else {
+ block[_inits.Count + 1] = Expression.Empty();
+ }
+ return MakeBlock(block);
+ }
+ }
+
+ private class MemberAssignmentRewriter : BindingRewriter {
+ Expression _rhs;
+
+ internal MemberAssignmentRewriter(MemberAssignment binding, StackSpiller spiller, Stack stack) :
+ base(binding, spiller) {
+
+ Result result = spiller.RewriteExpression(binding.Expression, stack);
+ _action = result.Action;
+ _rhs = result.Node;
+ }
+
+ internal override MemberBinding AsBinding() {
+ switch (_action) {
+ case RewriteAction.None:
+ return _binding;
+ case RewriteAction.Copy:
+ return Expression.Bind(_binding.Member, _rhs);
+ }
+ throw ContractUtils.Unreachable;
+ }
+
+ internal override Expression AsExpression(Expression target) {
+ RequireNotRefInstance(target);
+
+ MemberExpression member = Expression.MakeMemberAccess(target, _binding.Member);
+ ParameterExpression memberTemp = _spiller.MakeTemp(member.Type);
+
+ return MakeBlock(
+ Expression.Assign(memberTemp, _rhs),
+ Expression.Assign(member, memberTemp),
+ Expression.Empty()
+ );
+ }
+ }
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Generated.cs
new file mode 100644
index 00000000000..4de2f4073e3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Generated.cs
@@ -0,0 +1,278 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ internal partial class StackSpiller {
+
+ /// <summary>
+ /// Rewrite the expression
+ /// </summary>
+ ///
+ /// <param name="node">Expression to rewrite</param>
+ /// <param name="stack">State of the stack before the expression is emitted.</param>
+ /// <returns>Rewritten expression.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private Result RewriteExpression(Expression node, Stack stack) {
+ if (node == null) {
+ return new Result(RewriteAction.None, null);
+ }
+
+ Result result;
+ switch (node.NodeType) {
+ #region Generated StackSpiller Switch
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_stackspiller_switch from: generate_tree.py
+
+ case ExpressionType.Add:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.AddChecked:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.And:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.AndAlso:
+ result = RewriteLogicalBinaryExpression(node, stack);
+ break;
+ case ExpressionType.ArrayLength:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.ArrayIndex:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Call:
+ result = RewriteMethodCallExpression(node, stack);
+ break;
+ case ExpressionType.Coalesce:
+ result = RewriteLogicalBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Conditional:
+ result = RewriteConditionalExpression(node, stack);
+ break;
+ case ExpressionType.Convert:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.ConvertChecked:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.Divide:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Equal:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.ExclusiveOr:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.GreaterThan:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.GreaterThanOrEqual:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Invoke:
+ result = RewriteInvocationExpression(node, stack);
+ break;
+ case ExpressionType.Lambda:
+ result = RewriteLambdaExpression(node, stack);
+ break;
+ case ExpressionType.LeftShift:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.LessThan:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.LessThanOrEqual:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.ListInit:
+ result = RewriteListInitExpression(node, stack);
+ break;
+ case ExpressionType.MemberAccess:
+ result = RewriteMemberExpression(node, stack);
+ break;
+ case ExpressionType.MemberInit:
+ result = RewriteMemberInitExpression(node, stack);
+ break;
+ case ExpressionType.Modulo:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Multiply:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.MultiplyChecked:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Negate:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.UnaryPlus:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.NegateChecked:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.New:
+ result = RewriteNewExpression(node, stack);
+ break;
+ case ExpressionType.NewArrayInit:
+ result = RewriteNewArrayExpression(node, stack);
+ break;
+ case ExpressionType.NewArrayBounds:
+ result = RewriteNewArrayExpression(node, stack);
+ break;
+ case ExpressionType.Not:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.NotEqual:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Or:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.OrElse:
+ result = RewriteLogicalBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Power:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.RightShift:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Subtract:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.SubtractChecked:
+ result = RewriteBinaryExpression(node, stack);
+ break;
+ case ExpressionType.TypeAs:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.TypeIs:
+ result = RewriteTypeBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Assign:
+ result = RewriteAssignBinaryExpression(node, stack);
+ break;
+ case ExpressionType.Block:
+ result = RewriteBlockExpression(node, stack);
+ break;
+ case ExpressionType.Decrement:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.Dynamic:
+ result = RewriteDynamicExpression(node, stack);
+ break;
+ case ExpressionType.Extension:
+ result = RewriteExtensionExpression(node, stack);
+ break;
+ case ExpressionType.Goto:
+ result = RewriteGotoExpression(node, stack);
+ break;
+ case ExpressionType.Increment:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.Index:
+ result = RewriteIndexExpression(node, stack);
+ break;
+ case ExpressionType.Label:
+ result = RewriteLabelExpression(node, stack);
+ break;
+ case ExpressionType.Loop:
+ result = RewriteLoopExpression(node, stack);
+ break;
+ case ExpressionType.Switch:
+ result = RewriteSwitchExpression(node, stack);
+ break;
+ case ExpressionType.Throw:
+ result = RewriteThrowUnaryExpression(node, stack);
+ break;
+ case ExpressionType.Try:
+ result = RewriteTryExpression(node, stack);
+ break;
+ case ExpressionType.Unbox:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.TypeEqual:
+ result = RewriteTypeBinaryExpression(node, stack);
+ break;
+ case ExpressionType.OnesComplement:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.IsTrue:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.IsFalse:
+ result = RewriteUnaryExpression(node, stack);
+ break;
+ case ExpressionType.AddAssign:
+ case ExpressionType.AndAssign:
+ case ExpressionType.DivideAssign:
+ case ExpressionType.ExclusiveOrAssign:
+ case ExpressionType.LeftShiftAssign:
+ case ExpressionType.ModuloAssign:
+ case ExpressionType.MultiplyAssign:
+ case ExpressionType.OrAssign:
+ case ExpressionType.PowerAssign:
+ case ExpressionType.RightShiftAssign:
+ case ExpressionType.SubtractAssign:
+ case ExpressionType.AddAssignChecked:
+ case ExpressionType.MultiplyAssignChecked:
+ case ExpressionType.SubtractAssignChecked:
+ case ExpressionType.PreIncrementAssign:
+ case ExpressionType.PreDecrementAssign:
+ case ExpressionType.PostIncrementAssign:
+ case ExpressionType.PostDecrementAssign:
+ result = RewriteReducibleExpression(node, stack);
+ break;
+ case ExpressionType.Quote:
+ case ExpressionType.Parameter:
+ case ExpressionType.Constant:
+ case ExpressionType.RuntimeVariables:
+ case ExpressionType.Default:
+ case ExpressionType.DebugInfo:
+ return new Result(RewriteAction.None, node);
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default:
+ throw ContractUtils.Unreachable;
+ }
+
+ VerifyRewrite(result, node);
+
+ return result;
+ }
+ }
+}
+
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Temps.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Temps.cs
new file mode 100644
index 00000000000..42a147ac047
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.Temps.cs
@@ -0,0 +1,313 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ internal partial class StackSpiller {
+
+ private class TempMaker {
+ /// <summary>
+ /// Current temporary variable
+ /// </summary>
+ private int _temp;
+
+ /// <summary>
+ /// List of free temporary variables. These can be recycled for new temps.
+ /// </summary>
+ private List<ParameterExpression> _freeTemps;
+
+ /// <summary>
+ /// Stack of currently active temporary variables.
+ /// </summary>
+ private Stack<ParameterExpression> _usedTemps;
+
+ /// <summary>
+ /// List of all temps created by stackspiller for this rule/lambda
+ /// </summary>
+ private List<ParameterExpression> _temps = new List<ParameterExpression>();
+
+ internal List<ParameterExpression> Temps {
+ get { return _temps; }
+ }
+
+ internal ParameterExpression Temp(Type type) {
+ ParameterExpression temp;
+ if (_freeTemps != null) {
+ // Recycle from the free-list if possible.
+ for (int i = _freeTemps.Count - 1; i >= 0; i--) {
+ temp = _freeTemps[i];
+ if (temp.Type == type) {
+ _freeTemps.RemoveAt(i);
+ return UseTemp(temp);
+ }
+ }
+ }
+ // Not on the free-list, create a brand new one.
+ temp = Expression.Variable(type, "$temp$" + _temp++);
+ _temps.Add(temp);
+ return UseTemp(temp);
+ }
+
+ private ParameterExpression UseTemp(ParameterExpression temp) {
+ Debug.Assert(_freeTemps == null || !_freeTemps.Contains(temp));
+ Debug.Assert(_usedTemps == null || !_usedTemps.Contains(temp));
+
+ if (_usedTemps == null) {
+ _usedTemps = new Stack<ParameterExpression>();
+ }
+ _usedTemps.Push(temp);
+ return temp;
+ }
+
+ private void FreeTemp(ParameterExpression temp) {
+ Debug.Assert(_freeTemps == null || !_freeTemps.Contains(temp));
+ if (_freeTemps == null) {
+ _freeTemps = new List<ParameterExpression>();
+ }
+ _freeTemps.Add(temp);
+ }
+
+ internal int Mark() {
+ return _usedTemps != null ? _usedTemps.Count : 0;
+ }
+
+ // Free temporaries created since the last marking.
+ // This is a performance optimization to lower the overall number of tempories needed.
+ internal void Free(int mark) {
+ // (_usedTemps != null) ==> (mark <= _usedTemps.Count)
+ Debug.Assert(_usedTemps == null || mark <= _usedTemps.Count);
+ // (_usedTemps == null) ==> (mark == 0)
+ Debug.Assert(mark == 0 || _usedTemps != null);
+
+ if (_usedTemps != null) {
+ while (mark < _usedTemps.Count) {
+ FreeTemp(_usedTemps.Pop());
+ }
+ }
+ }
+
+ [Conditional("DEBUG")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ internal void VerifyTemps() {
+ Debug.Assert(_usedTemps == null || _usedTemps.Count == 0);
+ }
+ }
+
+
+ /// <summary>
+ /// Rewrites child expressions, spilling them into temps if needed. The
+ /// stack starts in the inital state, and after the first subexpression
+ /// is added it is change to non-empty. This behavior can be overridden
+ /// by setting the stack manually between adds.
+ ///
+ /// When all children have been added, the caller should rewrite the
+ /// node if Rewrite is true. Then, it should call Finish with etiher
+ /// the orignal expression or the rewritten expression. Finish will call
+ /// Expression.Comma if necessary and return a new Result.
+ /// </summary>
+ private class ChildRewriter {
+ private readonly StackSpiller _self;
+ private readonly Expression[] _expressions;
+ private int _expressionsCount;
+ private List<Expression> _comma;
+ private RewriteAction _action;
+ private Stack _stack;
+ private bool _done;
+
+ internal ChildRewriter(StackSpiller self, Stack stack, int count) {
+ _self = self;
+ _stack = stack;
+ _expressions = new Expression[count];
+ }
+
+ internal void Add(Expression node) {
+ Debug.Assert(!_done);
+
+ if (node == null) {
+ _expressions[_expressionsCount++] = null;
+ return;
+ }
+
+ Result exp = _self.RewriteExpression(node, _stack);
+ _action |= exp.Action;
+ _stack = Stack.NonEmpty;
+
+ // track items in case we need to copy or spill stack
+ _expressions[_expressionsCount++] = exp.Node;
+ }
+
+ internal void Add(IList<Expression> expressions) {
+ for (int i = 0, count = expressions.Count; i < count; i++) {
+ Add(expressions[i]);
+ }
+ }
+
+ internal void AddArguments(IArgumentProvider expressions) {
+ for (int i = 0, count = expressions.ArgumentCount; i < count; i++) {
+ Add(expressions.GetArgument(i));
+ }
+ }
+
+ private void EnsureDone() {
+ // done adding arguments, build the comma if necessary
+ if (!_done) {
+ _done = true;
+
+ if (_action == RewriteAction.SpillStack) {
+ Expression[] clone = _expressions;
+ int count = clone.Length;
+ List<Expression> comma = new List<Expression>(count + 1);
+ for (int i = 0; i < count; i++) {
+ if (clone[i] != null) {
+ Expression temp;
+ clone[i] = _self.ToTemp(clone[i], out temp);
+ comma.Add(temp);
+ }
+ }
+ comma.Capacity = comma.Count + 1;
+ _comma = comma;
+ }
+ }
+ }
+
+ internal bool Rewrite {
+ get { return _action != RewriteAction.None; }
+ }
+
+ internal RewriteAction Action {
+ get { return _action; }
+ }
+
+ internal Result Finish(Expression expr) {
+ EnsureDone();
+
+ if (_action == RewriteAction.SpillStack) {
+ Debug.Assert(_comma.Capacity == _comma.Count + 1);
+ _comma.Add(expr);
+ expr = MakeBlock(_comma);
+ }
+
+ return new Result(_action, expr);
+ }
+
+ internal Expression this[int index] {
+ get {
+ EnsureDone();
+ if (index < 0) {
+ index += _expressions.Length;
+ }
+ return _expressions[index];
+ }
+ }
+
+ internal Expression[] this[int first, int last] {
+ get {
+ EnsureDone();
+ if (last < 0) {
+ last += _expressions.Length;
+ }
+ int count = last - first + 1;
+ ContractUtils.RequiresArrayRange(_expressions, first, count, "first", "last");
+
+ if (count == _expressions.Length) {
+ Debug.Assert(first == 0);
+ // if the entire array is requested just return it so we don't make a new array
+ return _expressions;
+ }
+
+ Expression[] clone = new Expression[count];
+ Array.Copy(_expressions, first, clone, 0, count);
+ return clone;
+ }
+ }
+ }
+
+
+ private ParameterExpression MakeTemp(Type type) {
+ return _tm.Temp(type);
+ }
+
+ private int Mark() {
+ return _tm.Mark();
+ }
+
+ private void Free(int mark) {
+ _tm.Free(mark);
+ }
+
+ [Conditional("DEBUG")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
+ private void VerifyTemps() {
+ _tm.VerifyTemps();
+ }
+
+ /// <summary>
+ /// Will perform:
+ /// save: temp = expression
+ /// return value: temp
+ /// </summary>
+ private ParameterExpression ToTemp(Expression expression, out Expression save) {
+ ParameterExpression temp = MakeTemp(expression.Type);
+ save = Expression.Assign(temp, expression);
+ return temp;
+ }
+
+ /// <summary>
+ /// Creates a special block that is marked as not allowing jumps in.
+ /// This should not be used for rewriting BlockExpression itself, or
+ /// anything else that supports jumping.
+ /// </summary>
+ private static Expression MakeBlock(params Expression[] expressions) {
+ return MakeBlock((IList<Expression>)expressions);
+ }
+
+ /// <summary>
+ /// Creates a special block that is marked as not allowing jumps in.
+ /// This should not be used for rewriting BlockExpression itself, or
+ /// anything else that supports jumping.
+ /// </summary>
+ private static Expression MakeBlock(IList<Expression> expressions) {
+ return new SpilledExpressionBlock(expressions);
+ }
+ }
+
+ /// <summary>
+ /// A special subtype of BlockExpression that indicates to the compiler
+ /// that this block is a spilled expression and should not allow jumps in.
+ /// </summary>
+ internal sealed class SpilledExpressionBlock : BlockN {
+ internal SpilledExpressionBlock(IList<Expression> expressions)
+ : base(expressions) {
+ }
+ internal override BlockExpression Rewrite(ReadOnlyCollection<ParameterExpression> variables, Expression[] args) {
+ throw ContractUtils.Unreachable;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.cs
new file mode 100644
index 00000000000..12298c86dd6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/StackSpiller.cs
@@ -0,0 +1,991 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+
+ /// <summary>
+ /// Expression rewriting to spill the CLR stack into temporary variables
+ /// in order to guarantee some properties of code generation, for
+ /// example that we always enter try block on empty stack.
+ /// </summary>
+ internal partial class StackSpiller {
+
+ // Is the evaluation stack empty?
+ private enum Stack {
+ Empty,
+ NonEmpty
+ };
+
+ // Should the parent nodes be rewritten, and in what way?
+ // Designed so bitwise-or produces the correct result when merging two
+ // subtrees. In particular, SpillStack is preferred over Copy which is
+ // preferred over None.
+ //
+ // Values:
+ // None -> no rewrite needed
+ // Copy -> copy into a new node
+ // SpillStack -> spill stack into temps
+ [Flags]
+ private enum RewriteAction {
+ None = 0,
+ Copy = 1,
+ SpillStack = 3,
+ }
+
+ // Result of a rewrite operation. Always contains an action and a node.
+ private struct Result {
+ internal readonly RewriteAction Action;
+ internal readonly Expression Node;
+
+ internal Result(RewriteAction action, Expression node) {
+ Action = action;
+ Node = node;
+ }
+ }
+
+ /// <summary>
+ /// The source of temporary variables
+ /// </summary>
+ private readonly TempMaker _tm = new TempMaker();
+
+ /// <summary>
+ /// Initial stack state. Normally empty, but when inlining the lambda
+ /// we might have a non-empty starting stack state.
+ /// </summary>
+ private readonly Stack _startingStack;
+
+ /// <summary>
+ /// Lambda rewrite result. We need this for inlined lambdas to figure
+ /// out whether we need to guarentee it an empty stack.
+ /// </summary>
+ private RewriteAction _lambdaRewrite;
+
+ /// <summary>
+ /// Analyzes a lambda, producing a new one that has correct invariants
+ /// for codegen. In particular, it spills the IL stack to temps in
+ /// places where it's invalid to have a non-empty stack (for example,
+ /// entering a try statement).
+ /// </summary>
+ internal static LambdaExpression AnalyzeLambda(LambdaExpression lambda) {
+ return lambda.Accept(new StackSpiller(Stack.Empty));
+ }
+
+ private StackSpiller(Stack stack) {
+ _startingStack = stack;
+ }
+
+ // called by Expression<T>.Accept
+ internal Expression<T> Rewrite<T>(Expression<T> lambda) {
+ VerifyTemps();
+
+ // Lambda starts with an empty stack
+ Result body = RewriteExpressionFreeTemps(lambda.Body, _startingStack);
+ _lambdaRewrite = body.Action;
+
+ VerifyTemps();
+
+ if (body.Action != RewriteAction.None) {
+ // Create a new scope for temps
+ // (none of these will be hoisted so there is no closure impact)
+ Expression newBody = body.Node;
+ if (_tm.Temps.Count > 0) {
+ newBody = Expression.Block(_tm.Temps, newBody);
+ }
+
+ // Clone the lambda, replacing the body & variables
+ return new Expression<T>(newBody, lambda.Name, lambda.TailCall, lambda.Parameters);
+ }
+
+ return lambda;
+ }
+
+ #region Expressions
+
+ [Conditional("DEBUG")]
+ private static void VerifyRewrite(Result result, Expression node) {
+ Debug.Assert(result.Node != null);
+
+ // (result.Action == RewriteAction.None) if and only if (node == result.Node)
+ Debug.Assert((result.Action == RewriteAction.None) ^ (node != result.Node), "rewrite action does not match node object identity");
+
+ // if the original node is an extension node, it should have been rewritten
+ Debug.Assert(result.Node.NodeType != ExpressionType.Extension, "extension nodes must be rewritten");
+
+ // if we have Copy, then node type must match
+ Debug.Assert(
+ result.Action != RewriteAction.Copy || node.NodeType == result.Node.NodeType || node.CanReduce,
+ "rewrite action does not match node object kind"
+ );
+
+ // New type must be reference assignable to the old type
+ // (our rewrites preserve type exactly, but the rules for rewriting
+ // an extension node are more lenient, see Expression.ReduceAndCheck())
+ Debug.Assert(
+ TypeUtils.AreReferenceAssignable(node.Type, result.Node.Type),
+ "rewritten object must be reference assignable to the original type"
+ );
+ }
+
+ private Result RewriteExpressionFreeTemps(Expression expression, Stack stack) {
+ int mark = Mark();
+ Result result = RewriteExpression(expression, stack);
+ Free(mark);
+ return result;
+ }
+
+ // DynamicExpression
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "stack")]
+ private Result RewriteDynamicExpression(Expression expr, Stack stack) {
+ var node = (DynamicExpression)expr;
+
+ // CallSite is on the stack
+ IArgumentProvider argNode = (IArgumentProvider)node;
+ ChildRewriter cr = new ChildRewriter(this, Stack.NonEmpty, argNode.ArgumentCount);
+ cr.AddArguments(argNode);
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNoRefArgs(node.DelegateType.GetMethod("Invoke"));
+ }
+ return cr.Finish(cr.Rewrite ? node.Rewrite(cr[0, -1]) : expr);
+ }
+
+ private Result RewriteIndexAssignment(BinaryExpression node, Stack stack) {
+ IndexExpression index = (IndexExpression)node.Left;
+
+ ChildRewriter cr = new ChildRewriter(this, stack, 2 + index.Arguments.Count);
+
+ cr.Add(index.Object);
+ cr.Add(index.Arguments);
+ cr.Add(node.Right);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNotRefInstance(index.Object);
+ }
+
+ if (cr.Rewrite) {
+ node = new AssignBinaryExpression(
+ new IndexExpression(
+ cr[0], // Object
+ index.Indexer,
+ cr[1, -2] // arguments
+ ),
+ cr[-1] // value
+ );
+ }
+
+ return cr.Finish(node);
+ }
+
+ // BinaryExpression: AndAlso, OrElse
+ private Result RewriteLogicalBinaryExpression(Expression expr, Stack stack) {
+ BinaryExpression node = (BinaryExpression)expr;
+
+ // Left expression runs on a stack as left by parent
+ Result left = RewriteExpression(node.Left, stack);
+ // ... and so does the right one
+ Result right = RewriteExpression(node.Right, stack);
+ //conversion is a lambda. stack state will be ignored.
+ Result conversion = RewriteExpression(node.Conversion, stack);
+
+ RewriteAction action = left.Action | right.Action | conversion.Action;
+ if (action != RewriteAction.None) {
+
+ // We don't have to worry about byref parameters here, because the
+ // factory doesn't allow it (it requires identical parameters and
+ // return type from the AndAlso/OrElse method)
+
+ expr = BinaryExpression.Create(
+ node.NodeType,
+ left.Node,
+ right.Node,
+ node.Type,
+ node.Method,
+ (LambdaExpression)conversion.Node
+ );
+ }
+ return new Result(action, expr);
+ }
+
+ private Result RewriteReducibleExpression(Expression expr, Stack stack) {
+ Result result = RewriteExpression(expr.Reduce(), stack);
+ // it's at least Copy because we reduced the node
+ return new Result(result.Action | RewriteAction.Copy, result.Node);
+ }
+
+ // BinaryExpression
+ private Result RewriteBinaryExpression(Expression expr, Stack stack) {
+ BinaryExpression node = (BinaryExpression)expr;
+
+ ChildRewriter cr = new ChildRewriter(this, stack, 3);
+ // Left expression executes on the stack as left by parent
+ cr.Add(node.Left);
+ // Right expression always has non-empty stack (left is on it)
+ cr.Add(node.Right);
+ // conversion is a lambda, stack state will be ignored
+ cr.Add(node.Conversion);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNoRefArgs(node.Method);
+ }
+
+ return cr.Finish(cr.Rewrite ?
+ BinaryExpression.Create(
+ node.NodeType,
+ cr[0],
+ cr[1],
+ node.Type,
+ node.Method,
+ (LambdaExpression)cr[2]) :
+ expr);
+ }
+
+ // variable assignment
+ private Result RewriteVariableAssignment(BinaryExpression node, Stack stack) {
+ // Expression is evaluated on a stack in current state
+ Result right = RewriteExpression(node.Right, stack);
+ if (right.Action != RewriteAction.None) {
+ node = Expression.Assign(node.Left, right.Node);
+ }
+ return new Result(right.Action, node);
+ }
+
+ private Result RewriteAssignBinaryExpression(Expression expr, Stack stack) {
+ var node = (BinaryExpression)expr;
+
+ switch (node.Left.NodeType) {
+ case ExpressionType.Index:
+ return RewriteIndexAssignment(node, stack);
+ case ExpressionType.MemberAccess:
+ return RewriteMemberAssignment(node, stack);
+ case ExpressionType.Parameter:
+ return RewriteVariableAssignment(node, stack);
+ case ExpressionType.Extension:
+ return RewriteExtensionAssignment(node, stack);
+ default:
+ throw Error.InvalidLvalue(node.Left.NodeType);
+ }
+ }
+
+ private Result RewriteExtensionAssignment(BinaryExpression node, Stack stack) {
+ node = Expression.Assign(node.Left.ReduceExtensions(), node.Right);
+ Result result = RewriteAssignBinaryExpression(node, stack);
+ // it's at least Copy because we reduced the node
+ return new Result(result.Action | RewriteAction.Copy, result.Node);
+ }
+
+ // LambdaExpression
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "stack")]
+ private static Result RewriteLambdaExpression(Expression expr, Stack stack) {
+ LambdaExpression node = (LambdaExpression)expr;
+
+ // Call back into the rewriter
+ expr = AnalyzeLambda(node);
+
+ // If the lambda gets rewritten, we don't need to spill the stack,
+ // but we do need to rebuild the tree above us so it includes the new node.
+ RewriteAction action = (expr == node) ? RewriteAction.None : RewriteAction.Copy;
+
+ return new Result(action, expr);
+ }
+
+ // ConditionalExpression
+ private Result RewriteConditionalExpression(Expression expr, Stack stack) {
+ ConditionalExpression node = (ConditionalExpression)expr;
+ // Test executes at the stack as left by parent
+ Result test = RewriteExpression(node.Test, stack);
+ // The test is popped by conditional jump so branches execute
+ // at the stack as left by parent too.
+ Result ifTrue = RewriteExpression(node.IfTrue, stack);
+ Result ifFalse = RewriteExpression(node.IfFalse, stack);
+
+ RewriteAction action = test.Action | ifTrue.Action | ifFalse.Action;
+ if (action != RewriteAction.None) {
+ expr = Expression.Condition(test.Node, ifTrue.Node, ifFalse.Node, node.Type);
+ }
+
+ return new Result(action, expr);
+ }
+
+ // member assignment
+ private Result RewriteMemberAssignment(BinaryExpression node, Stack stack) {
+ MemberExpression lvalue = (MemberExpression)node.Left;
+
+ ChildRewriter cr = new ChildRewriter(this, stack, 2);
+
+ // If there's an instance, it executes on the stack in current state
+ // and rest is executed on non-empty stack.
+ // Otherwise the stack is left unchaged.
+ cr.Add(lvalue.Expression);
+
+ cr.Add(node.Right);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNotRefInstance(lvalue.Expression);
+ }
+
+ if (cr.Rewrite) {
+ return cr.Finish(
+ new AssignBinaryExpression(
+ MemberExpression.Make(cr[0], lvalue.Member),
+ cr[1]
+ )
+ );
+ }
+ return new Result(RewriteAction.None, node);
+ }
+
+ // MemberExpression
+ private Result RewriteMemberExpression(Expression expr, Stack stack) {
+ MemberExpression node = (MemberExpression)expr;
+
+ // Expression is emitted on top of the stack in current state
+ Result expression = RewriteExpression(node.Expression, stack);
+ if (expression.Action != RewriteAction.None) {
+ if (expression.Action == RewriteAction.SpillStack &&
+ node.Member.MemberType == MemberTypes.Property) {
+ // Only need to validate propreties because reading a field
+ // is always side-effect free.
+ RequireNotRefInstance(node.Expression);
+ }
+ expr = MemberExpression.Make(expression.Node, node.Member);
+ }
+ return new Result(expression.Action, expr);
+ }
+
+ //RewriteIndexExpression
+ private Result RewriteIndexExpression(Expression expr, Stack stack) {
+ IndexExpression node = (IndexExpression)expr;
+
+ ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);
+
+ // For instance methods, the instance executes on the
+ // stack as is, but stays on the stack, making it non-empty.
+ cr.Add(node.Object);
+ cr.Add(node.Arguments);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNotRefInstance(node.Object);
+ }
+
+ if (cr.Rewrite) {
+ expr = new IndexExpression(
+ cr[0],
+ node.Indexer,
+ cr[1, -1]
+ );
+ }
+
+ return cr.Finish(expr);
+ }
+
+ // MethodCallExpression
+ private Result RewriteMethodCallExpression(Expression expr, Stack stack) {
+ MethodCallExpression node = (MethodCallExpression)expr;
+
+ ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);
+
+ // For instance methods, the instance executes on the
+ // stack as is, but stays on the stack, making it non-empty.
+ cr.Add(node.Object);
+
+ cr.AddArguments(node);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNotRefInstance(node.Object);
+ RequireNoRefArgs(node.Method);
+ }
+
+ return cr.Finish(cr.Rewrite ? node.Rewrite(cr[0], cr[1, -1]) : expr);
+ }
+
+ // NewArrayExpression
+ private Result RewriteNewArrayExpression(Expression expr, Stack stack) {
+ NewArrayExpression node = (NewArrayExpression)expr;
+
+ if (node.NodeType == ExpressionType.NewArrayInit) {
+ // In a case of array construction with element initialization
+ // the element expressions are never emitted on an empty stack because
+ // the array reference and the index are on the stack.
+ stack = Stack.NonEmpty;
+ } else {
+ // In a case of NewArrayBounds we make no modifications to the stack
+ // before emitting bounds expressions.
+ }
+
+ ChildRewriter cr = new ChildRewriter(this, stack, node.Expressions.Count);
+ cr.Add(node.Expressions);
+
+ if (cr.Rewrite) {
+ Type element = node.Type.GetElementType();
+ if (node.NodeType == ExpressionType.NewArrayInit) {
+ expr = Expression.NewArrayInit(element, cr[0, -1]);
+ } else {
+ expr = Expression.NewArrayBounds(element, cr[0, -1]);
+ }
+ }
+
+ return cr.Finish(expr);
+ }
+
+ // InvocationExpression
+ private Result RewriteInvocationExpression(Expression expr, Stack stack) {
+ InvocationExpression node = (InvocationExpression)expr;
+
+ ChildRewriter cr;
+
+ // See if the lambda will be inlined
+ LambdaExpression lambda = node.LambdaOperand;
+ if (lambda != null) {
+ // Arguments execute on current stack
+ cr = new ChildRewriter(this, stack, node.Arguments.Count);
+ cr.Add(node.Arguments);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNoRefArgs(Expression.GetInvokeMethod(node.Expression));
+ }
+
+ // Lambda body also executes on current stack
+ var spiller = new StackSpiller(stack);
+ lambda = lambda.Accept(spiller);
+
+ if (cr.Rewrite || spiller._lambdaRewrite != RewriteAction.None) {
+ node = new InvocationExpression(lambda, cr[0, -1], node.Type);
+ }
+
+ Result result = cr.Finish(node);
+ return new Result(result.Action | spiller._lambdaRewrite, result.Node);
+ }
+
+ cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);
+
+ // first argument starts on stack as provided
+ cr.Add(node.Expression);
+
+ // rest of arguments have non-empty stack (delegate instance on the stack)
+ cr.Add(node.Arguments);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNoRefArgs(Expression.GetInvokeMethod(node.Expression));
+ }
+
+ return cr.Finish(cr.Rewrite ? new InvocationExpression(cr[0], cr[1, -1], node.Type) : expr);
+ }
+
+ // NewExpression
+ private Result RewriteNewExpression(Expression expr, Stack stack) {
+ NewExpression node = (NewExpression)expr;
+
+ // The first expression starts on a stack as provided by parent,
+ // rest are definitely non-emtpy (which ChildRewriter guarantees)
+ ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count);
+ cr.AddArguments(node);
+
+ if (cr.Action == RewriteAction.SpillStack) {
+ RequireNoRefArgs(node.Constructor);
+ }
+
+ return cr.Finish(cr.Rewrite ? new NewExpression(node.Constructor, cr[0, -1], node.Members) : expr);
+ }
+
+ // TypeBinaryExpression
+ private Result RewriteTypeBinaryExpression(Expression expr, Stack stack) {
+ TypeBinaryExpression node = (TypeBinaryExpression)expr;
+ // The expression is emitted on top of current stack
+ Result expression = RewriteExpression(node.Expression, stack);
+ if (expression.Action != RewriteAction.None) {
+ if (node.NodeType == ExpressionType.TypeIs) {
+ expr = Expression.TypeIs(expression.Node, node.TypeOperand);
+ } else {
+ expr = Expression.TypeEqual(expression.Node, node.TypeOperand);
+ }
+ }
+ return new Result(expression.Action, expr);
+ }
+
+ // Throw
+ private Result RewriteThrowUnaryExpression(Expression expr, Stack stack) {
+ UnaryExpression node = (UnaryExpression)expr;
+
+ // Throw statement itself does not care about the stack
+ // but it will empty the stack and it may cause stack misbalance
+ // it so we need to restore stack after unconditional throw to make JIT happy
+ // this has an effect of executing Throw on an empty stack.
+
+ Result value = RewriteExpressionFreeTemps(node.Operand, Stack.Empty);
+ RewriteAction action = value.Action;
+
+ if (stack != Stack.Empty) {
+ action = RewriteAction.SpillStack;
+ }
+
+ if (action != RewriteAction.None) {
+ expr = Expression.Throw(value.Node, node.Type);
+ }
+
+ return new Result(action, expr);
+ }
+
+ // UnaryExpression
+ private Result RewriteUnaryExpression(Expression expr, Stack stack) {
+ UnaryExpression node = (UnaryExpression)expr;
+
+ Debug.Assert(node.NodeType != ExpressionType.Quote, "unexpected Quote");
+ Debug.Assert(node.NodeType != ExpressionType.Throw, "unexpected Throw");
+
+ // Operand is emitted on top of the stack as is
+ Result expression = RewriteExpression(node.Operand, stack);
+
+ if (expression.Action == RewriteAction.SpillStack) {
+ RequireNoRefArgs(node.Method);
+ }
+
+ if (expression.Action != RewriteAction.None) {
+ expr = new UnaryExpression(node.NodeType, expression.Node, node.Type, node.Method);
+ }
+ return new Result(expression.Action, expr);
+ }
+
+ // RewriteListInitExpression
+ private Result RewriteListInitExpression(Expression expr, Stack stack) {
+ ListInitExpression node = (ListInitExpression)expr;
+
+ //ctor runs on initial stack
+ Result newResult = RewriteExpression(node.NewExpression, stack);
+ Expression rewrittenNew = newResult.Node;
+ RewriteAction action = newResult.Action;
+
+ ReadOnlyCollection<ElementInit> inits = node.Initializers;
+
+ ChildRewriter[] cloneCrs = new ChildRewriter[inits.Count];
+
+ for (int i = 0; i < inits.Count; i++) {
+ ElementInit init = inits[i];
+
+ //initializers all run on nonempty stack
+ ChildRewriter cr = new ChildRewriter(this, Stack.NonEmpty, init.Arguments.Count);
+ cr.Add(init.Arguments);
+
+ action |= cr.Action;
+ cloneCrs[i] = cr;
+ }
+
+ switch (action) {
+ case RewriteAction.None:
+ break;
+ case RewriteAction.Copy:
+ ElementInit[] newInits = new ElementInit[inits.Count];
+ for (int i = 0; i < inits.Count; i++) {
+ ChildRewriter cr = cloneCrs[i];
+ if (cr.Action == RewriteAction.None) {
+ newInits[i] = inits[i];
+ } else {
+ newInits[i] = Expression.ElementInit(inits[i].AddMethod, cr[0, -1]);
+ }
+ }
+ expr = Expression.ListInit((NewExpression)rewrittenNew, new TrueReadOnlyCollection<ElementInit>(newInits));
+ break;
+ case RewriteAction.SpillStack:
+ RequireNotRefInstance(node.NewExpression);
+
+ ParameterExpression tempNew = MakeTemp(rewrittenNew.Type);
+ Expression[] comma = new Expression[inits.Count + 2];
+ comma[0] = Expression.Assign(tempNew, rewrittenNew);
+
+ for (int i = 0; i < inits.Count; i++) {
+ ChildRewriter cr = cloneCrs[i];
+ Result add = cr.Finish(Expression.Call(tempNew, inits[i].AddMethod, cr[0, -1]));
+ comma[i + 1] = add.Node;
+ }
+ comma[inits.Count + 1] = tempNew;
+ expr = MakeBlock(comma);
+ break;
+ default:
+ throw ContractUtils.Unreachable;
+ }
+
+ return new Result(action, expr);
+ }
+
+ // RewriteMemberInitExpression
+ private Result RewriteMemberInitExpression(Expression expr, Stack stack) {
+ MemberInitExpression node = (MemberInitExpression)expr;
+
+ //ctor runs on original stack
+ Result result = RewriteExpression(node.NewExpression, stack);
+ Expression rewrittenNew = result.Node;
+ RewriteAction action = result.Action;
+
+ ReadOnlyCollection<MemberBinding> bindings = node.Bindings;
+ BindingRewriter[] bindingRewriters = new BindingRewriter[bindings.Count];
+ for (int i = 0; i < bindings.Count; i++) {
+ MemberBinding binding = bindings[i];
+ //bindings run on nonempty stack
+ BindingRewriter rewriter = BindingRewriter.Create(binding, this, Stack.NonEmpty);
+ bindingRewriters[i] = rewriter;
+ action |= rewriter.Action;
+ }
+
+ switch (action) {
+ case RewriteAction.None:
+ break;
+ case RewriteAction.Copy:
+ MemberBinding[] newBindings = new MemberBinding[bindings.Count];
+ for (int i = 0; i < bindings.Count; i++) {
+ newBindings[i] = bindingRewriters[i].AsBinding();
+ }
+ expr = Expression.MemberInit((NewExpression)rewrittenNew, new TrueReadOnlyCollection<MemberBinding>(newBindings));
+ break;
+ case RewriteAction.SpillStack:
+ RequireNotRefInstance(node.NewExpression);
+
+ ParameterExpression tempNew = MakeTemp(rewrittenNew.Type);
+ Expression[] comma = new Expression[bindings.Count + 2];
+ comma[0] = Expression.Assign(tempNew, rewrittenNew);
+ for (int i = 0; i < bindings.Count; i++) {
+ BindingRewriter cr = bindingRewriters[i];
+ Expression initExpr = cr.AsExpression(tempNew);
+ comma[i + 1] = initExpr;
+ }
+ comma[bindings.Count + 1] = tempNew;
+ expr = MakeBlock(comma);
+ break;
+ default:
+ throw ContractUtils.Unreachable;
+ }
+ return new Result(action, expr);
+ }
+
+ #endregion
+
+ #region Statements
+
+ // Block
+ private Result RewriteBlockExpression(Expression expr, Stack stack) {
+ BlockExpression node = (BlockExpression)expr;
+
+ int count = node.ExpressionCount;
+ RewriteAction action = RewriteAction.None;
+ Expression[] clone = null;
+ for (int i = 0; i < count; i++) {
+ Expression expression = node.GetExpression(i);
+ // All statements within the block execute at the
+ // same stack state.
+ Result rewritten = RewriteExpression(expression, stack);
+ action |= rewritten.Action;
+
+ if (clone == null && rewritten.Action != RewriteAction.None) {
+ clone = Clone(node.Expressions, i);
+ }
+
+ if (clone != null) {
+ clone[i] = rewritten.Node;
+ }
+ }
+
+ if (action != RewriteAction.None) {
+ // okay to wrap since we know no one can mutate the clone array
+ expr = node.Rewrite(null, clone);
+ }
+ return new Result(action, expr);
+ }
+
+ // LabelExpression
+ private Result RewriteLabelExpression(Expression expr, Stack stack) {
+ LabelExpression node = (LabelExpression)expr;
+
+ Result expression = RewriteExpression(node.DefaultValue, stack);
+ if (expression.Action != RewriteAction.None) {
+ expr = Expression.Label(node.Target, expression.Node);
+ }
+ return new Result(expression.Action, expr);
+ }
+
+ // LoopStatement
+ private Result RewriteLoopExpression(Expression expr, Stack stack) {
+ LoopExpression node = (LoopExpression)expr;
+
+ // The loop statement requires empty stack for itself, so it
+ // can guarantee it to the child nodes.
+ Result body = RewriteExpression(node.Body, Stack.Empty);
+
+ RewriteAction action = body.Action;
+
+ // However, the loop itself requires that it executes on an empty stack
+ // so we need to rewrite if the stack is not empty.
+ if (stack != Stack.Empty) {
+ action = RewriteAction.SpillStack;
+ }
+
+ if (action != RewriteAction.None) {
+ expr = new LoopExpression(body.Node, node.BreakLabel, node.ContinueLabel);
+ }
+ return new Result(action, expr);
+ }
+
+ // GotoExpression
+ // Note: goto does not necessarily need an empty stack. We could always
+ // emit it as a "leave" which would clear the stack for us. That would
+ // prevent us from doing certain optimizations we might want to do,
+ // however, like the switch-case-goto pattern. For now, be conservative
+ private Result RewriteGotoExpression(Expression expr, Stack stack) {
+ GotoExpression node = (GotoExpression)expr;
+
+ // Goto requires empty stack to execute so the expression is
+ // going to execute on an empty stack.
+ Result value = RewriteExpressionFreeTemps(node.Value, Stack.Empty);
+
+ // However, the statement itself needs an empty stack for itself
+ // so if stack is not empty, rewrite to empty the stack.
+ RewriteAction action = value.Action;
+ if (stack != Stack.Empty) {
+ action = RewriteAction.SpillStack;
+ }
+
+ if (action != RewriteAction.None) {
+ expr = Expression.MakeGoto(node.Kind, node.Target, value.Node, node.Type);
+ }
+ return new Result(action, expr);
+ }
+
+ // SwitchStatement
+ private Result RewriteSwitchExpression(Expression expr, Stack stack) {
+ SwitchExpression node = (SwitchExpression)expr;
+
+ // The switch statement test is emitted on the stack in current state
+ Result switchValue = RewriteExpressionFreeTemps(node.SwitchValue, stack);
+
+ RewriteAction action = switchValue.Action;
+ ReadOnlyCollection<SwitchCase> cases = node.Cases;
+ SwitchCase[] clone = null;
+ for (int i = 0; i < cases.Count; i++) {
+ SwitchCase @case = cases[i];
+
+ Expression[] cloneTests = null;
+ ReadOnlyCollection<Expression> testValues = @case.TestValues;
+ for (int j = 0; j < testValues.Count; j++) {
+ // All tests execute at the same stack state as the switch.
+ // This is guarenteed by the compiler (to simplify spilling)
+ Result test = RewriteExpression(testValues[j], stack);
+ action |= test.Action;
+
+ if (cloneTests == null && test.Action != RewriteAction.None) {
+ cloneTests = Clone(testValues, j);
+ }
+
+ if (cloneTests != null) {
+ cloneTests[j] = test.Node;
+ }
+ }
+
+ // And all the cases also run on the same stack level.
+ Result body = RewriteExpression(@case.Body, stack);
+ action |= body.Action;
+
+ if (body.Action != RewriteAction.None || cloneTests != null) {
+ if (cloneTests != null) {
+ testValues = new ReadOnlyCollection<Expression>(cloneTests);
+ }
+ @case = new SwitchCase(body.Node, testValues);
+
+ if (clone == null) {
+ clone = Clone(cases, i);
+ }
+ }
+
+ if (clone != null) {
+ clone[i] = @case;
+ }
+ }
+
+ // default body also runs on initial stack
+ Result defaultBody = RewriteExpression(node.DefaultBody, stack);
+ action |= defaultBody.Action;
+
+ if (action != RewriteAction.None) {
+ if (clone != null) {
+ // okay to wrap because we aren't modifying the array
+ cases = new ReadOnlyCollection<SwitchCase>(clone);
+ }
+
+ expr = new SwitchExpression(node.Type, switchValue.Node, defaultBody.Node, node.Comparison, cases);
+ }
+
+ return new Result(action, expr);
+ }
+
+ // TryStatement
+ private Result RewriteTryExpression(Expression expr, Stack stack) {
+ TryExpression node = (TryExpression)expr;
+
+ // Try statement definitely needs an empty stack so its
+ // child nodes execute at empty stack.
+ Result body = RewriteExpression(node.Body, Stack.Empty);
+ ReadOnlyCollection<CatchBlock> handlers = node.Handlers;
+ CatchBlock[] clone = null;
+
+ RewriteAction action = body.Action;
+ if (handlers != null) {
+ for (int i = 0; i < handlers.Count; i++) {
+ RewriteAction curAction = body.Action;
+
+ CatchBlock handler = handlers[i];
+
+ Expression filter = handler.Filter;
+ if (handler.Filter != null) {
+ // our code gen saves the incoming filter value and provides it as a varaible so the stack is empty
+ Result rfault = RewriteExpression(handler.Filter, Stack.Empty);
+ action |= rfault.Action;
+ curAction |= rfault.Action;
+ filter = rfault.Node;
+ }
+
+ // Catch block starts with an empty stack (guaranteed by TryStatement)
+ Result rbody = RewriteExpression(handler.Body, Stack.Empty);
+ action |= rbody.Action;
+ curAction |= rbody.Action;
+
+ if (curAction != RewriteAction.None) {
+ handler = Expression.MakeCatchBlock(handler.Test, handler.Variable, rbody.Node, filter);
+
+ if (clone == null) {
+ clone = Clone(handlers, i);
+ }
+ }
+
+ if (clone != null) {
+ clone[i] = handler;
+ }
+ }
+ }
+
+ Result fault = RewriteExpression(node.Fault, Stack.Empty);
+ action |= fault.Action;
+
+ Result @finally = RewriteExpression(node.Finally, Stack.Empty);
+ action |= @finally.Action;
+
+ // If the stack is initially not empty, rewrite to spill the stack
+ if (stack != Stack.Empty) {
+ action = RewriteAction.SpillStack;
+ }
+
+ if (action != RewriteAction.None) {
+ if (clone != null) {
+ // okay to wrap because we aren't modifying the array
+ handlers = new ReadOnlyCollection<CatchBlock>(clone);
+ }
+
+ expr = new TryExpression(node.Type, body.Node, @finally.Node, fault.Node, handlers);
+ }
+ return new Result(action, expr);
+ }
+
+ private Result RewriteExtensionExpression(Expression expr, Stack stack) {
+ Result result = RewriteExpression(expr.ReduceExtensions(), stack);
+ // it's at least Copy because we reduced the node
+ return new Result(result.Action | RewriteAction.Copy, result.Node);
+ }
+
+ #endregion
+
+ #region Cloning
+
+ /// <summary>
+ /// Will clone an IList into an array of the same size, and copy
+ /// all vaues up to (and NOT including) the max index
+ /// </summary>
+ /// <returns>The cloned array.</returns>
+ private static T[] Clone<T>(ReadOnlyCollection<T> original, int max) {
+ Debug.Assert(original != null);
+ Debug.Assert(max < original.Count);
+
+ T[] clone = new T[original.Count];
+ for (int j = 0; j < max; j++) {
+ clone[j] = original[j];
+ }
+ return clone;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// If we are spilling, requires that there are no byref arguments to
+ /// the method call.
+ ///
+ /// Used for:
+ /// NewExpression,
+ /// MethodCallExpression,
+ /// InvocationExpression,
+ /// DynamicExpression,
+ /// UnaryExpression,
+ /// BinaryExpression.
+ /// </summary>
+ /// <remarks>
+ /// We could support this if spilling happened later in the compiler.
+ /// Other expressions that can emit calls with arguments (such as
+ /// ListInitExpression and IndexExpression) don't allow byref arguments.
+ /// </remarks>
+ private static void RequireNoRefArgs(MethodBase method) {
+ if (method != null && method.GetParametersCached().Any(p => p.ParameterType.IsByRef)) {
+ throw Error.TryNotSupportedForMethodsWithRefArgs(method);
+ }
+ }
+
+ /// <summary>
+ /// Requires that the instance is not a value type (primitive types are
+ /// okay because they're immutable).
+ ///
+ /// Used for:
+ /// MethodCallExpression,
+ /// MemberExpression (for properties),
+ /// IndexExpression,
+ /// ListInitExpression,
+ /// MemberInitExpression,
+ /// assign to MemberExpression,
+ /// assign to IndexExpression.
+ /// </summary>
+ /// <remarks>
+ /// We could support this if spilling happened later in the compiler.
+ /// </remarks>
+ private static void RequireNotRefInstance(Expression instance) {
+ // Primitive value types are okay because they are all readonly,
+ // but we can't rely on this for non-primitive types. So we throw
+ // NotSupported.
+ if (instance != null && instance.Type.IsValueType && Type.GetTypeCode(instance.Type) == TypeCode.Object) {
+ throw Error.TryNotSupportedForValueTypeInstances(instance.Type);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/SymbolDocumentGenerator.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/SymbolDocumentGenerator.cs
new file mode 100644
index 00000000000..cb0775cd49c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/SymbolDocumentGenerator.cs
@@ -0,0 +1,76 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.SymbolStore;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+using System.Linq.Expressions.Compiler;
+#else
+using Microsoft.Linq.Expressions;
+using Microsoft.Linq.Expressions.Compiler;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+#if CODEPLEX_40
+using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#else
+using ILGenerator = Microsoft.Linq.Expressions.Compiler.OffsetTrackingILGenerator;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// Generator of PDB debugging information for expression trees.
+ /// </summary>
+ internal sealed class SymbolDocumentGenerator : DebugInfoGenerator {
+ private Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter> _symbolWriters;
+
+ private ISymbolDocumentWriter GetSymbolWriter(MethodBuilder method, SymbolDocumentInfo document) {
+ ISymbolDocumentWriter result;
+ if (_symbolWriters == null) {
+ _symbolWriters = new Dictionary<SymbolDocumentInfo, ISymbolDocumentWriter>();
+ }
+
+ if (!_symbolWriters.TryGetValue(document, out result)) {
+ result = ((ModuleBuilder)method.Module).DefineDocument(document.FileName, document.Language, document.LanguageVendor, SymbolGuids.DocumentType_Text);
+ _symbolWriters.Add(document, result);
+ }
+
+ return result;
+ }
+
+ internal override void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) {
+ MethodBuilder builder = methodBase as MethodBuilder;
+ if (builder != null) {
+ ilg.MarkSequencePoint(GetSymbolWriter(builder, sequencePoint.Document), sequencePoint.StartLine, sequencePoint.StartColumn, sequencePoint.EndLine, sequencePoint.EndColumn);
+ }
+ }
+
+ public override void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression sequencePoint) {
+ Debug.Assert(false);
+ }
+
+ internal override void SetLocalName(LocalBuilder localBuilder, string name) {
+ localBuilder.SetLocalSymInfo(name);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/VariableBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/VariableBinder.cs
new file mode 100644
index 00000000000..fb01051b8e3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/VariableBinder.cs
@@ -0,0 +1,246 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions.Compiler {
+#else
+namespace Microsoft.Linq.Expressions.Compiler {
+#endif
+ /// <summary>
+ /// Determines if variables are closed over in nested lambdas and need to
+ /// be hoisted.
+ /// </summary>
+ internal sealed class VariableBinder : ExpressionVisitor {
+ private readonly AnalyzedTree _tree = new AnalyzedTree();
+ private readonly Stack<CompilerScope> _scopes = new Stack<CompilerScope>();
+ private readonly Stack<BoundConstants> _constants = new Stack<BoundConstants>();
+ private bool _inQuote;
+
+ internal static AnalyzedTree Bind(LambdaExpression lambda) {
+ var binder = new VariableBinder();
+ binder.Visit(lambda);
+ return binder._tree;
+ }
+
+ private VariableBinder() {
+ }
+
+ protected internal override Expression VisitConstant(ConstantExpression node) {
+ // If we're in Quote, we can ignore constants completely
+ if (_inQuote) {
+ return node;
+ }
+
+ // Constants that can be emitted into IL don't need to be stored on
+ // the delegate
+ if (ILGen.CanEmitConstant(node.Value, node.Type)) {
+ return node;
+ }
+
+ _constants.Peek().AddReference(node.Value, node.Type);
+ return node;
+ }
+
+ protected internal override Expression VisitUnary(UnaryExpression node) {
+ if (node.NodeType == ExpressionType.Quote) {
+ bool savedInQuote = _inQuote;
+ _inQuote = true;
+ Visit(node.Operand);
+ _inQuote = savedInQuote;
+ } else {
+ Visit(node.Operand);
+ }
+ return node;
+ }
+
+ protected internal override Expression VisitLambda<T>(Expression<T> node) {
+ _scopes.Push(_tree.Scopes[node] = new CompilerScope(node, true));
+ _constants.Push(_tree.Constants[node] = new BoundConstants());
+ Visit(MergeScopes(node));
+ _constants.Pop();
+ _scopes.Pop();
+ return node;
+ }
+
+ protected internal override Expression VisitInvocation(InvocationExpression node) {
+ LambdaExpression lambda = node.LambdaOperand;
+
+ // optimization: inline code for literal lambda's directly
+ if (lambda != null) {
+ // visit the lambda, but treat it more like a scope
+ _scopes.Push(_tree.Scopes[lambda] = new CompilerScope(lambda, false));
+ Visit(MergeScopes(lambda));
+ _scopes.Pop();
+ // visit the invoke's arguments
+ Visit(node.Arguments);
+ return node;
+ }
+
+ return base.VisitInvocation(node);
+ }
+
+ protected internal override Expression VisitBlock(BlockExpression node) {
+ if (node.Variables.Count == 0) {
+ Visit(node.Expressions);
+ return node;
+ }
+ _scopes.Push(_tree.Scopes[node] = new CompilerScope(node, false));
+ Visit(MergeScopes(node));
+ _scopes.Pop();
+ return node;
+ }
+
+ protected override CatchBlock VisitCatchBlock(CatchBlock node) {
+ if (node.Variable == null) {
+ Visit(node.Body);
+ return node;
+ }
+ _scopes.Push(_tree.Scopes[node] = new CompilerScope(node, false));
+ Visit(node.Body);
+ _scopes.Pop();
+ return node;
+ }
+
+ // If the immediate child is another scope, merge it into this one
+ // This is an optimization to save environment allocations and
+ // array accesses.
+ private ReadOnlyCollection<Expression> MergeScopes(Expression node) {
+ ReadOnlyCollection<Expression> body;
+ var lambda = node as LambdaExpression;
+ if (lambda != null) {
+ body = new ReadOnlyCollection<Expression>(new[] { lambda.Body });
+ } else {
+ body = ((BlockExpression)node).Expressions;
+ }
+
+ var currentScope = _scopes.Peek();
+
+ // A block body is mergeable if the body only contains one single block node containing variables,
+ // and the child block has the same type as the parent block.
+ while (body.Count == 1 && body[0].NodeType == ExpressionType.Block) {
+ var block = (BlockExpression)body[0];
+
+ if (block.Variables.Count > 0) {
+ // Make sure none of the variables are shadowed. If any
+ // are, we can't merge it.
+ foreach (var v in block.Variables) {
+ if (currentScope.Definitions.ContainsKey(v)) {
+ return body;
+ }
+ }
+
+ // Otherwise, merge it
+ if (currentScope.MergedScopes == null) {
+ currentScope.MergedScopes = new Set<object>(ReferenceEqualityComparer<object>.Instance);
+ }
+ currentScope.MergedScopes.Add(block);
+ foreach (var v in block.Variables) {
+ currentScope.Definitions.Add(v, VariableStorageKind.Local);
+ }
+ }
+ node = block;
+ body = block.Expressions;
+ }
+ return body;
+ }
+
+
+ protected internal override Expression VisitParameter(ParameterExpression node) {
+ Reference(node, VariableStorageKind.Local);
+
+ //
+ // Track reference count so we can emit it in a more optimal way if
+ // it is used a lot.
+ //
+ CompilerScope referenceScope = null;
+ foreach (CompilerScope scope in _scopes) {
+ //
+ // There are two times we care about references:
+ // 1. When we enter a lambda, we want to cache frequently
+ // used variables
+ // 2. When we enter a scope with closed-over variables, we
+ // want to cache it immediately when we allocate the
+ // closure slot for it
+ //
+ if (scope.IsMethod || scope.Definitions.ContainsKey(node)) {
+ referenceScope = scope;
+ break;
+ }
+ }
+
+ Debug.Assert(referenceScope != null);
+ if (referenceScope.ReferenceCount == null) {
+ referenceScope.ReferenceCount = new Dictionary<ParameterExpression, int>();
+ }
+
+ Helpers.IncrementCount(node, referenceScope.ReferenceCount);
+ return node;
+ }
+
+ protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
+ foreach (var v in node.Variables) {
+ // Force hoisting of these variables
+ Reference(v, VariableStorageKind.Hoisted);
+ }
+ return node;
+ }
+
+ private void Reference(ParameterExpression node, VariableStorageKind storage) {
+ CompilerScope definition = null;
+ foreach (CompilerScope scope in _scopes) {
+ if (scope.Definitions.ContainsKey(node)) {
+ definition = scope;
+ break;
+ }
+ scope.NeedsClosure = true;
+ if (scope.IsMethod) {
+ storage = VariableStorageKind.Hoisted;
+ }
+ }
+ if (definition == null) {
+ throw Error.UndefinedVariable(node.Name, node.Type, CurrentLambdaName);
+ }
+ if (storage == VariableStorageKind.Hoisted) {
+ if (node.IsByRef) {
+ throw Error.CannotCloseOverByRef(node.Name, CurrentLambdaName);
+ }
+ definition.Definitions[node] = VariableStorageKind.Hoisted;
+ }
+ }
+
+ private string CurrentLambdaName {
+ get {
+ foreach (var scope in _scopes) {
+ var lambda = scope.Node as LambdaExpression;
+ if (lambda != null) {
+ return lambda.Name;
+ }
+ }
+ throw ContractUtils.Unreachable;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/GlobalSuppressions.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/GlobalSuppressions.cs
new file mode 100644
index 00000000000..72fe59d28d6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/GlobalSuppressions.cs
@@ -0,0 +1,28 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click
+// "In Project Suppression File".
+// You do not need to add suppressions to this file manually.
+
+#if CODEPLEX_40
+//UnhandledExpressionType is used by System.Linq.Expressions.OldExpressionVisitor
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Linq.Expressions.Error.#UnhandledExpressionType(System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Linq.Expressions.Strings.#UnhandledExpressionType(System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Linq.Expressions.Error.#InvalidNullValue(System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Linq.Expressions.Error.#InvalidObjectType(System.Object,System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Linq.Expressions.Error.#HomogenousAppDomainRequired()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Linq.Expressions.Strings.#HomogenousAppDomainRequired")]
+#else
+//UnhandledExpressionType is used by Microsoft.Linq.Expressions.OldExpressionVisitor
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Linq.Expressions.Error.#UnhandledExpressionType(System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Linq.Expressions.Strings.#UnhandledExpressionType(System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Linq.Expressions.Error.#InvalidNullValue(System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Linq.Expressions.Error.#InvalidObjectType(System.Object,System.Object)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Linq.Expressions.Error.#HomogenousAppDomainRequired()")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Microsoft.Linq.Expressions.Strings.#HomogenousAppDomainRequired")]
+#endif
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "System.Runtime.CompilerServices.StrongBox`1.#System.Runtime.CompilerServices.IStrongBox.Value")]
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.Core.csproj b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.Core.csproj
new file mode 100644
index 00000000000..766f3130950
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.Core.csproj
@@ -0,0 +1,248 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+
+
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2AE75F5A-CD1F-4925-9647-AF4D1C282FB4}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <RootNamespace>System.Scripting</RootNamespace>
+ <AssemblyName>Microsoft.Scripting.Core</AssemblyName>
+<DocumentationFile>$(OutputPath)\Microsoft.Scripting.Core.XML</DocumentationFile>
+ <NoWarn>1591</NoWarn>
+ <OldToolsVersion>2.0</OldToolsVersion>
+<AssemblyOriginatorKeyFile>$(SolutionDir)\Runtime\MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly Condition="'$(SignAssembly)' == '' And Exists('$(AssemblyOriginatorKeyFile)')">true</SignAssembly>
+ <SignedSym Condition="'$(SignAssembly)' == 'true'">SIGNED</SignedSym>
+ <DelaySign>true</DelaySign>
+ <SilverlightPath Condition="$(SilverlightPath) == ''">$(ProgramFiles)\Microsoft Silverlight\2.0.40115.0</SilverlightPath>
+ <BaseAddress>855638016</BaseAddress>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FxCop|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\fxcop\</OutputPath>
+ <DefineConstants>TRACE;$(SignedSym);MICROSOFT_SCRIPTING_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <CodeAnalysisRules>-Microsoft.Usage#CA2209;+!Microsoft.Design#CA1012;-!Microsoft.Design#CA2210;+!Microsoft.Design#CA1040;+!Microsoft.Design#CA1005;+!Microsoft.Design#CA1020;-!Microsoft.Design#CA1021;+!Microsoft.Design#CA1010;+!Microsoft.Design#CA1011;+!Microsoft.Design#CA1009;+!Microsoft.Design#CA1050;+!Microsoft.Design#CA1026;+!Microsoft.Design#CA1019;+!Microsoft.Design#CA1031;+!Microsoft.Design#CA1047;+!Microsoft.Design#CA1000;+!Microsoft.Design#CA1048;+!Microsoft.Design#CA1051;+!Microsoft.Design#CA1002;+!Microsoft.Design#CA1061;+!Microsoft.Design#CA1006;+!Microsoft.Design#CA1046;+!Microsoft.Design#CA1045;+!Microsoft.Design#CA1065;+!Microsoft.Design#CA1038;+!Microsoft.Design#CA1008;+!Microsoft.Design#CA1028;+!Microsoft.Design#CA1064;-!Microsoft.Design#CA1004;+!Microsoft.Design#CA1035;+!Microsoft.Design#CA1063;+!Microsoft.Design#CA1032;+!Microsoft.Design#CA1023;+!Microsoft.Design#CA1033;+!Microsoft.Design#CA1039;+!Microsoft.Design#CA1016;+!Microsoft.Design#CA1014;+!Microsoft.Design#CA1017;+!Microsoft.Design#CA1018;+!Microsoft.Design#CA1027;+!Microsoft.Design#CA1059;+!Microsoft.Design#CA1060;+!Microsoft.Design#CA1034;+!Microsoft.Design#CA1013;+!Microsoft.Design#CA1036;+!Microsoft.Design#CA1044;+!Microsoft.Design#CA1041;+!Microsoft.Design#CA1025;+!Microsoft.Design#CA1052;+!Microsoft.Design#CA1053;+!Microsoft.Design#CA1057;+!Microsoft.Design#CA1058;+!Microsoft.Design#CA1001;+!Microsoft.Design#CA1049;+!Microsoft.Design#CA1054;+!Microsoft.Design#CA1056;+!Microsoft.Design#CA1055;+!Microsoft.Design#CA1030;+!Microsoft.Design#CA1003;+!Microsoft.Design#CA1007;+!Microsoft.Design#CA1043;+!Microsoft.Design#CA1024;+!Microsoft.Globalization#CA1301;+!Microsoft.Globalization#CA1302;+!Microsoft.Globalization#CA1308;+!Microsoft.Globalization#CA1306;+!Microsoft.Globalization#CA1304;+!Microsoft.Globalization#CA1305;+!Microsoft.Globalization#CA2101;+!Microsoft.Globalization#CA1300;+!Microsoft.Globalization#CA1307;+!Microsoft.Globalization#CA1309;+!Microsoft.Interoperability#CA1403;+!Microsoft.Interoperability#CA1406;+!Microsoft.Interoperability#CA1413;+!Microsoft.Interoperability#CA1402;+!Microsoft.Interoperability#CA1407;+!Microsoft.Interoperability#CA1404;+!Microsoft.Interoperability#CA1410;+!Microsoft.Interoperability#CA1411;+!Microsoft.Interoperability#CA1405;+!Microsoft.Interoperability#CA1409;+!Microsoft.Interoperability#CA1415;+!Microsoft.Interoperability#CA1408;+!Microsoft.Interoperability#CA1414;+!Microsoft.Interoperability#CA1412;+!Microsoft.Interoperability#CA1400;+!Microsoft.Interoperability#CA1401;+!Microsoft.Maintainability#CA1506;+!Microsoft.Maintainability#CA1502;+!Microsoft.Maintainability#CA1501;+!Microsoft.Maintainability#CA1505;+!Microsoft.Maintainability#CA1504;+!Microsoft.Maintainability#CA1500;+!Microsoft.Mobility#CA1600;+!Microsoft.Mobility#CA1601;-!Microsoft.Naming#CA1702;+!Microsoft.Naming#CA1700;+!Microsoft.Naming#CA1712;+!Microsoft.Naming#CA1713;+!Microsoft.Naming#CA1714;+!Microsoft.Naming#CA1709;-!Microsoft.Naming#CA1704;+!Microsoft.Naming#CA1708;+!Microsoft.Naming#CA1715;-!Microsoft.Naming#CA1710;-!Microsoft.Naming#CA1720;+!Microsoft.Naming#CA1707;+!Microsoft.Naming#CA1722;-!Microsoft.Naming#CA1711;+!Microsoft.Naming#CA1716;+!Microsoft.Naming#CA1717;+!Microsoft.Naming#CA1725;+!Microsoft.Naming#CA1719;+!Microsoft.Naming#CA1721;+!Microsoft.Naming#CA1701;+!Microsoft.Naming#CA1703;+!Microsoft.Naming#CA1724;-!Microsoft.Naming#CA1726;+!Microsoft.Performance#CA1809;+!Microsoft.Performance#CA1811;+!Microsoft.Performance#CA1812;+!Microsoft.Performance#CA1813;+!Microsoft.Performance#CA1823;+!Microsoft.Performance#CA1800;+!Microsoft.Performance#CA1805;+!Microsoft.Performance#CA1810;+!Microsoft.Performance#CA1824;+!Microsoft.Performance#CA1822;+!Microsoft.Performance#CA1815;+!Microsoft.Performance#CA1814;+!Microsoft.Performance#CA1819;+!Microsoft.Performance#CA1821;+!Microsoft.Performance#CA1804;+!Microsoft.Performance#CA1820;+!Microsoft.Performance#CA1802;+!Microsoft.Portability#CA1901;+!Microsoft.Portability#CA1900;+!Microsoft.Reliability#CA2001;+!Microsoft.Reliability#CA2002;+!Microsoft.Reliability#CA2003;+!Microsoft.Reliability#CA2004;+!Microsoft.Reliability#CA2006;+!Microsoft.Security#CA2116;+!Microsoft.Security#CA2117;+!Microsoft.Security#CA2105;+!Microsoft.Security#CA2115;+!Microsoft.Security#CA2102;+!Microsoft.Security#CA2104;+!Microsoft.Security#CA2122;+!Microsoft.Security#CA2114;+!Microsoft.Security#CA2123;+!Microsoft.Security#CA2111;+!Microsoft.Security#CA2108;+!Microsoft.Security#CA2107;+!Microsoft.Security#CA2103;+!Microsoft.Security#CA2118;+!Microsoft.Security#CA2109;+!Microsoft.Security#CA2119;+!Microsoft.Security#CA2106;+!Microsoft.Security#CA2112;+!Microsoft.Security#CA2120;+!Microsoft.Security#CA2121;+!Microsoft.Security#CA2126;+!Microsoft.Security#CA2124;+!Microsoft.Security#CA2127;+!Microsoft.Security#CA2128;+!Microsoft.Security#CA2129;+!Microsoft.Usage#CA2243;+!Microsoft.Usage#CA2236;+!Microsoft.Usage#CA1816;+!Microsoft.Usage#CA2227;+!Microsoft.Usage#CA2213;+!Microsoft.Usage#CA2216;+!Microsoft.Usage#CA2214;+!Microsoft.Usage#CA2222;+!Microsoft.Usage#CA1806;+!Microsoft.Usage#CA2217;+!Microsoft.Usage#CA2212;+!Microsoft.Usage#CA2219;+!Microsoft.Usage#CA2201;+!Microsoft.Usage#CA2228;+!Microsoft.Usage#CA2221;+!Microsoft.Usage#CA2220;+!Microsoft.Usage#CA2240;+!Microsoft.Usage#CA2229;+!Microsoft.Usage#CA2238;+!Microsoft.Usage#CA2207;+!Microsoft.Usage#CA2208;+!Microsoft.Usage#CA2235;+!Microsoft.Usage#CA2237;+!Microsoft.Usage#CA2232;+!Microsoft.Usage#CA2223;+!Microsoft.Usage#CA2211;+!Microsoft.Usage#CA2233;+!Microsoft.Usage#CA2225;+!Microsoft.Usage#CA2226;+!Microsoft.Usage#CA2231;+!Microsoft.Usage#CA2224;+!Microsoft.Usage#CA2218;+!Microsoft.Usage#CA2234;+!Microsoft.Usage#CA2239;+!Microsoft.Usage#CA2200;+!Microsoft.Usage#CA1801;+!Microsoft.Usage#CA2242;+!Microsoft.Usage#CA2205;+!Microsoft.Usage#CA2230</CodeAnalysisRules>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Debug\</OutputPath>
+<DocumentationFile>$(OutputPath)\Microsoft.Scripting.Core.xml</DocumentationFile>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym);MICROSOFT_SCRIPTING_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Release\</OutputPath>
+<DocumentationFile>$(OutputPath)\Microsoft.Scripting.Core.xml</DocumentationFile>
+ <DefineConstants>TRACE;$(SignedSym);MICROSOFT_SCRIPTING_CORE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+<OutputPath>$(SolutionDir)\..\Bin\Silverlight Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;SILVERLIGHT;MICROSOFT_SCRIPTING_CORE</DefineConstants>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <ErrorReport>prompt</ErrorReport>
+ <NoStdLib>true</NoStdLib>
+<DocumentationFile>$(OutputPath)\Microsoft.Scripting.Core.xml</DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <SilverlightBuild>true</SilverlightBuild>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Release|AnyCPU' ">
+<OutputPath>$(SolutionDir)\..\Bin\Silverlight Release\</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;MICROSOFT_SCRIPTING_CORE</DefineConstants>
+<DocumentationFile>$(OutputPath)\Microsoft.Scripting.Core.xml</DocumentationFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <NoWarn>618</NoWarn>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <SilverlightBuild>true</SilverlightBuild>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="System.Configuration" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SilverlightPath)\mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SilverlightPath)\System.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Data" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="System.Xml" Condition=" $(SilverlightBuild) != 'true' " />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\Hosts\Silverlight\SilverlightVersion.cs" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <Link>Properties\SilverlightVersion.cs</Link>
+ </Compile>
+ <Compile Include="Actions\CallInfo.cs" />
+ <Compile Include="Actions\CallSiteOps.cs" />
+ <Compile Include="Actions\InvokeMemberBinder.cs" />
+ <Compile Include="Actions\BinaryOperationBinder.cs" />
+ <Compile Include="Actions\CallSite.cs" />
+ <Compile Include="Actions\CallSiteBinder.cs" />
+ <Compile Include="Actions\CallSiteHelpers.cs" />
+ <Compile Include="Actions\ConvertBinder.cs" />
+ <Compile Include="Actions\DeleteIndexBinder.cs" />
+ <Compile Include="Actions\DynamicObject.cs" />
+ <Compile Include="Actions\ExpandoObject.cs" />
+ <Compile Include="Actions\ExpandoClass.cs" />
+ <Compile Include="Actions\GetIndexBinder.cs" />
+ <Compile Include="Actions\CreateInstanceBinder.cs" />
+ <Compile Include="Actions\DeleteMemberBinder.cs" />
+ <Compile Include="Actions\GetMemberBinder.cs" />
+ <Compile Include="Actions\IDynamicMetaObjectProvider.cs" />
+ <Compile Include="Actions\InvokeBinder.cs" />
+ <Compile Include="Actions\DynamicMetaObject.cs" />
+ <Compile Include="Actions\DynamicMetaObjectBinder.cs" />
+ <Compile Include="Actions\BindingRestrictions.cs" />
+ <Compile Include="Actions\RuleCache.cs" />
+ <Compile Include="Actions\SetIndexBinder.cs" />
+ <Compile Include="Actions\SetMemberBinder.cs" />
+ <Compile Include="Ast\Expression.DebuggerProxy.cs" />
+ <Compile Include="Ast\IArgumentProvider.cs" />
+ <Compile Include="Ast\ListArgumentProvider.cs" />
+ <Compile Include="Actions\UnaryOperationBinder.cs" />
+ <Compile Include="Ast\ExpressionStringBuilder.cs" />
+ <Compile Include="Compiler\BoundConstants.cs" />
+ <Compile Include="Ast\DebugInfoExpression.cs" />
+ <Compile Include="Ast\SymbolDocumentInfo.cs" />
+ <Compile Include="Compiler\DelegateHelpers.cs" />
+ <Compile Include="Compiler\DelegateHelpers.Generated.cs" />
+ <Compile Include="Ast\GotoExpression.cs" />
+ <Compile Include="Compiler\LabelInfo.cs" />
+ <Compile Include="Compiler\AnalyzedTree.cs" />
+ <Compile Include="Compiler\OffsetTrackingILGenerator.cs" />
+ <Compile Include="Compiler\RuntimeVariableList.cs" />
+ <Compile Include="Actions\UpdateDelegates.Generated.cs" />
+ <Compile Include="Ast\DynamicExpression.cs" />
+ <Compile Include="Ast\BinaryExpression.cs" />
+ <Compile Include="Ast\BlockExpression.cs" />
+ <Compile Include="Ast\CatchBlock.cs" />
+ <Compile Include="Ast\ConditionalExpression.cs" />
+ <Compile Include="Ast\ConstantExpression.cs" />
+ <Compile Include="Ast\DefaultExpression.cs" />
+ <Compile Include="Ast\ElementInit.cs" />
+ <Compile Include="Ast\Expression.cs" />
+ <Compile Include="Ast\ExpressionType.cs" />
+ <Compile Include="Ast\IndexExpression.cs" />
+ <Compile Include="Ast\InvocationExpression.cs" />
+ <Compile Include="Ast\LabelTarget.cs" />
+ <Compile Include="Ast\LabelExpression.cs" />
+ <Compile Include="Ast\LambdaExpression.cs" />
+ <Compile Include="Ast\ListInitExpression.cs" />
+ <Compile Include="Ast\RuntimeVariablesExpression.cs" />
+ <Compile Include="Ast\LoopExpression.cs" />
+ <Compile Include="Ast\MemberAssignment.cs" />
+ <Compile Include="Ast\MemberBinding.cs" />
+ <Compile Include="Ast\MemberExpression.cs" />
+ <Compile Include="Ast\MemberInitExpression.cs" />
+ <Compile Include="Ast\MemberListBinding.cs" />
+ <Compile Include="Ast\MemberMemberBinding.cs" />
+ <Compile Include="Ast\MethodCallExpression.cs" />
+ <Compile Include="Ast\NewArrayExpression.cs" />
+ <Compile Include="Ast\NewExpression.cs" />
+ <Compile Include="Ast\ParameterExpression.cs" />
+ <Compile Include="Ast\SwitchCase.cs" />
+ <Compile Include="Ast\SwitchExpression.cs" />
+ <Compile Include="Ast\TryExpression.cs" />
+ <Compile Include="Ast\TypeBinaryExpression.cs" />
+ <Compile Include="Ast\TypeUtils.cs" />
+ <Compile Include="Ast\UnaryExpression.cs" />
+ <Compile Include="Compiler\Closure.cs" />
+ <Compile Include="Compiler\CompilerScope.Storage.cs" />
+ <Compile Include="Compiler\CompilerScope.cs" />
+ <Compile Include="Compiler\ConstantCheck.cs" />
+ <Compile Include="Compiler\ExpressionQuoter.cs" />
+ <Compile Include="Ast\ExpressionVisitor.cs" />
+ <Compile Include="Ast\DebugViewWriter.cs" />
+ <Compile Include="Compiler\HoistedLocals.cs" />
+ <Compile Include="Compiler\KeyedQueue.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Address.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Binary.cs" />
+ <Compile Include="Compiler\LambdaCompiler.ControlFlow.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Expressions.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Generated.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Lambda.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Logical.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Statements.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Unary.cs" />
+ <Compile Include="Compiler\LambdaCompiler.cs" />
+ <Compile Include="Compiler\DebugInfoGenerator.cs" />
+ <Compile Include="Compiler\Set.cs" />
+ <Compile Include="Compiler\StackSpiller.Bindings.cs" />
+ <Compile Include="Compiler\StackSpiller.Generated.cs" />
+ <Compile Include="Compiler\StackSpiller.Temps.cs" />
+ <Compile Include="Compiler\StackSpiller.cs" />
+ <Compile Include="Compiler\SymbolDocumentGenerator.cs" />
+ <Compile Include="Compiler\VariableBinder.cs" />
+ <Compile Include="Compiler\AssemblyGen.cs" />
+ <Compile Include="Compiler\ILGen.cs" />
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Utils\Action.cs" />
+ <Compile Include="Utils\CacheDict.cs" />
+ <Compile Include="Utils\CollectionExtensions.cs" />
+ <Compile Include="Utils\ContractUtils.cs" />
+ <Compile Include="Utils\ExceptionFactory.Generated.cs" />
+ <Compile Include="Utils\Function.cs" />
+ <Compile Include="Utils\Helpers.cs" />
+ <Compile Include="Utils\IRuntimeVariables.cs" />
+ <Compile Include="Utils\ReadOnlyCollectionBuilder.cs" />
+ <Compile Include="Utils\ReadOnlyDictionary.cs" />
+ <Compile Include="Utils\ReferenceEqualityComparer.cs" />
+ <Compile Include="Utils\StrongBox.cs" />
+ <Compile Include="Utils\TrueReadOnlyCollection.cs" />
+ <Compile Include="Utils\TypeExtensions.cs" />
+ <Compile Include="Stubs.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="Microsoft.Scripting.ExtensionAttribute.csproj">
+ <Project>{8B0F1074-750E-4D64-BF23-A1E0F54261E5}</Project>
+ <Name>Microsoft.Scripting.ExtensionAttribute</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="..\..\System\Linq\Expressions\System.Linq.Expressions.txt">
+ <Link>Ast\System.Linq.Expressions.txt</Link>
+ </Content>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" Condition=" '$(SilverlightTreeBuild)' != 'true' " />
+ <!-- This task produces a list of Compile items. -->
+ <Target Name="GetCompileItems" Outputs="@(CompileItems)">
+ <CreateItem Include="%(Compile.Identity)">
+ <Output TaskParameter="Include" ItemName="CompileItems" />
+ </CreateItem>
+ </Target>
+</Project>
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.ExtensionAttribute.csproj b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.ExtensionAttribute.csproj
new file mode 100644
index 00000000000..863a5d01eeb
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Microsoft.Scripting.ExtensionAttribute.csproj
@@ -0,0 +1,104 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+
+
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8B0F1074-750E-4D64-BF23-A1E0F54261E5}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Microsoft.Scripting.ExtensionAttribute</RootNamespace>
+ <AssemblyName>Microsoft.Scripting.ExtensionAttribute</AssemblyName>
+ <OldToolsVersion>2.0</OldToolsVersion>
+<AssemblyOriginatorKeyFile>$(SolutionDir)\Runtime\MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly Condition="'$(SignAssembly)' == '' And Exists('$(AssemblyOriginatorKeyFile)')">true</SignAssembly>
+ <SignedSym Condition="'$(SignAssembly)' == 'true'">SIGNED</SignedSym>
+ <DelaySign>true</DelaySign>
+ <BaseAddress>866123776</BaseAddress>
+ <SilverlightPath Condition="$(SilverlightPath) == ''">$(ProgramFiles)\Microsoft Silverlight\2.0.40115.0</SilverlightPath>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FxCop|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\fxcop\</OutputPath>
+ <DefineConstants>TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <CodeAnalysisRules>-Microsoft.Usage#CA2209;+!Microsoft.Design#CA1012;-!Microsoft.Design#CA2210;+!Microsoft.Design#CA1040;+!Microsoft.Design#CA1005;+!Microsoft.Design#CA1020;-!Microsoft.Design#CA1021;+!Microsoft.Design#CA1010;+!Microsoft.Design#CA1011;+!Microsoft.Design#CA1009;+!Microsoft.Design#CA1050;+!Microsoft.Design#CA1026;+!Microsoft.Design#CA1019;+!Microsoft.Design#CA1031;+!Microsoft.Design#CA1047;+!Microsoft.Design#CA1000;+!Microsoft.Design#CA1048;+!Microsoft.Design#CA1051;+!Microsoft.Design#CA1002;+!Microsoft.Design#CA1061;+!Microsoft.Design#CA1006;+!Microsoft.Design#CA1046;+!Microsoft.Design#CA1045;+!Microsoft.Design#CA1065;+!Microsoft.Design#CA1038;+!Microsoft.Design#CA1008;+!Microsoft.Design#CA1028;+!Microsoft.Design#CA1064;-!Microsoft.Design#CA1004;+!Microsoft.Design#CA1035;+!Microsoft.Design#CA1063;+!Microsoft.Design#CA1032;+!Microsoft.Design#CA1023;+!Microsoft.Design#CA1033;+!Microsoft.Design#CA1039;+!Microsoft.Design#CA1016;+!Microsoft.Design#CA1014;+!Microsoft.Design#CA1017;+!Microsoft.Design#CA1018;+!Microsoft.Design#CA1027;+!Microsoft.Design#CA1059;+!Microsoft.Design#CA1060;+!Microsoft.Design#CA1034;+!Microsoft.Design#CA1013;+!Microsoft.Design#CA1036;+!Microsoft.Design#CA1044;+!Microsoft.Design#CA1041;+!Microsoft.Design#CA1025;+!Microsoft.Design#CA1052;+!Microsoft.Design#CA1053;+!Microsoft.Design#CA1057;+!Microsoft.Design#CA1058;+!Microsoft.Design#CA1001;+!Microsoft.Design#CA1049;+!Microsoft.Design#CA1054;+!Microsoft.Design#CA1056;+!Microsoft.Design#CA1055;+!Microsoft.Design#CA1030;+!Microsoft.Design#CA1003;+!Microsoft.Design#CA1007;+!Microsoft.Design#CA1043;+!Microsoft.Design#CA1024;+!Microsoft.Globalization#CA1301;+!Microsoft.Globalization#CA1302;+!Microsoft.Globalization#CA1308;+!Microsoft.Globalization#CA1306;+!Microsoft.Globalization#CA1304;+!Microsoft.Globalization#CA1305;+!Microsoft.Globalization#CA2101;+!Microsoft.Globalization#CA1300;+!Microsoft.Globalization#CA1307;+!Microsoft.Globalization#CA1309;+!Microsoft.Interoperability#CA1403;+!Microsoft.Interoperability#CA1406;+!Microsoft.Interoperability#CA1413;+!Microsoft.Interoperability#CA1402;+!Microsoft.Interoperability#CA1407;+!Microsoft.Interoperability#CA1404;+!Microsoft.Interoperability#CA1410;+!Microsoft.Interoperability#CA1411;+!Microsoft.Interoperability#CA1405;+!Microsoft.Interoperability#CA1409;+!Microsoft.Interoperability#CA1415;+!Microsoft.Interoperability#CA1408;+!Microsoft.Interoperability#CA1414;+!Microsoft.Interoperability#CA1412;+!Microsoft.Interoperability#CA1400;+!Microsoft.Interoperability#CA1401;+!Microsoft.Maintainability#CA1506;+!Microsoft.Maintainability#CA1502;+!Microsoft.Maintainability#CA1501;+!Microsoft.Maintainability#CA1505;+!Microsoft.Maintainability#CA1504;+!Microsoft.Maintainability#CA1500;+!Microsoft.Mobility#CA1600;+!Microsoft.Mobility#CA1601;-!Microsoft.Naming#CA1702;+!Microsoft.Naming#CA1700;+!Microsoft.Naming#CA1712;+!Microsoft.Naming#CA1713;+!Microsoft.Naming#CA1714;+!Microsoft.Naming#CA1709;-!Microsoft.Naming#CA1704;+!Microsoft.Naming#CA1708;+!Microsoft.Naming#CA1715;-!Microsoft.Naming#CA1710;-!Microsoft.Naming#CA1720;+!Microsoft.Naming#CA1707;+!Microsoft.Naming#CA1722;-!Microsoft.Naming#CA1711;+!Microsoft.Naming#CA1716;+!Microsoft.Naming#CA1717;+!Microsoft.Naming#CA1725;+!Microsoft.Naming#CA1719;+!Microsoft.Naming#CA1721;+!Microsoft.Naming#CA1701;+!Microsoft.Naming#CA1703;+!Microsoft.Naming#CA1724;-!Microsoft.Naming#CA1726;+!Microsoft.Performance#CA1809;+!Microsoft.Performance#CA1811;+!Microsoft.Performance#CA1812;+!Microsoft.Performance#CA1813;+!Microsoft.Performance#CA1823;+!Microsoft.Performance#CA1800;+!Microsoft.Performance#CA1805;+!Microsoft.Performance#CA1810;+!Microsoft.Performance#CA1824;+!Microsoft.Performance#CA1822;+!Microsoft.Performance#CA1815;+!Microsoft.Performance#CA1814;+!Microsoft.Performance#CA1819;+!Microsoft.Performance#CA1821;+!Microsoft.Performance#CA1804;+!Microsoft.Performance#CA1820;+!Microsoft.Performance#CA1802;+!Microsoft.Portability#CA1901;+!Microsoft.Portability#CA1900;+!Microsoft.Reliability#CA2001;+!Microsoft.Reliability#CA2002;+!Microsoft.Reliability#CA2003;+!Microsoft.Reliability#CA2004;+!Microsoft.Reliability#CA2006;+!Microsoft.Security#CA2116;+!Microsoft.Security#CA2117;+!Microsoft.Security#CA2105;+!Microsoft.Security#CA2115;+!Microsoft.Security#CA2102;+!Microsoft.Security#CA2104;+!Microsoft.Security#CA2122;+!Microsoft.Security#CA2114;+!Microsoft.Security#CA2123;+!Microsoft.Security#CA2111;+!Microsoft.Security#CA2108;+!Microsoft.Security#CA2107;+!Microsoft.Security#CA2103;+!Microsoft.Security#CA2118;+!Microsoft.Security#CA2109;+!Microsoft.Security#CA2119;+!Microsoft.Security#CA2106;+!Microsoft.Security#CA2112;+!Microsoft.Security#CA2120;+!Microsoft.Security#CA2121;+!Microsoft.Security#CA2126;+!Microsoft.Security#CA2124;+!Microsoft.Security#CA2127;+!Microsoft.Security#CA2128;+!Microsoft.Security#CA2129;+!Microsoft.Usage#CA2243;+!Microsoft.Usage#CA2236;+!Microsoft.Usage#CA1816;+!Microsoft.Usage#CA2227;+!Microsoft.Usage#CA2213;+!Microsoft.Usage#CA2216;+!Microsoft.Usage#CA2214;+!Microsoft.Usage#CA2222;+!Microsoft.Usage#CA1806;+!Microsoft.Usage#CA2217;+!Microsoft.Usage#CA2212;+!Microsoft.Usage#CA2219;+!Microsoft.Usage#CA2201;+!Microsoft.Usage#CA2228;+!Microsoft.Usage#CA2221;+!Microsoft.Usage#CA2220;+!Microsoft.Usage#CA2240;+!Microsoft.Usage#CA2229;+!Microsoft.Usage#CA2238;+!Microsoft.Usage#CA2207;+!Microsoft.Usage#CA2208;+!Microsoft.Usage#CA2235;+!Microsoft.Usage#CA2237;+!Microsoft.Usage#CA2232;+!Microsoft.Usage#CA2223;+!Microsoft.Usage#CA2211;+!Microsoft.Usage#CA2233;+!Microsoft.Usage#CA2225;+!Microsoft.Usage#CA2226;+!Microsoft.Usage#CA2231;+!Microsoft.Usage#CA2224;+!Microsoft.Usage#CA2218;+!Microsoft.Usage#CA2234;+!Microsoft.Usage#CA2239;+!Microsoft.Usage#CA2200;+!Microsoft.Usage#CA1801;+!Microsoft.Usage#CA2242;+!Microsoft.Usage#CA2205;+!Microsoft.Usage#CA2230</CodeAnalysisRules>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Release\</OutputPath>
+ <DefineConstants>TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <BaseAddress>1929379840</BaseAddress>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+<OutputPath>$(SolutionDir)\..\Bin\Silverlight Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;SILVERLIGHT</DefineConstants>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <ErrorReport>prompt</ErrorReport>
+ <NoStdLib>true</NoStdLib>
+ <NoWarn>1591,618</NoWarn>
+ <SilverlightBuild>true</SilverlightBuild>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Release|AnyCPU' ">
+<OutputPath>$(SolutionDir)\..\Bin\Silverlight Release\</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <NoWarn>1591,618</NoWarn>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <SilverlightBuild>true</SilverlightBuild>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SilverlightPath)\mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SilverlightPath)\System.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\Hosts\Silverlight\SilverlightVersion.cs" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <Link>Properties\SilverlightVersion.cs</Link>
+ </Compile>
+ <Compile Include="Properties\ExtensionAssemblyInfo.cs" />
+ <Compile Include="Utils\Extension.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" Condition=" '$(SilverlightTreeBuild)' != 'true' " />
+ <!-- This task produces a list of Compile items. -->
+ <Target Name="GetCompileItems" Outputs="@(CompileItems)">
+ <CreateItem Include="%(Compile.Identity)">
+ <Output TaskParameter="Include" ItemName="CompileItems" />
+ </CreateItem>
+ </Target>
+</Project>
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/AssemblyInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..8760043dbb1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/AssemblyInfo.cs
@@ -0,0 +1,73 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Scripting")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Microsoft.Scripting")]
+[assembly: AssemblyCopyright("� Microsoft Corporation. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+[assembly: CLSCompliant(true)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("cabb8088-1370-43ca-ad47-1c32d3f7bd10")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: SecurityTransparent]
+
+[assembly: System.Resources.NeutralResourcesLanguage("en-US")]
+
+#if !SILVERLIGHT
+[assembly: AssemblyVersion("0.9.6.10")]
+[assembly: AssemblyFileVersion("1.0.0.00")]
+[assembly: AssemblyInformationalVersion("1.0")]
+[assembly: AllowPartiallyTrustedCallers]
+#if CODEPLEX_40
+[assembly: SecurityRules(SecurityRuleSet.Level1)]
+#endif
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/ExtensionAssemblyInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/ExtensionAssemblyInfo.cs
new file mode 100644
index 00000000000..b4d07215ed9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Properties/ExtensionAssemblyInfo.cs
@@ -0,0 +1,69 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Scripting.ExtensionAttribute")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("Microsoft.Scripting.ExtensionAttribute")]
+[assembly: AssemblyCopyright("� Microsoft Corporation. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+[assembly: CLSCompliant(true)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b828a36d-f568-48a7-9bdd-412b0a1bfa32")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: SecurityTransparent]
+
+[assembly: System.Resources.NeutralResourcesLanguage("en-US")]
+
+#if !SILVERLIGHT
+[assembly: AssemblyVersion("2.0.0.0")] // shouldn't change, this assembly is unchanged. This is the version it originally shipped as.
+[assembly: AssemblyFileVersion("1.0.0.00")]
+[assembly: AssemblyInformationalVersion("1.0")]
+[assembly: AllowPartiallyTrustedCallers]
+#if CODEPLEX_40
+[assembly: SecurityRules(SecurityRuleSet.Level1)]
+#endif
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Stubs.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Stubs.cs
new file mode 100644
index 00000000000..25ef27c9f77
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Stubs.cs
@@ -0,0 +1,213 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if SILVERLIGHT // Stubs
+
+namespace System {
+
+ /// <summary>
+ /// An application exception.
+ /// </summary>
+ public class ApplicationException : Exception {
+ private const int error = unchecked((int)0x80131600);
+ /// <summary>
+ /// The constructor.
+ /// </summary>
+ public ApplicationException()
+ : base("Application Exception") {
+ HResult = error;
+ }
+
+ /// <summary>
+ /// The constructor.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ public ApplicationException(string message)
+ : base(message) {
+ HResult = error;
+ }
+
+ /// <summary>
+ /// The constructor.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <param name="innerException">The inner exception.</param>
+ public ApplicationException(string message, Exception innerException)
+ : base(message, innerException) {
+ HResult = error;
+ }
+ }
+
+ namespace Runtime.InteropServices {
+ /// <summary>
+ /// The Default Parameter Value Attribute.
+ /// </summary>
+ public sealed class DefaultParameterValueAttribute : Attribute {
+ /// <summary>
+ /// The constructor
+ /// </summary>
+ /// <param name="value">The value.</param>
+ public DefaultParameterValueAttribute(object value) { }
+ }
+ }
+
+ // We reference these namespaces via "using"
+ // We don't actually use them because the code is #if !SILVERLIGHT
+ // Rather than fix the usings all over the place, just define these here
+ namespace Runtime.Remoting { class Dummy {} }
+ namespace Security.Policy { class Dummy {} }
+ namespace Xml.XPath { class Dummy {} }
+
+ namespace Reflection {
+ /// <summary>
+ /// PortableExecutableKinds enum.
+ /// </summary>
+ public enum PortableExecutableKinds {
+ /// <summary>
+ /// ILOnly
+ /// </summary>
+ ILOnly = 0
+ }
+
+ /// <summary>
+ /// ImageFileMachine enum.
+ /// </summary>
+ public enum ImageFileMachine {
+ /// <summary>
+ /// I386
+ /// </summary>
+ I386 = 1
+ }
+ }
+
+ namespace ComponentModel {
+
+ /// <summary>
+ /// The Warning exception.
+ /// </summary>
+ public class WarningException : SystemException {
+ /// <summary>
+ /// The constructor.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ public WarningException(string message) : base(message) { }
+ }
+ }
+
+ /// <summary>
+ /// The serializable attribute.
+ /// </summary>
+ public class SerializableAttribute : Attribute {
+ }
+
+ /// <summary>
+ /// Non serializable attribute.
+ /// </summary>
+ public class NonSerializedAttribute : Attribute {
+ }
+
+ namespace Runtime.Serialization {
+ /// <summary>
+ /// ISerializable interface.
+ /// </summary>
+ public interface ISerializable {
+ }
+ }
+
+ /// <summary>
+ /// The ConsoleColor enum.
+ /// </summary>
+ public enum ConsoleColor {
+ /// <summary>
+ /// Black.
+ /// </summary>
+ Black = 0,
+ /// <summary>
+ /// DarkBlue.
+ /// </summary>
+ DarkBlue = 1,
+ /// <summary>
+ /// DarkGreen.
+ /// </summary>
+ DarkGreen = 2,
+ /// <summary>
+ /// DaryCyan.
+ /// </summary>
+ DarkCyan = 3,
+ /// <summary>
+ /// DarkRed
+ /// </summary>
+ DarkRed = 4,
+ /// <summary>
+ /// DarkMagenta
+ /// </summary>
+ DarkMagenta = 5,
+ /// <summary>
+ /// DarkYellow
+ /// </summary>
+ DarkYellow = 6,
+ /// <summary>
+ /// Gray
+ /// </summary>
+ Gray = 7,
+ /// <summary>
+ /// DarkGray
+ /// </summary>
+ DarkGray = 8,
+ /// <summary>
+ /// Blue
+ /// </summary>
+ Blue = 9,
+ /// <summary>
+ /// Green
+ /// </summary>
+ Green = 10,
+ /// <summary>
+ /// Cyan
+ /// </summary>
+ Cyan = 11,
+ /// <summary>
+ /// Red
+ /// </summary>
+ Red = 12,
+ /// <summary>
+ /// Magenta
+ /// </summary>
+ Magenta = 13,
+ /// <summary>
+ /// Yellow
+ /// </summary>
+ Yellow = 14,
+ /// <summary>
+ /// White
+ /// </summary>
+ White = 15,
+ }
+
+}
+
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/System.Core.csproj b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/System.Core.csproj
new file mode 100644
index 00000000000..22938af0480
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/System.Core.csproj
@@ -0,0 +1,253 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+
+
+
+
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2AE75F5A-CD1F-4925-9647-AF4D1C282FB4}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <RootNamespace>System.Scripting</RootNamespace>
+ <AssemblyName>System.Core</AssemblyName>
+<DocumentationFile>$(OutputPath)\System.Core.XML</DocumentationFile>
+ <NoWarn>1591</NoWarn>
+ <OldToolsVersion>2.0</OldToolsVersion>
+<AssemblyOriginatorKeyFile>$(SolutionDir)\Runtime\MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly Condition="'$(SignAssembly)' == '' And Exists('$(AssemblyOriginatorKeyFile)')">true</SignAssembly>
+ <SignedSym Condition="'$(SignAssembly)' == 'true'">SIGNED</SignedSym>
+ <DelaySign>true</DelaySign>
+ <BaseAddress>855638016</BaseAddress>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FxCop|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\fxcop\</OutputPath>
+ <DefineConstants>TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>true</RunCodeAnalysis>
+ <CodeAnalysisRules>-Microsoft.Usage#CA2209;+!Microsoft.Design#CA1012;-!Microsoft.Design#CA2210;+!Microsoft.Design#CA1040;+!Microsoft.Design#CA1005;+!Microsoft.Design#CA1020;-!Microsoft.Design#CA1021;+!Microsoft.Design#CA1010;+!Microsoft.Design#CA1011;+!Microsoft.Design#CA1009;+!Microsoft.Design#CA1050;+!Microsoft.Design#CA1026;+!Microsoft.Design#CA1019;+!Microsoft.Design#CA1031;+!Microsoft.Design#CA1047;+!Microsoft.Design#CA1000;+!Microsoft.Design#CA1048;+!Microsoft.Design#CA1051;+!Microsoft.Design#CA1002;+!Microsoft.Design#CA1061;+!Microsoft.Design#CA1006;+!Microsoft.Design#CA1046;+!Microsoft.Design#CA1045;+!Microsoft.Design#CA1065;+!Microsoft.Design#CA1038;+!Microsoft.Design#CA1008;+!Microsoft.Design#CA1028;+!Microsoft.Design#CA1064;-!Microsoft.Design#CA1004;+!Microsoft.Design#CA1035;+!Microsoft.Design#CA1063;+!Microsoft.Design#CA1032;+!Microsoft.Design#CA1023;+!Microsoft.Design#CA1033;+!Microsoft.Design#CA1039;+!Microsoft.Design#CA1016;+!Microsoft.Design#CA1014;+!Microsoft.Design#CA1017;+!Microsoft.Design#CA1018;+!Microsoft.Design#CA1027;+!Microsoft.Design#CA1059;+!Microsoft.Design#CA1060;+!Microsoft.Design#CA1034;+!Microsoft.Design#CA1013;+!Microsoft.Design#CA1036;+!Microsoft.Design#CA1044;+!Microsoft.Design#CA1041;+!Microsoft.Design#CA1025;+!Microsoft.Design#CA1052;+!Microsoft.Design#CA1053;+!Microsoft.Design#CA1057;+!Microsoft.Design#CA1058;+!Microsoft.Design#CA1001;+!Microsoft.Design#CA1049;+!Microsoft.Design#CA1054;+!Microsoft.Design#CA1056;+!Microsoft.Design#CA1055;+!Microsoft.Design#CA1030;+!Microsoft.Design#CA1003;+!Microsoft.Design#CA1007;+!Microsoft.Design#CA1043;+!Microsoft.Design#CA1024;+!Microsoft.Globalization#CA1301;+!Microsoft.Globalization#CA1302;+!Microsoft.Globalization#CA1308;+!Microsoft.Globalization#CA1306;+!Microsoft.Globalization#CA1304;+!Microsoft.Globalization#CA1305;+!Microsoft.Globalization#CA2101;+!Microsoft.Globalization#CA1300;+!Microsoft.Globalization#CA1307;+!Microsoft.Globalization#CA1309;+!Microsoft.Interoperability#CA1403;+!Microsoft.Interoperability#CA1406;+!Microsoft.Interoperability#CA1413;+!Microsoft.Interoperability#CA1402;+!Microsoft.Interoperability#CA1407;+!Microsoft.Interoperability#CA1404;+!Microsoft.Interoperability#CA1410;+!Microsoft.Interoperability#CA1411;+!Microsoft.Interoperability#CA1405;+!Microsoft.Interoperability#CA1409;+!Microsoft.Interoperability#CA1415;+!Microsoft.Interoperability#CA1408;+!Microsoft.Interoperability#CA1414;+!Microsoft.Interoperability#CA1412;+!Microsoft.Interoperability#CA1400;+!Microsoft.Interoperability#CA1401;+!Microsoft.Maintainability#CA1506;+!Microsoft.Maintainability#CA1502;+!Microsoft.Maintainability#CA1501;+!Microsoft.Maintainability#CA1505;+!Microsoft.Maintainability#CA1504;+!Microsoft.Maintainability#CA1500;+!Microsoft.Mobility#CA1600;+!Microsoft.Mobility#CA1601;-!Microsoft.Naming#CA1702;+!Microsoft.Naming#CA1700;+!Microsoft.Naming#CA1712;+!Microsoft.Naming#CA1713;+!Microsoft.Naming#CA1714;+!Microsoft.Naming#CA1709;-!Microsoft.Naming#CA1704;+!Microsoft.Naming#CA1708;+!Microsoft.Naming#CA1715;-!Microsoft.Naming#CA1710;-!Microsoft.Naming#CA1720;+!Microsoft.Naming#CA1707;+!Microsoft.Naming#CA1722;-!Microsoft.Naming#CA1711;+!Microsoft.Naming#CA1716;+!Microsoft.Naming#CA1717;+!Microsoft.Naming#CA1725;+!Microsoft.Naming#CA1719;+!Microsoft.Naming#CA1721;+!Microsoft.Naming#CA1701;+!Microsoft.Naming#CA1703;+!Microsoft.Naming#CA1724;-!Microsoft.Naming#CA1726;+!Microsoft.Performance#CA1809;+!Microsoft.Performance#CA1811;+!Microsoft.Performance#CA1812;+!Microsoft.Performance#CA1813;+!Microsoft.Performance#CA1823;+!Microsoft.Performance#CA1800;+!Microsoft.Performance#CA1805;+!Microsoft.Performance#CA1810;+!Microsoft.Performance#CA1824;+!Microsoft.Performance#CA1822;+!Microsoft.Performance#CA1815;+!Microsoft.Performance#CA1814;+!Microsoft.Performance#CA1819;+!Microsoft.Performance#CA1821;+!Microsoft.Performance#CA1804;+!Microsoft.Performance#CA1820;+!Microsoft.Performance#CA1802;+!Microsoft.Portability#CA1901;+!Microsoft.Portability#CA1900;+!Microsoft.Reliability#CA2001;+!Microsoft.Reliability#CA2002;+!Microsoft.Reliability#CA2003;+!Microsoft.Reliability#CA2004;+!Microsoft.Reliability#CA2006;+!Microsoft.Security#CA2116;+!Microsoft.Security#CA2117;+!Microsoft.Security#CA2105;+!Microsoft.Security#CA2115;+!Microsoft.Security#CA2102;+!Microsoft.Security#CA2104;+!Microsoft.Security#CA2122;+!Microsoft.Security#CA2114;+!Microsoft.Security#CA2123;+!Microsoft.Security#CA2111;+!Microsoft.Security#CA2108;+!Microsoft.Security#CA2107;+!Microsoft.Security#CA2103;+!Microsoft.Security#CA2118;+!Microsoft.Security#CA2109;+!Microsoft.Security#CA2119;+!Microsoft.Security#CA2106;+!Microsoft.Security#CA2112;+!Microsoft.Security#CA2120;+!Microsoft.Security#CA2121;+!Microsoft.Security#CA2126;+!Microsoft.Security#CA2124;+!Microsoft.Security#CA2127;+!Microsoft.Security#CA2128;+!Microsoft.Security#CA2129;+!Microsoft.Usage#CA2243;+!Microsoft.Usage#CA2236;+!Microsoft.Usage#CA1816;+!Microsoft.Usage#CA2227;+!Microsoft.Usage#CA2213;+!Microsoft.Usage#CA2216;+!Microsoft.Usage#CA2214;+!Microsoft.Usage#CA2222;+!Microsoft.Usage#CA1806;+!Microsoft.Usage#CA2217;+!Microsoft.Usage#CA2212;+!Microsoft.Usage#CA2219;+!Microsoft.Usage#CA2201;+!Microsoft.Usage#CA2228;+!Microsoft.Usage#CA2221;+!Microsoft.Usage#CA2220;+!Microsoft.Usage#CA2240;+!Microsoft.Usage#CA2229;+!Microsoft.Usage#CA2238;+!Microsoft.Usage#CA2207;+!Microsoft.Usage#CA2208;+!Microsoft.Usage#CA2235;+!Microsoft.Usage#CA2237;+!Microsoft.Usage#CA2232;+!Microsoft.Usage#CA2223;+!Microsoft.Usage#CA2211;+!Microsoft.Usage#CA2233;+!Microsoft.Usage#CA2225;+!Microsoft.Usage#CA2226;+!Microsoft.Usage#CA2231;+!Microsoft.Usage#CA2224;+!Microsoft.Usage#CA2218;+!Microsoft.Usage#CA2234;+!Microsoft.Usage#CA2239;+!Microsoft.Usage#CA2200;+!Microsoft.Usage#CA1801;+!Microsoft.Usage#CA2242;+!Microsoft.Usage#CA2205;+!Microsoft.Usage#CA2230</CodeAnalysisRules>
+ <NoWarn>
+ </NoWarn>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Debug\</OutputPath>
+<DocumentationFile>$(OutputPath)\System.Core.xml</DocumentationFile>
+ <DefineConstants>DEBUG;TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+<OutputPath>$(SolutionDir)\..\Bin\Release\</OutputPath>
+<DocumentationFile>$(OutputPath)\System.Scripting.Core.xml</DocumentationFile>
+ <DefineConstants>TRACE;$(SignedSym)</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <NoWarn>
+ </NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+<OutputPath>$(SolutionDir)\..\Bin\Silverlight Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;SILVERLIGHT</DefineConstants>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <DebugType>full</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
+ <ErrorReport>prompt</ErrorReport>
+ <NoStdLib>true</NoStdLib>
+<DocumentationFile>$(OutputPath)\System.Scripting.Core.xml</DocumentationFile>
+ <NoWarn>618</NoWarn>
+ <SilverlightBuild>true</SilverlightBuild>
+ <SilverlightSdkPath>$(ProgramFiles)\Microsoft Silverlight\2.0.31005.0</SilverlightSdkPath>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Silverlight Release|AnyCPU' ">
+<OutputPath>$(SolutionDir)\..\Bin\Silverlight Release\</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
+<DocumentationFile>$(OutputPath)\System.Scripting.Core.xml</DocumentationFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <NoWarn>618</NoWarn>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <SilverlightBuild>true</SilverlightBuild>
+ <SilverlightSdkPath>$(ProgramFiles)\Microsoft Silverlight\2.0.31005.0</SilverlightSdkPath>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="System.Configuration" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SilverlightSdkPath)\mscorlib.dll</HintPath>
+ </Reference>
+ <Reference Include="System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SilverlightSdkPath)\System.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Data" Condition=" $(SilverlightBuild) != 'true' " />
+ <Reference Include="System.Xml" Condition=" $(SilverlightBuild) != 'true' " />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\Hosts\Silverlight\SilverlightVersion.cs" Condition=" '$(SilverlightBuild)' == 'true' ">
+ <Link>Properties\SilverlightVersion.cs</Link>
+ </Compile>
+ <Compile Include="Actions\CallInfo.cs" />
+ <Compile Include="Actions\CallSiteOps.cs" />
+ <Compile Include="Actions\InvokeMemberBinder.cs" />
+ <Compile Include="Actions\BinaryOperationBinder.cs" />
+ <Compile Include="Actions\CallSite.cs" />
+ <Compile Include="Actions\CallSiteBinder.cs" />
+ <Compile Include="Actions\CallSiteRule.cs" />
+ <Compile Include="Actions\CallSiteHelpers.cs" />
+ <Compile Include="Actions\ConvertBinder.cs" />
+ <Compile Include="Actions\DeleteIndexBinder.cs" />
+ <Compile Include="Actions\DynamicObject.cs" />
+ <Compile Include="Actions\ExpandoObject.cs" />
+ <Compile Include="Actions\ExpandoClass.cs" />
+ <Compile Include="Actions\GetIndexBinder.cs" />
+ <Compile Include="Actions\CreateInstanceBinder.cs" />
+ <Compile Include="Actions\DeleteMemberBinder.cs" />
+ <Compile Include="Actions\GetMemberBinder.cs" />
+ <Compile Include="Actions\IDynamicMetaObjectProvider.cs" />
+ <Compile Include="Actions\InvokeBinder.cs" />
+ <Compile Include="Actions\DynamicMetaObject.cs" />
+ <Compile Include="Actions\DynamicMetaObjectBinder.cs" />
+ <Compile Include="Actions\BindingRestrictions.cs" />
+ <Compile Include="Actions\RuleCache.cs" />
+ <Compile Include="Actions\SetIndexBinder.cs" />
+ <Compile Include="Actions\SetMemberBinder.cs" />
+ <Compile Include="Actions\SmallRuleSet.cs" />
+ <Compile Include="Ast\Expression.DebuggerProxy.cs" />
+ <Compile Include="Ast\IArgumentProvider.cs" />
+ <Compile Include="Ast\ListArgumentProvider.cs" />
+ <Compile Include="Compiler\ArgumentPrepender.cs" />
+ <Compile Include="Actions\UnaryOperationBinder.cs" />
+ <Compile Include="Ast\ExpressionStringBuilder.cs" />
+ <Compile Include="Compiler\BoundConstants.cs" />
+ <Compile Include="Ast\DebugInfoExpression.cs" />
+ <Compile Include="Ast\SymbolDocumentInfo.cs" />
+ <Compile Include="Compiler\DelegateHelpers.cs" />
+ <Compile Include="Compiler\DelegateHelpers.Generated.cs" />
+ <Compile Include="Ast\GotoExpression.cs" />
+ <Compile Include="Compiler\LabelInfo.cs" />
+ <Compile Include="Compiler\AnalyzedTree.cs" />
+ <Compile Include="Compiler\OffsetTrackingILGenerator.cs" />
+ <Compile Include="Compiler\RuntimeVariableList.cs" />
+ <Compile Include="Actions\UpdateDelegates.Generated.cs" />
+ <Compile Include="Ast\DynamicExpression.cs" />
+ <Compile Include="Actions\AutoRuleTemplate.cs" />
+ <Compile Include="Ast\BinaryExpression.cs" />
+ <Compile Include="Ast\BlockExpression.cs" />
+ <Compile Include="Ast\CatchBlock.cs" />
+ <Compile Include="Ast\ConditionalExpression.cs" />
+ <Compile Include="Ast\ConstantExpression.cs" />
+ <Compile Include="Ast\DefaultExpression.cs" />
+ <Compile Include="Ast\ElementInit.cs" />
+ <Compile Include="Ast\Expression.cs" />
+ <Compile Include="Ast\ExpressionType.cs" />
+ <Compile Include="Ast\IndexExpression.cs" />
+ <Compile Include="Ast\InvocationExpression.cs" />
+ <Compile Include="Ast\LabelTarget.cs" />
+ <Compile Include="Ast\LabelExpression.cs" />
+ <Compile Include="Ast\LambdaExpression.cs" />
+ <Compile Include="Ast\ListInitExpression.cs" />
+ <Compile Include="Ast\RuntimeVariablesExpression.cs" />
+ <Compile Include="Ast\LoopExpression.cs" />
+ <Compile Include="Ast\MemberAssignment.cs" />
+ <Compile Include="Ast\MemberBinding.cs" />
+ <Compile Include="Ast\MemberExpression.cs" />
+ <Compile Include="Ast\MemberInitExpression.cs" />
+ <Compile Include="Ast\MemberListBinding.cs" />
+ <Compile Include="Ast\MemberMemberBinding.cs" />
+ <Compile Include="Ast\MethodCallExpression.cs" />
+ <Compile Include="Ast\NewArrayExpression.cs" />
+ <Compile Include="Ast\NewExpression.cs" />
+ <Compile Include="Ast\ParameterExpression.cs" />
+ <Compile Include="Ast\SwitchCase.cs" />
+ <Compile Include="Ast\SwitchExpression.cs" />
+ <Compile Include="Ast\TreeComparer.cs" />
+ <Compile Include="Ast\TryExpression.cs" />
+ <Compile Include="Ast\TypeBinaryExpression.cs" />
+ <Compile Include="Ast\TypeUtils.cs" />
+ <Compile Include="Ast\UnaryExpression.cs" />
+ <Compile Include="Compiler\Closure.cs" />
+ <Compile Include="Compiler\CompilerScope.Storage.cs" />
+ <Compile Include="Compiler\CompilerScope.cs" />
+ <Compile Include="Compiler\ConstantCheck.cs" />
+ <Compile Include="Compiler\ExpressionQuoter.cs" />
+ <Compile Include="Ast\ExpressionVisitor.cs" />
+ <Compile Include="Ast\ExpressionWriter.cs" />
+ <Compile Include="Compiler\HoistedLocals.cs" />
+ <Compile Include="Compiler\KeyedQueue.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Address.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Binary.cs" />
+ <Compile Include="Compiler\LambdaCompiler.ControlFlow.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Expressions.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Generated.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Lambda.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Logical.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Statements.cs" />
+ <Compile Include="Compiler\LambdaCompiler.Unary.cs" />
+ <Compile Include="Compiler\LambdaCompiler.cs" />
+ <Compile Include="Compiler\DebugInfoGenerator.cs" />
+ <Compile Include="Compiler\Set.cs" />
+ <Compile Include="Compiler\StackSpiller.Bindings.cs" />
+ <Compile Include="Compiler\StackSpiller.Generated.cs" />
+ <Compile Include="Compiler\StackSpiller.Temps.cs" />
+ <Compile Include="Compiler\StackSpiller.cs" />
+ <Compile Include="Compiler\SymbolDocumentGenerator.cs" />
+ <Compile Include="Compiler\VariableBinder.cs" />
+ <Compile Include="Compiler\AssemblyGen.cs" />
+ <Compile Include="Compiler\ILGen.cs" />
+ <Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Utils\Action.cs" />
+ <Compile Include="Utils\CacheDict.cs" />
+ <Compile Include="Utils\CollectionExtensions.cs" />
+ <Compile Include="Utils\ContractUtils.cs" />
+ <Compile Include="Utils\ExceptionFactory.Generated.cs" />
+ <Compile Include="Utils\Function.cs" />
+ <Compile Include="Utils\Helpers.cs" />
+ <Compile Include="Utils\IRuntimeVariables.cs" />
+ <Compile Include="Utils\ReadOnlyCollectionBuilder.cs" />
+ <Compile Include="Utils\ReadOnlyDictionary.cs" />
+ <Compile Include="Utils\ReferenceEqualityComparer.cs" />
+ <Compile Include="Utils\StrongBox.cs" />
+ <Compile Include="Utils\TrueReadOnlyCollection.cs" />
+ <Compile Include="Utils\TypeExtensions.cs" />
+ <Compile Include="Stubs.cs" />
+ <Compile Include="Utils\WeakUniqueSet.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="..\..\System\Linq\Expressions\System.Linq.Expressions.txt">
+ <Link>Ast\System.Linq.Expressions.txt</Link>
+ </Content>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" Condition=" '$(SilverlightTreeBuild)' != 'true' " />
+ <!-- This task produces a list of Compile items. -->
+ <Target Name="GetCompileItems" Outputs="@(CompileItems)">
+ <CreateItem Include="%(Compile.Identity)">
+ <Output TaskParameter="Include" ItemName="CompileItems" />
+ </CreateItem>
+ </Target>
+</Project>
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Action.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Action.cs
new file mode 100644
index 00000000000..3d6eee3ae10
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Action.cs
@@ -0,0 +1,654 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+namespace System {
+#else
+namespace Microsoft {
+#endif
+ #if MICROSOFT_SCRIPTING_CORE
+
+ /// <summary>
+ /// Encapsulates a method that takes no parameters and does not return a value.
+ /// </summary>
+ public delegate void Action();
+
+ #endif
+
+ // public delegate void Action<T>(T obj); -- Already defined in mscorlib
+
+ #region Generated Action Types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_action_types from: generate_dynsites.py
+
+#if MICROSOFT_SCRIPTING_CORE
+
+ /// <summary>
+ /// Encapsulates a method that takes two parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
+
+ /// <summary>
+ /// Encapsulates a method that takes three parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
+
+ /// <summary>
+ /// Encapsulates a method that takes four parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+
+ /// <summary>
+ /// Encapsulates a method that takes five parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+
+ /// <summary>
+ /// Encapsulates a method that takes six parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
+
+ /// <summary>
+ /// Encapsulates a method that takes seven parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
+
+ /// <summary>
+ /// Encapsulates a method that takes eight parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
+
+ /// <summary>
+ /// Encapsulates a method that takes nine parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
+
+ /// <summary>
+ /// Encapsulates a method that takes ten parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
+
+ /// <summary>
+ /// Encapsulates a method that takes eleven parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
+
+ /// <summary>
+ /// Encapsulates a method that takes twelve parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
+
+ /// <summary>
+ /// Encapsulates a method that takes thirteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13);
+
+ /// <summary>
+ /// Encapsulates a method that takes fourteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
+
+ /// <summary>
+ /// Encapsulates a method that takes fifteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
+
+ /// <summary>
+ /// Encapsulates a method that takes sixteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T16">The type of the sixteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg16">The sixteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
+#else
+
+ /// <summary>
+ /// Encapsulates a method that takes nine parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
+
+ /// <summary>
+ /// Encapsulates a method that takes ten parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
+
+ /// <summary>
+ /// Encapsulates a method that takes eleven parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
+
+ /// <summary>
+ /// Encapsulates a method that takes twelve parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
+
+ /// <summary>
+ /// Encapsulates a method that takes thirteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13);
+
+ /// <summary>
+ /// Encapsulates a method that takes fourteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
+
+ /// <summary>
+ /// Encapsulates a method that takes fifteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
+
+ /// <summary>
+ /// Encapsulates a method that takes sixteen parameters and does not return a value.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T16">The type of the sixteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg16">The sixteenth parameter of the method that this delegate encapsulates.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
+
+#endif
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CacheDict.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CacheDict.cs
new file mode 100644
index 00000000000..3297e6e975e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CacheDict.cs
@@ -0,0 +1,121 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+ /// <summary>
+ /// Provides a dictionary-like object used for caches which holds onto a maximum
+ /// number of elements specified at construction time.
+ ///
+ /// This class is not thread safe.
+ /// </summary>
+ internal class CacheDict<TKey, TValue> {
+ private readonly Dictionary<TKey, KeyInfo> _dict = new Dictionary<TKey, KeyInfo>();
+ private readonly LinkedList<TKey> _list = new LinkedList<TKey>();
+ private readonly int _maxSize;
+
+ /// <summary>
+ /// Creates a dictionary-like object used for caches.
+ /// </summary>
+ /// <param name="maxSize">The maximum number of elements to store.</param>
+ internal CacheDict(int maxSize) {
+ _maxSize = maxSize;
+ }
+
+ /// <summary>
+ /// Tries to get the value associated with 'key', returning true if it's found and
+ /// false if it's not present.
+ /// </summary>
+ internal bool TryGetValue(TKey key, out TValue value) {
+ KeyInfo storedValue;
+ if (_dict.TryGetValue(key, out storedValue)) {
+ LinkedListNode<TKey> node = storedValue.List;
+ if (node.Previous != null) {
+ // move us to the head of the list...
+ _list.Remove(node);
+ _list.AddFirst(node);
+ }
+
+ value = storedValue.Value;
+ return true;
+ }
+
+ value = default(TValue);
+ return false;
+ }
+
+ /// <summary>
+ /// Adds a new element to the cache, replacing and moving it to the front if the
+ /// element is already present.
+ /// </summary>
+ internal void Add(TKey key, TValue value) {
+ KeyInfo keyInfo;
+ if (_dict.TryGetValue(key, out keyInfo)) {
+ // remove original entry from the linked list
+ _list.Remove(keyInfo.List);
+ } else if (_list.Count == _maxSize) {
+ // we've reached capacity, remove the last used element...
+ LinkedListNode<TKey> node = _list.Last;
+ _list.RemoveLast();
+ bool res = _dict.Remove(node.Value);
+ Debug.Assert(res);
+ }
+
+ // add the new entry to the head of the list and into the dictionary
+ LinkedListNode<TKey> listNode = new LinkedListNode<TKey>(key);
+ _list.AddFirst(listNode);
+ _dict[key] = new CacheDict<TKey, TValue>.KeyInfo(value, listNode);
+ }
+
+ /// <summary>
+ /// Returns the value associated with the given key, or throws KeyNotFoundException
+ /// if the key is not present.
+ /// </summary>
+ internal TValue this[TKey key] {
+ get {
+ TValue res;
+ if (TryGetValue(key, out res)) {
+ return res;
+ }
+ throw new KeyNotFoundException();
+ }
+ set {
+ Add(key, value);
+ }
+ }
+
+ private struct KeyInfo {
+ internal readonly TValue Value;
+ internal readonly LinkedListNode<TKey> List;
+
+ internal KeyInfo(TValue value, LinkedListNode<TKey> list) {
+ Value = value;
+ List = list;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CollectionExtensions.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CollectionExtensions.cs
new file mode 100644
index 00000000000..48ac6c1e17d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/CollectionExtensions.cs
@@ -0,0 +1,193 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+ internal static class CollectionExtensions {
+ /// <summary>
+ /// Wraps the provided enumerable into a ReadOnlyCollection{T}
+ ///
+ /// Copies all of the data into a new array, so the data can't be
+ /// changed after creation. The exception is if the enumerable is
+ /// already a ReadOnlyCollection{T}, in which case we just return it.
+ /// </summary>
+ internal static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> enumerable) {
+ if (enumerable == null) {
+ return EmptyReadOnlyCollection<T>.Instance;
+ }
+
+ var troc = enumerable as TrueReadOnlyCollection<T>;
+ if (troc != null) {
+ return troc;
+ }
+
+ var builder = enumerable as ReadOnlyCollectionBuilder<T>;
+ if (builder != null) {
+ return builder.ToReadOnlyCollection();
+ }
+
+ var collection = enumerable as ICollection<T>;
+ if (collection != null) {
+ int count = collection.Count;
+ if (count == 0) {
+ return EmptyReadOnlyCollection<T>.Instance;
+ }
+
+ T[] clone = new T[count];
+ collection.CopyTo(clone, 0);
+ return new TrueReadOnlyCollection<T>(clone);
+ }
+
+ // ToArray trims the excess space and speeds up access
+ return new TrueReadOnlyCollection<T>(new List<T>(enumerable).ToArray());
+ }
+
+ // We could probably improve the hashing here
+ internal static int ListHashCode<T>(this IEnumerable<T> list) {
+ var cmp = EqualityComparer<T>.Default;
+ int h = 6551;
+ foreach (T t in list) {
+ h ^= (h << 5) ^ cmp.GetHashCode(t);
+ }
+ return h;
+ }
+
+ internal static bool ListEquals<T>(this ICollection<T> first, ICollection<T> second) {
+ if (first.Count != second.Count) {
+ return false;
+ }
+ var cmp = EqualityComparer<T>.Default;
+ var f = first.GetEnumerator();
+ var s = second.GetEnumerator();
+ while (f.MoveNext()) {
+ s.MoveNext();
+
+ if (!cmp.Equals(f.Current, s.Current)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal static IEnumerable<U> Select<T, U>(this IEnumerable<T> enumerable, Func<T, U> select) {
+ foreach (T t in enumerable) {
+ yield return select(t);
+ }
+ }
+
+ // Name needs to be different so it doesn't conflict with Enumerable.Select
+ internal static U[] Map<T, U>(this ICollection<T> collection, Func<T, U> select) {
+ int count = collection.Count;
+ U[] result = new U[count];
+ count = 0;
+ foreach (T t in collection) {
+ result[count++] = select(t);
+ }
+ return result;
+ }
+
+ internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) {
+ foreach (T t in enumerable) {
+ if (where(t)) {
+ yield return t;
+ }
+ }
+ }
+
+ internal static bool Any<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
+ foreach (T element in source) {
+ if (predicate(element)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ internal static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
+ foreach (T element in source) {
+ if (!predicate(element)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal static T[] RemoveFirst<T>(this T[] array) {
+ T[] result = new T[array.Length - 1];
+ Array.Copy(array, 1, result, 0, result.Length);
+ return result;
+ }
+
+ internal static T[] RemoveLast<T>(this T[] array) {
+ T[] result = new T[array.Length - 1];
+ Array.Copy(array, 0, result, 0, result.Length);
+ return result;
+ }
+
+ internal static T[] AddFirst<T>(this IList<T> list, T item) {
+ T[] res = new T[list.Count + 1];
+ res[0] = item;
+ list.CopyTo(res, 1);
+ return res;
+ }
+
+ internal static T[] AddLast<T>(this IList<T> list, T item) {
+ T[] res = new T[list.Count + 1];
+ list.CopyTo(res, 0);
+ res[list.Count] = item;
+ return res;
+ }
+
+ internal static T First<T>(this IEnumerable<T> source) {
+ var list = source as IList<T>;
+ if (list != null) {
+ return list[0];
+ }
+ using (var e = source.GetEnumerator()) {
+ if (e.MoveNext()) return e.Current;
+ }
+ throw new InvalidOperationException();
+ }
+
+ internal static T Last<T>(this IList<T> list) {
+ return list[list.Count - 1];
+ }
+
+ internal static T[] Copy<T>(this T[] array) {
+ T[] copy = new T[array.Length];
+ Array.Copy(array, copy, array.Length);
+ return copy;
+ }
+ }
+
+
+ internal static class EmptyReadOnlyCollection<T> {
+ internal static ReadOnlyCollection<T> Instance = new TrueReadOnlyCollection<T>(new T[0]);
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ContractUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ContractUtils.cs
new file mode 100644
index 00000000000..2e09e18c7f2
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ContractUtils.cs
@@ -0,0 +1,107 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Diagnostics;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+
+ // Will be replaced with CLRv4 managed contracts
+ internal static class ContractUtils {
+
+ internal static Exception Unreachable {
+ get {
+ Debug.Assert(false, "Unreachable");
+ return new InvalidOperationException("Code supposed to be unreachable");
+ }
+ }
+
+ internal static void Requires(bool precondition) {
+ if (!precondition) {
+ throw new ArgumentException(Strings.MethodPreconditionViolated);
+ }
+ }
+
+ internal static void Requires(bool precondition, string paramName) {
+ Debug.Assert(!string.IsNullOrEmpty(paramName));
+
+ if (!precondition) {
+ throw new ArgumentException(Strings.InvalidArgumentValue, paramName);
+ }
+ }
+
+ internal static void Requires(bool precondition, string paramName, string message) {
+ Debug.Assert(!string.IsNullOrEmpty(paramName));
+
+ if (!precondition) {
+ throw new ArgumentException(message, paramName);
+ }
+ }
+
+ internal static void RequiresNotNull(object value, string paramName) {
+ Debug.Assert(!string.IsNullOrEmpty(paramName));
+
+ if (value == null) {
+ throw new ArgumentNullException(paramName);
+ }
+ }
+
+ internal static void RequiresNotEmpty<T>(ICollection<T> collection, string paramName) {
+ RequiresNotNull(collection, paramName);
+ if (collection.Count == 0) {
+ throw new ArgumentException(Strings.NonEmptyCollectionRequired, paramName);
+ }
+ }
+
+ /// <summary>
+ /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
+ /// </summary>
+ /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
+ internal static void RequiresArrayRange<T>(IList<T> array, int offset, int count, string offsetName, string countName) {
+ Debug.Assert(!string.IsNullOrEmpty(offsetName));
+ Debug.Assert(!string.IsNullOrEmpty(countName));
+ Debug.Assert(array != null);
+
+ if (count < 0) throw new ArgumentOutOfRangeException(countName);
+ if (offset < 0 || array.Count - offset < count) throw new ArgumentOutOfRangeException(offsetName);
+ }
+
+ /// <summary>
+ /// Requires the array and all its items to be non-null.
+ /// </summary>
+ internal static void RequiresNotNullItems<T>(IList<T> array, string arrayName) {
+ Debug.Assert(arrayName != null);
+ RequiresNotNull(array, arrayName);
+
+ for (int i = 0; i < array.Count; i++) {
+ if (array[i] == null) {
+ throw new ArgumentNullException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0}[{1}]", arrayName, i));
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ExceptionFactory.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ExceptionFactory.Generated.cs
new file mode 100644
index 00000000000..b08b49e68cc
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ExceptionFactory.Generated.cs
@@ -0,0 +1,2524 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Linq.Expressions {
+#endif
+
+ internal static partial class Strings {
+ private static string FormatString(string format, params object[] args) {
+ return string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args);
+ }
+ }
+
+ #region Generated Exception Factory
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_expr_factory_core from: generate_exception_factory.py
+
+ /// <summary>
+ /// Strongly-typed and parameterized string factory.
+ /// </summary>
+
+ internal static partial class Strings {
+ /// <summary>
+ /// A string like "Method precondition violated"
+ /// </summary>
+ internal static string MethodPreconditionViolated {
+ get {
+ return "Method precondition violated";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid argument value"
+ /// </summary>
+ internal static string InvalidArgumentValue {
+ get {
+ return "Invalid argument value";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Non-empty collection required"
+ /// </summary>
+ internal static string NonEmptyCollectionRequired {
+ get {
+ return "Non-empty collection required";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument count must be greater than number of named arguments."
+ /// </summary>
+ internal static string ArgCntMustBeGreaterThanNameCnt {
+ get {
+ return "Argument count must be greater than number of named arguments.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "reducible nodes must override Expression.Reduce()"
+ /// </summary>
+ internal static string ReducibleMustOverrideReduce {
+ get {
+ return "reducible nodes must override Expression.Reduce()";
+ }
+ }
+
+ /// <summary>
+ /// A string like "node cannot reduce to itself or null"
+ /// </summary>
+ internal static string MustReduceToDifferent {
+ get {
+ return "node cannot reduce to itself or null";
+ }
+ }
+
+ /// <summary>
+ /// A string like "cannot assign from the reduced node type to the original node type"
+ /// </summary>
+ internal static string ReducedNotCompatible {
+ get {
+ return "cannot assign from the reduced node type to the original node type";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Setter must have parameters."
+ /// </summary>
+ internal static string SetterHasNoParams {
+ get {
+ return "Setter must have parameters.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Property cannot have a managed pointer type."
+ /// </summary>
+ internal static string PropertyCannotHaveRefType {
+ get {
+ return "Property cannot have a managed pointer type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Indexing parameters of getter and setter must match."
+ /// </summary>
+ internal static string IndexesOfSetGetMustMatch {
+ get {
+ return "Indexing parameters of getter and setter must match.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Accessor method should not have VarArgs."
+ /// </summary>
+ internal static string AccessorsCannotHaveVarArgs {
+ get {
+ return "Accessor method should not have VarArgs.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Accessor indexes cannot be passed ByRef."
+ /// </summary>
+ internal static string AccessorsCannotHaveByRefArgs {
+ get {
+ return "Accessor indexes cannot be passed ByRef.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Bounds count cannot be less than 1"
+ /// </summary>
+ internal static string BoundsCannotBeLessThanOne {
+ get {
+ return "Bounds count cannot be less than 1";
+ }
+ }
+
+ /// <summary>
+ /// A string like "type must not be ByRef"
+ /// </summary>
+ internal static string TypeMustNotBeByRef {
+ get {
+ return "type must not be ByRef";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type doesn't have constructor with a given signature"
+ /// </summary>
+ internal static string TypeDoesNotHaveConstructorForTheSignature {
+ get {
+ return "Type doesn't have constructor with a given signature";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Count must be non-negative."
+ /// </summary>
+ internal static string CountCannotBeNegative {
+ get {
+ return "Count must be non-negative.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "arrayType must be an array type"
+ /// </summary>
+ internal static string ArrayTypeMustBeArray {
+ get {
+ return "arrayType must be an array type";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Setter should have void type."
+ /// </summary>
+ internal static string SetterMustBeVoid {
+ get {
+ return "Setter should have void type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Property type must match the value type of setter"
+ /// </summary>
+ internal static string PropertyTyepMustMatchSetter {
+ get {
+ return "Property type must match the value type of setter";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Both accessors must be static."
+ /// </summary>
+ internal static string BothAccessorsMustBeStatic {
+ get {
+ return "Both accessors must be static.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Static field requires null instance, non-static field requires non-null instance."
+ /// </summary>
+ internal static string OnlyStaticFieldsHaveNullInstance {
+ get {
+ return "Static field requires null instance, non-static field requires non-null instance.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Static property requires null instance, non-static property requires non-null instance."
+ /// </summary>
+ internal static string OnlyStaticPropertiesHaveNullInstance {
+ get {
+ return "Static property requires null instance, non-static property requires non-null instance.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Static method requires null instance, non-static method requires non-null instance."
+ /// </summary>
+ internal static string OnlyStaticMethodsHaveNullInstance {
+ get {
+ return "Static method requires null instance, non-static method requires non-null instance.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Property cannot have a void type."
+ /// </summary>
+ internal static string PropertyTypeCannotBeVoid {
+ get {
+ return "Property cannot have a void type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Can only unbox from an object or interface type to a value type."
+ /// </summary>
+ internal static string InvalidUnboxType {
+ get {
+ return "Can only unbox from an object or interface type to a value type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Expression must be readable"
+ /// </summary>
+ internal static string ExpressionMustBeReadable {
+ get {
+ return "Expression must be readable";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Expression must be writeable"
+ /// </summary>
+ internal static string ExpressionMustBeWriteable {
+ get {
+ return "Expression must be writeable";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must not have a value type."
+ /// </summary>
+ internal static string ArgumentMustNotHaveValueType {
+ get {
+ return "Argument must not have a value type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "must be reducible node"
+ /// </summary>
+ internal static string MustBeReducible {
+ get {
+ return "must be reducible node";
+ }
+ }
+
+ /// <summary>
+ /// A string like "All test values must have the same type."
+ /// </summary>
+ internal static string AllTestValuesMustHaveSameType {
+ get {
+ return "All test values must have the same type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "All case bodies and the default body must have the same type."
+ /// </summary>
+ internal static string AllCaseBodiesMustHaveSameType {
+ get {
+ return "All case bodies and the default body must have the same type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Default body must be supplied if case bodies are not System.Void."
+ /// </summary>
+ internal static string DefaultBodyMustBeSupplied {
+ get {
+ return "Default body must be supplied if case bodies are not System.Void.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "MethodBuilder does not have a valid TypeBuilder"
+ /// </summary>
+ internal static string MethodBuilderDoesNotHaveTypeBuilder {
+ get {
+ return "MethodBuilder does not have a valid TypeBuilder";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type must be derived from System.Delegate"
+ /// </summary>
+ internal static string TypeMustBeDerivedFromSystemDelegate {
+ get {
+ return "Type must be derived from System.Delegate";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument type cannot be void"
+ /// </summary>
+ internal static string ArgumentTypeCannotBeVoid {
+ get {
+ return "Argument type cannot be void";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Label type must be System.Void if an expression is not supplied"
+ /// </summary>
+ internal static string LabelMustBeVoidOrHaveExpression {
+ get {
+ return "Label type must be System.Void if an expression is not supplied";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type must be System.Void for this label argument"
+ /// </summary>
+ internal static string LabelTypeMustBeVoid {
+ get {
+ return "Type must be System.Void for this label argument";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Quoted expression must be a lambda"
+ /// </summary>
+ internal static string QuotedExpressionMustBeLambda {
+ get {
+ return "Quoted expression must be a lambda";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Variable '{0}' uses unsupported type '{1}'. Reference types are not supported for variables."
+ /// </summary>
+ internal static string VariableMustNotBeByRef(object p0, object p1) {
+ return FormatString("Variable '{0}' uses unsupported type '{1}'. Reference types are not supported for variables.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Found duplicate parameter '{0}'. Each ParameterExpression in the list must be a unique object."
+ /// </summary>
+ internal static string DuplicateVariable(object p0) {
+ return FormatString("Found duplicate parameter '{0}'. Each ParameterExpression in the list must be a unique object.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Start and End must be well ordered"
+ /// </summary>
+ internal static string StartEndMustBeOrdered {
+ get {
+ return "Start and End must be well ordered";
+ }
+ }
+
+ /// <summary>
+ /// A string like "fault cannot be used with catch or finally clauses"
+ /// </summary>
+ internal static string FaultCannotHaveCatchOrFinally {
+ get {
+ return "fault cannot be used with catch or finally clauses";
+ }
+ }
+
+ /// <summary>
+ /// A string like "try must have at least one catch, finally, or fault clause"
+ /// </summary>
+ internal static string TryMustHaveCatchFinallyOrFault {
+ get {
+ return "try must have at least one catch, finally, or fault clause";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Body of catch must have the same type as body of try."
+ /// </summary>
+ internal static string BodyOfCatchMustHaveSameTypeAsBodyOfTry {
+ get {
+ return "Body of catch must have the same type as body of try.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Extension node must override the property {0}."
+ /// </summary>
+ internal static string ExtensionNodeMustOverrideProperty(object p0) {
+ return FormatString("Extension node must override the property {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "User-defined operator method '{0}' must be static."
+ /// </summary>
+ internal static string UserDefinedOperatorMustBeStatic(object p0) {
+ return FormatString("User-defined operator method '{0}' must be static.", p0);
+ }
+
+ /// <summary>
+ /// A string like "User-defined operator method '{0}' must not be void."
+ /// </summary>
+ internal static string UserDefinedOperatorMustNotBeVoid(object p0) {
+ return FormatString("User-defined operator method '{0}' must not be void.", p0);
+ }
+
+ /// <summary>
+ /// A string like "No coercion operator is defined between types '{0}' and '{1}'."
+ /// </summary>
+ internal static string CoercionOperatorNotDefined(object p0, object p1) {
+ return FormatString("No coercion operator is defined between types '{0}' and '{1}'.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The result type '{0}' of the dynamic binding produced by binder '{1}' is not compatible with the result type '{2}' expected by the call site."
+ /// </summary>
+ internal static string DynamicBinderResultNotAssignable(object p0, object p1, object p2) {
+ return FormatString("The result type '{0}' of the dynamic binding produced by binder '{1}' is not compatible with the result type '{2}' expected by the call site.", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "The result type '{0}' of the dynamic binding produced by the object with type '{1}' for the binder '{2}' is not compatible with the result type '{3}' expected by the call site."
+ /// </summary>
+ internal static string DynamicObjectResultNotAssignable(object p0, object p1, object p2, object p3) {
+ return FormatString("The result type '{0}' of the dynamic binding produced by the object with type '{1}' for the binder '{2}' is not compatible with the result type '{3}' expected by the call site.", p0, p1, p2, p3);
+ }
+
+ /// <summary>
+ /// A string like "The result of the dynamic binding produced by the object with type '{0}' for the binder '{1}' needs at least one restriction."
+ /// </summary>
+ internal static string DynamicBindingNeedsRestrictions(object p0, object p1) {
+ return FormatString("The result of the dynamic binding produced by the object with type '{0}' for the binder '{1}' needs at least one restriction.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The result type '{0}' of the binder '{1}' is not compatible with the result type '{2}' expected by the call site."
+ /// </summary>
+ internal static string BinderNotCompatibleWithCallSite(object p0, object p1, object p2) {
+ return FormatString("The result type '{0}' of the binder '{1}' is not compatible with the result type '{2}' expected by the call site.", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "The unary operator {0} is not defined for the type '{1}'."
+ /// </summary>
+ internal static string UnaryOperatorNotDefined(object p0, object p1) {
+ return FormatString("The unary operator {0} is not defined for the type '{1}'.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The binary operator {0} is not defined for the types '{1}' and '{2}'."
+ /// </summary>
+ internal static string BinaryOperatorNotDefined(object p0, object p1, object p2) {
+ return FormatString("The binary operator {0} is not defined for the types '{1}' and '{2}'.", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Reference equality is not defined for the types '{0}' and '{1}'."
+ /// </summary>
+ internal static string ReferenceEqualityNotDefined(object p0, object p1) {
+ return FormatString("Reference equality is not defined for the types '{0}' and '{1}'.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The operands for operator '{0}' do not match the parameters of method '{1}'."
+ /// </summary>
+ internal static string OperandTypesDoNotMatchParameters(object p0, object p1) {
+ return FormatString("The operands for operator '{0}' do not match the parameters of method '{1}'.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The return type of overload method for operator '{0}' does not match the parameter type of conversion method '{1}'."
+ /// </summary>
+ internal static string OverloadOperatorTypeDoesNotMatchConversionType(object p0, object p1) {
+ return FormatString("The return type of overload method for operator '{0}' does not match the parameter type of conversion method '{1}'.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Conversion is not supported for arithmetic types without operator overloading."
+ /// </summary>
+ internal static string ConversionIsNotSupportedForArithmeticTypes {
+ get {
+ return "Conversion is not supported for arithmetic types without operator overloading.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must be array"
+ /// </summary>
+ internal static string ArgumentMustBeArray {
+ get {
+ return "Argument must be array";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must be boolean"
+ /// </summary>
+ internal static string ArgumentMustBeBoolean {
+ get {
+ return "Argument must be boolean";
+ }
+ }
+
+ /// <summary>
+ /// A string like "The user-defined equality method '{0}' must return a boolean value."
+ /// </summary>
+ internal static string EqualityMustReturnBoolean(object p0) {
+ return FormatString("The user-defined equality method '{0}' must return a boolean value.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Argument must be either a FieldInfo or PropertyInfo"
+ /// </summary>
+ internal static string ArgumentMustBeFieldInfoOrPropertInfo {
+ get {
+ return "Argument must be either a FieldInfo or PropertyInfo";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must be either a FieldInfo, PropertyInfo or MethodInfo"
+ /// </summary>
+ internal static string ArgumentMustBeFieldInfoOrPropertInfoOrMethod {
+ get {
+ return "Argument must be either a FieldInfo, PropertyInfo or MethodInfo";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must be an instance member"
+ /// </summary>
+ internal static string ArgumentMustBeInstanceMember {
+ get {
+ return "Argument must be an instance member";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must be of an integer type"
+ /// </summary>
+ internal static string ArgumentMustBeInteger {
+ get {
+ return "Argument must be of an integer type";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument for array index must be of type Int32"
+ /// </summary>
+ internal static string ArgumentMustBeArrayIndexType {
+ get {
+ return "Argument for array index must be of type Int32";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument must be single dimensional array type"
+ /// </summary>
+ internal static string ArgumentMustBeSingleDimensionalArrayType {
+ get {
+ return "Argument must be single dimensional array type";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument types do not match"
+ /// </summary>
+ internal static string ArgumentTypesMustMatch {
+ get {
+ return "Argument types do not match";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot auto initialize elements of value type through property '{0}', use assignment instead"
+ /// </summary>
+ internal static string CannotAutoInitializeValueTypeElementThroughProperty(object p0) {
+ return FormatString("Cannot auto initialize elements of value type through property '{0}', use assignment instead", p0);
+ }
+
+ /// <summary>
+ /// A string like "Cannot auto initialize members of value type through property '{0}', use assignment instead"
+ /// </summary>
+ internal static string CannotAutoInitializeValueTypeMemberThroughProperty(object p0) {
+ return FormatString("Cannot auto initialize members of value type through property '{0}', use assignment instead", p0);
+ }
+
+ /// <summary>
+ /// A string like "The type used in TypeAs Expression must be of reference or nullable type, {0} is neither"
+ /// </summary>
+ internal static string IncorrectTypeForTypeAs(object p0) {
+ return FormatString("The type used in TypeAs Expression must be of reference or nullable type, {0} is neither", p0);
+ }
+
+ /// <summary>
+ /// A string like "Coalesce used with type that cannot be null"
+ /// </summary>
+ internal static string CoalesceUsedOnNonNullType {
+ get {
+ return "Coalesce used with type that cannot be null";
+ }
+ }
+
+ /// <summary>
+ /// A string like "An expression of type '{0}' cannot be used to initialize an array of type '{1}'"
+ /// </summary>
+ internal static string ExpressionTypeCannotInitializeArrayType(object p0, object p1) {
+ return FormatString("An expression of type '{0}' cannot be used to initialize an array of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be used for constructor parameter of type '{1}'"
+ /// </summary>
+ internal static string ExpressionTypeDoesNotMatchConstructorParameter(object p0, object p1) {
+ return FormatString("Expression of type '{0}' cannot be used for constructor parameter of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like " Argument type '{0}' does not match the corresponding member type '{1}'"
+ /// </summary>
+ internal static string ArgumentTypeDoesNotMatchMember(object p0, object p1) {
+ return FormatString(" Argument type '{0}' does not match the corresponding member type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like " The member '{0}' is not declared on type '{1}' being created"
+ /// </summary>
+ internal static string ArgumentMemberNotDeclOnType(object p0, object p1) {
+ return FormatString(" The member '{0}' is not declared on type '{1}' being created", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be used for parameter of type '{1}' of method '{2}'"
+ /// </summary>
+ internal static string ExpressionTypeDoesNotMatchMethodParameter(object p0, object p1, object p2) {
+ return FormatString("Expression of type '{0}' cannot be used for parameter of type '{1}' of method '{2}'", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be used for parameter of type '{1}'"
+ /// </summary>
+ internal static string ExpressionTypeDoesNotMatchParameter(object p0, object p1) {
+ return FormatString("Expression of type '{0}' cannot be used for parameter of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be used for return type '{1}'"
+ /// </summary>
+ internal static string ExpressionTypeDoesNotMatchReturn(object p0, object p1) {
+ return FormatString("Expression of type '{0}' cannot be used for return type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be used for assignment to type '{1}'"
+ /// </summary>
+ internal static string ExpressionTypeDoesNotMatchAssignment(object p0, object p1) {
+ return FormatString("Expression of type '{0}' cannot be used for assignment to type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be used for label of type '{1}'"
+ /// </summary>
+ internal static string ExpressionTypeDoesNotMatchLabel(object p0, object p1) {
+ return FormatString("Expression of type '{0}' cannot be used for label of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Expression of type '{0}' cannot be invoked"
+ /// </summary>
+ internal static string ExpressionTypeNotInvocable(object p0) {
+ return FormatString("Expression of type '{0}' cannot be invoked", p0);
+ }
+
+ /// <summary>
+ /// A string like "Field '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static string FieldNotDefinedForType(object p0, object p1) {
+ return FormatString("Field '{0}' is not defined for type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Instance field '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static string InstanceFieldNotDefinedForType(object p0, object p1) {
+ return FormatString("Instance field '{0}' is not defined for type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Field '{0}.{1}' is not defined for type '{2}'"
+ /// </summary>
+ internal static string FieldInfoNotDefinedForType(object p0, object p1, object p2) {
+ return FormatString("Field '{0}.{1}' is not defined for type '{2}'", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Incorrect number of indexes"
+ /// </summary>
+ internal static string IncorrectNumberOfIndexes {
+ get {
+ return "Incorrect number of indexes";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Incorrect number of arguments supplied for lambda invocation"
+ /// </summary>
+ internal static string IncorrectNumberOfLambdaArguments {
+ get {
+ return "Incorrect number of arguments supplied for lambda invocation";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Incorrect number of parameters supplied for lambda declaration"
+ /// </summary>
+ internal static string IncorrectNumberOfLambdaDeclarationParameters {
+ get {
+ return "Incorrect number of parameters supplied for lambda declaration";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Incorrect number of arguments supplied for call to method '{0}'"
+ /// </summary>
+ internal static string IncorrectNumberOfMethodCallArguments(object p0) {
+ return FormatString("Incorrect number of arguments supplied for call to method '{0}'", p0);
+ }
+
+ /// <summary>
+ /// A string like "Incorrect number of arguments for constructor"
+ /// </summary>
+ internal static string IncorrectNumberOfConstructorArguments {
+ get {
+ return "Incorrect number of arguments for constructor";
+ }
+ }
+
+ /// <summary>
+ /// A string like " Incorrect number of members for constructor"
+ /// </summary>
+ internal static string IncorrectNumberOfMembersForGivenConstructor {
+ get {
+ return " Incorrect number of members for constructor";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Incorrect number of arguments for the given members "
+ /// </summary>
+ internal static string IncorrectNumberOfArgumentsForMembers {
+ get {
+ return "Incorrect number of arguments for the given members ";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Lambda type parameter must be derived from System.Delegate"
+ /// </summary>
+ internal static string LambdaTypeMustBeDerivedFromSystemDelegate {
+ get {
+ return "Lambda type parameter must be derived from System.Delegate";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Member '{0}' not field or property"
+ /// </summary>
+ internal static string MemberNotFieldOrProperty(object p0) {
+ return FormatString("Member '{0}' not field or property", p0);
+ }
+
+ /// <summary>
+ /// A string like "Method {0} contains generic parameters"
+ /// </summary>
+ internal static string MethodContainsGenericParameters(object p0) {
+ return FormatString("Method {0} contains generic parameters", p0);
+ }
+
+ /// <summary>
+ /// A string like "Method {0} is a generic method definition"
+ /// </summary>
+ internal static string MethodIsGeneric(object p0) {
+ return FormatString("Method {0} is a generic method definition", p0);
+ }
+
+ /// <summary>
+ /// A string like "The method '{0}.{1}' is not a property accessor"
+ /// </summary>
+ internal static string MethodNotPropertyAccessor(object p0, object p1) {
+ return FormatString("The method '{0}.{1}' is not a property accessor", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The property '{0}' has no 'get' accessor"
+ /// </summary>
+ internal static string PropertyDoesNotHaveGetter(object p0) {
+ return FormatString("The property '{0}' has no 'get' accessor", p0);
+ }
+
+ /// <summary>
+ /// A string like "The property '{0}' has no 'set' accessor"
+ /// </summary>
+ internal static string PropertyDoesNotHaveSetter(object p0) {
+ return FormatString("The property '{0}' has no 'set' accessor", p0);
+ }
+
+ /// <summary>
+ /// A string like "The property '{0}' has no 'get' or 'set' accessors"
+ /// </summary>
+ internal static string PropertyDoesNotHaveAccessor(object p0) {
+ return FormatString("The property '{0}' has no 'get' or 'set' accessors", p0);
+ }
+
+ /// <summary>
+ /// A string like "'{0}' is not a member of type '{1}'"
+ /// </summary>
+ internal static string NotAMemberOfType(object p0, object p1) {
+ return FormatString("'{0}' is not a member of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The operator '{0}' is not implemented for type '{1}'"
+ /// </summary>
+ internal static string OperatorNotImplementedForType(object p0, object p1) {
+ return FormatString("The operator '{0}' is not implemented for type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "ParameterExpression of type '{0}' cannot be used for delegate parameter of type '{1}'"
+ /// </summary>
+ internal static string ParameterExpressionNotValidAsDelegate(object p0, object p1) {
+ return FormatString("ParameterExpression of type '{0}' cannot be used for delegate parameter of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Property '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static string PropertyNotDefinedForType(object p0, object p1) {
+ return FormatString("Property '{0}' is not defined for type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Instance property '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static string InstancePropertyNotDefinedForType(object p0, object p1) {
+ return FormatString("Instance property '{0}' is not defined for type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Instance property '{0}' that takes no argument is not defined for type '{1}'"
+ /// </summary>
+ internal static string InstancePropertyWithoutParameterNotDefinedForType(object p0, object p1) {
+ return FormatString("Instance property '{0}' that takes no argument is not defined for type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Instance property '{0}{1}' is not defined for type '{2}'"
+ /// </summary>
+ internal static string InstancePropertyWithSpecifiedParametersNotDefinedForType(object p0, object p1, object p2) {
+ return FormatString("Instance property '{0}{1}' is not defined for type '{2}'", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Method '{0}' declared on type '{1}' cannot be called with instance of type '{2}'"
+ /// </summary>
+ internal static string InstanceAndMethodTypeMismatch(object p0, object p1, object p2) {
+ return FormatString("Method '{0}' declared on type '{1}' cannot be called with instance of type '{2}'", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Type {0} contains generic parameters"
+ /// </summary>
+ internal static string TypeContainsGenericParameters(object p0) {
+ return FormatString("Type {0} contains generic parameters", p0);
+ }
+
+ /// <summary>
+ /// A string like "Type {0} is a generic type definition"
+ /// </summary>
+ internal static string TypeIsGeneric(object p0) {
+ return FormatString("Type {0} is a generic type definition", p0);
+ }
+
+ /// <summary>
+ /// A string like "Type '{0}' does not have a default constructor"
+ /// </summary>
+ internal static string TypeMissingDefaultConstructor(object p0) {
+ return FormatString("Type '{0}' does not have a default constructor", p0);
+ }
+
+ /// <summary>
+ /// A string like "List initializers must contain at least one initializer"
+ /// </summary>
+ internal static string ListInitializerWithZeroMembers {
+ get {
+ return "List initializers must contain at least one initializer";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Element initializer method must be named 'Add'"
+ /// </summary>
+ internal static string ElementInitializerMethodNotAdd {
+ get {
+ return "Element initializer method must be named 'Add'";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Parameter '{0}' of element initializer method '{1}' must not be a pass by reference parameter"
+ /// </summary>
+ internal static string ElementInitializerMethodNoRefOutParam(object p0, object p1) {
+ return FormatString("Parameter '{0}' of element initializer method '{1}' must not be a pass by reference parameter", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Element initializer method must have at least 1 parameter"
+ /// </summary>
+ internal static string ElementInitializerMethodWithZeroArgs {
+ get {
+ return "Element initializer method must have at least 1 parameter";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Element initializer method must be an instance method"
+ /// </summary>
+ internal static string ElementInitializerMethodStatic {
+ get {
+ return "Element initializer method must be an instance method";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type '{0}' is not IEnumerable"
+ /// </summary>
+ internal static string TypeNotIEnumerable(object p0) {
+ return FormatString("Type '{0}' is not IEnumerable", p0);
+ }
+
+ /// <summary>
+ /// A string like "Type parameter is {0}. Expected a delegate."
+ /// </summary>
+ internal static string TypeParameterIsNotDelegate(object p0) {
+ return FormatString("Type parameter is {0}. Expected a delegate.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Unexpected coalesce operator."
+ /// </summary>
+ internal static string UnexpectedCoalesceOperator {
+ get {
+ return "Unexpected coalesce operator.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot cast from type '{0}' to type '{1}"
+ /// </summary>
+ internal static string InvalidCast(object p0, object p1) {
+ return FormatString("Cannot cast from type '{0}' to type '{1}", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Unhandled binary: {0}"
+ /// </summary>
+ internal static string UnhandledBinary(object p0) {
+ return FormatString("Unhandled binary: {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "Unhandled binding "
+ /// </summary>
+ internal static string UnhandledBinding {
+ get {
+ return "Unhandled binding ";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Unhandled Binding Type: {0}"
+ /// </summary>
+ internal static string UnhandledBindingType(object p0) {
+ return FormatString("Unhandled Binding Type: {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "Unhandled convert: {0}"
+ /// </summary>
+ internal static string UnhandledConvert(object p0) {
+ return FormatString("Unhandled convert: {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "Unhandled Expression Type: {0}"
+ /// </summary>
+ internal static string UnhandledExpressionType(object p0) {
+ return FormatString("Unhandled Expression Type: {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "Unhandled unary: {0}"
+ /// </summary>
+ internal static string UnhandledUnary(object p0) {
+ return FormatString("Unhandled unary: {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "Unknown binding type"
+ /// </summary>
+ internal static string UnknownBindingType {
+ get {
+ return "Unknown binding type";
+ }
+ }
+
+ /// <summary>
+ /// A string like "The user-defined operator method '{1}' for operator '{0}' must have identical parameter and return types."
+ /// </summary>
+ internal static string UserDefinedOpMustHaveConsistentTypes(object p0, object p1) {
+ return FormatString("The user-defined operator method '{1}' for operator '{0}' must have identical parameter and return types.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The user-defined operator method '{1}' for operator '{0}' must return the same type as its parameter or a derived type."
+ /// </summary>
+ internal static string UserDefinedOpMustHaveValidReturnType(object p0, object p1) {
+ return FormatString("The user-defined operator method '{1}' for operator '{0}' must return the same type as its parameter or a derived type.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The user-defined operator method '{1}' for operator '{0}' must have associated boolean True and False operators."
+ /// </summary>
+ internal static string LogicalOperatorMustHaveBooleanOperators(object p0, object p1) {
+ return FormatString("The user-defined operator method '{1}' for operator '{0}' must have associated boolean True and False operators.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "No method '{0}' exists on type '{1}'."
+ /// </summary>
+ internal static string MethodDoesNotExistOnType(object p0, object p1) {
+ return FormatString("No method '{0}' exists on type '{1}'.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "No method '{0}' on type '{1}' is compatible with the supplied arguments."
+ /// </summary>
+ internal static string MethodWithArgsDoesNotExistOnType(object p0, object p1) {
+ return FormatString("No method '{0}' on type '{1}' is compatible with the supplied arguments.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "No generic method '{0}' on type '{1}' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic. "
+ /// </summary>
+ internal static string GenericMethodWithArgsDoesNotExistOnType(object p0, object p1) {
+ return FormatString("No generic method '{0}' on type '{1}' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic. ", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "More than one method '{0}' on type '{1}' is compatible with the supplied arguments."
+ /// </summary>
+ internal static string MethodWithMoreThanOneMatch(object p0, object p1) {
+ return FormatString("More than one method '{0}' on type '{1}' is compatible with the supplied arguments.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "More than one property '{0}' on type '{1}' is compatible with the supplied arguments."
+ /// </summary>
+ internal static string PropertyWithMoreThanOneMatch(object p0, object p1) {
+ return FormatString("More than one property '{0}' on type '{1}' is compatible with the supplied arguments.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "An incorrect number of type args were specified for the declaration of a Func type."
+ /// </summary>
+ internal static string IncorrectNumberOfTypeArgsForFunc {
+ get {
+ return "An incorrect number of type args were specified for the declaration of a Func type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "An incorrect number of type args were specified for the declaration of an Action type."
+ /// </summary>
+ internal static string IncorrectNumberOfTypeArgsForAction {
+ get {
+ return "An incorrect number of type args were specified for the declaration of an Action type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Argument type cannot be System.Void."
+ /// </summary>
+ internal static string ArgumentCannotBeOfTypeVoid {
+ get {
+ return "Argument type cannot be System.Void.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "More than one key matching '{0}' was found in the ExpandoObject."
+ /// </summary>
+ internal static string AmbiguousMatchInExpandoObject(object p0) {
+ return FormatString("More than one key matching '{0}' was found in the ExpandoObject.", p0);
+ }
+
+ /// <summary>
+ /// A string like "An element with the same key '{0}' already exists in the ExpandoObject."
+ /// </summary>
+ internal static string SameKeyExistsInExpando(object p0) {
+ return FormatString("An element with the same key '{0}' already exists in the ExpandoObject.", p0);
+ }
+
+ /// <summary>
+ /// A string like "The specified key '{0}' does not exist in the ExpandoObject."
+ /// </summary>
+ internal static string KeyDoesNotExistInExpando(object p0) {
+ return FormatString("The specified key '{0}' does not exist in the ExpandoObject.", p0);
+ }
+
+ /// <summary>
+ /// A string like "No or Invalid rule produced"
+ /// </summary>
+ internal static string NoOrInvalidRuleProduced {
+ get {
+ return "No or Invalid rule produced";
+ }
+ }
+
+ /// <summary>
+ /// A string like "First argument of delegate must be CallSite"
+ /// </summary>
+ internal static string FirstArgumentMustBeCallSite {
+ get {
+ return "First argument of delegate must be CallSite";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Bind cannot return null."
+ /// </summary>
+ internal static string BindingCannotBeNull {
+ get {
+ return "Bind cannot return null.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid operation: '{0}'"
+ /// </summary>
+ internal static string InvalidOperation(object p0) {
+ return FormatString("Invalid operation: '{0}'", p0);
+ }
+
+ /// <summary>
+ /// A string like "{0} must be greater than or equal to {1}"
+ /// </summary>
+ internal static string OutOfRange(object p0, object p1) {
+ return FormatString("{0} must be greater than or equal to {1}", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Queue empty."
+ /// </summary>
+ internal static string QueueEmpty {
+ get {
+ return "Queue empty.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot redefine label '{0}' in an inner block."
+ /// </summary>
+ internal static string LabelTargetAlreadyDefined(object p0) {
+ return FormatString("Cannot redefine label '{0}' in an inner block.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Cannot jump to undefined label '{0}'."
+ /// </summary>
+ internal static string LabelTargetUndefined(object p0) {
+ return FormatString("Cannot jump to undefined label '{0}'.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Control cannot leave a finally block."
+ /// </summary>
+ internal static string ControlCannotLeaveFinally {
+ get {
+ return "Control cannot leave a finally block.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Control cannot leave a filter test."
+ /// </summary>
+ internal static string ControlCannotLeaveFilterTest {
+ get {
+ return "Control cannot leave a filter test.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot jump to ambiguous label '{0}'."
+ /// </summary>
+ internal static string AmbiguousJump(object p0) {
+ return FormatString("Cannot jump to ambiguous label '{0}'.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Control cannot enter a try block."
+ /// </summary>
+ internal static string ControlCannotEnterTry {
+ get {
+ return "Control cannot enter a try block.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Control cannot enter an expression--only statements can be jumped into."
+ /// </summary>
+ internal static string ControlCannotEnterExpression {
+ get {
+ return "Control cannot enter an expression--only statements can be jumped into.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot jump to non-local label '{0}' with a value. Only jumps to labels defined in outer blocks can pass values."
+ /// </summary>
+ internal static string NonLocalJumpWithValue(object p0) {
+ return FormatString("Cannot jump to non-local label '{0}' with a value. Only jumps to labels defined in outer blocks can pass values.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Extension should have been reduced."
+ /// </summary>
+ internal static string ExtensionNotReduced {
+ get {
+ return "Extension should have been reduced.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "CompileToMethod cannot compile constant '{0}' because it is a non-trivial value, such as a live object. Instead, create an expression tree that can construct this value."
+ /// </summary>
+ internal static string CannotCompileConstant(object p0) {
+ return FormatString("CompileToMethod cannot compile constant '{0}' because it is a non-trivial value, such as a live object. Instead, create an expression tree that can construct this value.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Dynamic expressions are not supported by CompileToMethod. Instead, create an expression tree that uses System.Runtime.CompilerServices.CallSite."
+ /// </summary>
+ internal static string CannotCompileDynamic {
+ get {
+ return "Dynamic expressions are not supported by CompileToMethod. Instead, create an expression tree that uses System.Runtime.CompilerServices.CallSite.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid lvalue for assignment: {0}."
+ /// </summary>
+ internal static string InvalidLvalue(object p0) {
+ return FormatString("Invalid lvalue for assignment: {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Invalid member type: {0}."
+ /// </summary>
+ internal static string InvalidMemberType(object p0) {
+ return FormatString("Invalid member type: {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "unknown lift type: '{0}'."
+ /// </summary>
+ internal static string UnknownLiftType(object p0) {
+ return FormatString("unknown lift type: '{0}'.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Invalid output directory."
+ /// </summary>
+ internal static string InvalidOutputDir {
+ get {
+ return "Invalid output directory.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid assembly name or file extension."
+ /// </summary>
+ internal static string InvalidAsmNameOrExtension {
+ get {
+ return "Invalid assembly name or file extension.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Collection is read-only."
+ /// </summary>
+ internal static string CollectionReadOnly {
+ get {
+ return "Collection is read-only.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot create instance of {0} because it contains generic parameters"
+ /// </summary>
+ internal static string IllegalNewGenericParams(object p0) {
+ return FormatString("Cannot create instance of {0} because it contains generic parameters", p0);
+ }
+
+ /// <summary>
+ /// A string like "variable '{0}' of type '{1}' referenced from scope '{2}', but it is not defined"
+ /// </summary>
+ internal static string UndefinedVariable(object p0, object p1, object p2) {
+ return FormatString("variable '{0}' of type '{1}' referenced from scope '{2}', but it is not defined", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Cannot close over byref parameter '{0}' referenced in lambda '{1}'"
+ /// </summary>
+ internal static string CannotCloseOverByRef(object p0, object p1) {
+ return FormatString("Cannot close over byref parameter '{0}' referenced in lambda '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Unexpected VarArgs call to method '{0}'"
+ /// </summary>
+ internal static string UnexpectedVarArgsCall(object p0) {
+ return FormatString("Unexpected VarArgs call to method '{0}'", p0);
+ }
+
+ /// <summary>
+ /// A string like "Rethrow statement is valid only inside a Catch block."
+ /// </summary>
+ internal static string RethrowRequiresCatch {
+ get {
+ return "Rethrow statement is valid only inside a Catch block.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Try expression is not allowed inside a filter body."
+ /// </summary>
+ internal static string TryNotAllowedInFilter {
+ get {
+ return "Try expression is not allowed inside a filter body.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "When called from '{0}', rewriting a node of type '{1}' must return a non-null value of the same type. Alternatively, override '{2}' and change it to not visit children of this type."
+ /// </summary>
+ internal static string MustRewriteToSameNode(object p0, object p1, object p2) {
+ return FormatString("When called from '{0}', rewriting a node of type '{1}' must return a non-null value of the same type. Alternatively, override '{2}' and change it to not visit children of this type.", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Rewriting child expression from type '{0}' to type '{1}' is not allowed, because it would change the meaning of the operation. If this is intentional, override '{2}' and change it to allow this rewrite."
+ /// </summary>
+ internal static string MustRewriteChildToSameType(object p0, object p1, object p2) {
+ return FormatString("Rewriting child expression from type '{0}' to type '{1}' is not allowed, because it would change the meaning of the operation. If this is intentional, override '{2}' and change it to allow this rewrite.", p0, p1, p2);
+ }
+
+ /// <summary>
+ /// A string like "Rewritten expression calls operator method '{0}', but the original node had no operator method. If this is is intentional, override '{1}' and change it to allow this rewrite."
+ /// </summary>
+ internal static string MustRewriteWithoutMethod(object p0, object p1) {
+ return FormatString("Rewritten expression calls operator method '{0}', but the original node had no operator method. If this is is intentional, override '{1}' and change it to allow this rewrite.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "The value null is not of type '{0}' and cannot be used in this collection."
+ /// </summary>
+ internal static string InvalidNullValue(object p0) {
+ return FormatString("The value null is not of type '{0}' and cannot be used in this collection.", p0);
+ }
+
+ /// <summary>
+ /// A string like "The value '{0}' is not of type '{1}' and cannot be used in this collection."
+ /// </summary>
+ internal static string InvalidObjectType(object p0, object p1) {
+ return FormatString("The value '{0}' is not of type '{1}' and cannot be used in this collection.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "TryExpression is not supported as an argument to method '{0}' because it has an argument with by-ref type. Construct the tree so the TryExpression is not nested inside of this expression."
+ /// </summary>
+ internal static string TryNotSupportedForMethodsWithRefArgs(object p0) {
+ return FormatString("TryExpression is not supported as an argument to method '{0}' because it has an argument with by-ref type. Construct the tree so the TryExpression is not nested inside of this expression.", p0);
+ }
+
+ /// <summary>
+ /// A string like "TryExpression is not supported as a child expression when accessing a member on type '{0}' because it is a value type. Construct the tree so the TryExpression is not nested inside of this expression."
+ /// </summary>
+ internal static string TryNotSupportedForValueTypeInstances(object p0) {
+ return FormatString("TryExpression is not supported as a child expression when accessing a member on type '{0}' because it is a value type. Construct the tree so the TryExpression is not nested inside of this expression.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Collection was modified; enumeration operation may not execute."
+ /// </summary>
+ internal static string CollectionModifiedWhileEnumerating {
+ get {
+ return "Collection was modified; enumeration operation may not execute.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Enumeration has either not started or has already finished."
+ /// </summary>
+ internal static string EnumerationIsDone {
+ get {
+ return "Enumeration has either not started or has already finished.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Dynamic operations can only be performed in homogenous AppDomain."
+ /// </summary>
+ internal static string HomogenousAppDomainRequired {
+ get {
+ return "Dynamic operations can only be performed in homogenous AppDomain.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Test value of type '{0}' cannot be used for the comparison method parameter of type '{1}'"
+ /// </summary>
+ internal static string TestValueTypeDoesNotMatchComparisonMethodParameter(object p0, object p1) {
+ return FormatString("Test value of type '{0}' cannot be used for the comparison method parameter of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Switch value of type '{0}' cannot be used for the comparison method parameter of type '{1}'"
+ /// </summary>
+ internal static string SwitchValueTypeDoesNotMatchComparisonMethodParameter(object p0, object p1) {
+ return FormatString("Switch value of type '{0}' cannot be used for the comparison method parameter of type '{1}'", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "An IDynamicMetaObjectProvider {0} created an invalid DynamicMetaObject instance."
+ /// </summary>
+ internal static string InvalidMetaObjectCreated(object p0) {
+ return FormatString("An IDynamicMetaObjectProvider {0} created an invalid DynamicMetaObject instance.", p0);
+ }
+
+ }
+ /// <summary>
+ /// Strongly-typed and parameterized exception factory.
+ /// </summary>
+
+ internal static partial class Error {
+ /// <summary>
+ /// ArgumentException with message like "Variable '{0}' uses unsupported type '{1}'. Reference types are not supported for variables."
+ /// </summary>
+ internal static Exception VariableMustNotBeByRef(object p0, object p1) {
+ return new ArgumentException(Strings.VariableMustNotBeByRef(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Found duplicate parameter '{0}'. Each ParameterExpression in the list must be a unique object."
+ /// </summary>
+ internal static Exception DuplicateVariable(object p0) {
+ return new ArgumentException(Strings.DuplicateVariable(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Start and End must be well ordered"
+ /// </summary>
+ internal static Exception StartEndMustBeOrdered() {
+ return new ArgumentException(Strings.StartEndMustBeOrdered);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "fault cannot be used with catch or finally clauses"
+ /// </summary>
+ internal static Exception FaultCannotHaveCatchOrFinally() {
+ return new ArgumentException(Strings.FaultCannotHaveCatchOrFinally);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "try must have at least one catch, finally, or fault clause"
+ /// </summary>
+ internal static Exception TryMustHaveCatchFinallyOrFault() {
+ return new ArgumentException(Strings.TryMustHaveCatchFinallyOrFault);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Body of catch must have the same type as body of try."
+ /// </summary>
+ internal static Exception BodyOfCatchMustHaveSameTypeAsBodyOfTry() {
+ return new ArgumentException(Strings.BodyOfCatchMustHaveSameTypeAsBodyOfTry);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Extension node must override the property {0}."
+ /// </summary>
+ internal static Exception ExtensionNodeMustOverrideProperty(object p0) {
+ return new InvalidOperationException(Strings.ExtensionNodeMustOverrideProperty(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "User-defined operator method '{0}' must be static."
+ /// </summary>
+ internal static Exception UserDefinedOperatorMustBeStatic(object p0) {
+ return new ArgumentException(Strings.UserDefinedOperatorMustBeStatic(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "User-defined operator method '{0}' must not be void."
+ /// </summary>
+ internal static Exception UserDefinedOperatorMustNotBeVoid(object p0) {
+ return new ArgumentException(Strings.UserDefinedOperatorMustNotBeVoid(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No coercion operator is defined between types '{0}' and '{1}'."
+ /// </summary>
+ internal static Exception CoercionOperatorNotDefined(object p0, object p1) {
+ return new InvalidOperationException(Strings.CoercionOperatorNotDefined(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidCastException with message like "The result type '{0}' of the dynamic binding produced by binder '{1}' is not compatible with the result type '{2}' expected by the call site."
+ /// </summary>
+ internal static Exception DynamicBinderResultNotAssignable(object p0, object p1, object p2) {
+ return new InvalidCastException(Strings.DynamicBinderResultNotAssignable(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// InvalidCastException with message like "The result type '{0}' of the dynamic binding produced by the object with type '{1}' for the binder '{2}' is not compatible with the result type '{3}' expected by the call site."
+ /// </summary>
+ internal static Exception DynamicObjectResultNotAssignable(object p0, object p1, object p2, object p3) {
+ return new InvalidCastException(Strings.DynamicObjectResultNotAssignable(p0, p1, p2, p3));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "The result of the dynamic binding produced by the object with type '{0}' for the binder '{1}' needs at least one restriction."
+ /// </summary>
+ internal static Exception DynamicBindingNeedsRestrictions(object p0, object p1) {
+ return new InvalidOperationException(Strings.DynamicBindingNeedsRestrictions(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "The result type '{0}' of the binder '{1}' is not compatible with the result type '{2}' expected by the call site."
+ /// </summary>
+ internal static Exception BinderNotCompatibleWithCallSite(object p0, object p1, object p2) {
+ return new InvalidOperationException(Strings.BinderNotCompatibleWithCallSite(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "The unary operator {0} is not defined for the type '{1}'."
+ /// </summary>
+ internal static Exception UnaryOperatorNotDefined(object p0, object p1) {
+ return new InvalidOperationException(Strings.UnaryOperatorNotDefined(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "The binary operator {0} is not defined for the types '{1}' and '{2}'."
+ /// </summary>
+ internal static Exception BinaryOperatorNotDefined(object p0, object p1, object p2) {
+ return new InvalidOperationException(Strings.BinaryOperatorNotDefined(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Reference equality is not defined for the types '{0}' and '{1}'."
+ /// </summary>
+ internal static Exception ReferenceEqualityNotDefined(object p0, object p1) {
+ return new InvalidOperationException(Strings.ReferenceEqualityNotDefined(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "The operands for operator '{0}' do not match the parameters of method '{1}'."
+ /// </summary>
+ internal static Exception OperandTypesDoNotMatchParameters(object p0, object p1) {
+ return new InvalidOperationException(Strings.OperandTypesDoNotMatchParameters(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "The return type of overload method for operator '{0}' does not match the parameter type of conversion method '{1}'."
+ /// </summary>
+ internal static Exception OverloadOperatorTypeDoesNotMatchConversionType(object p0, object p1) {
+ return new InvalidOperationException(Strings.OverloadOperatorTypeDoesNotMatchConversionType(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Conversion is not supported for arithmetic types without operator overloading."
+ /// </summary>
+ internal static Exception ConversionIsNotSupportedForArithmeticTypes() {
+ return new InvalidOperationException(Strings.ConversionIsNotSupportedForArithmeticTypes);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be array"
+ /// </summary>
+ internal static Exception ArgumentMustBeArray() {
+ return new ArgumentException(Strings.ArgumentMustBeArray);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be boolean"
+ /// </summary>
+ internal static Exception ArgumentMustBeBoolean() {
+ return new ArgumentException(Strings.ArgumentMustBeBoolean);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The user-defined equality method '{0}' must return a boolean value."
+ /// </summary>
+ internal static Exception EqualityMustReturnBoolean(object p0) {
+ return new ArgumentException(Strings.EqualityMustReturnBoolean(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be either a FieldInfo or PropertyInfo"
+ /// </summary>
+ internal static Exception ArgumentMustBeFieldInfoOrPropertInfo() {
+ return new ArgumentException(Strings.ArgumentMustBeFieldInfoOrPropertInfo);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be either a FieldInfo, PropertyInfo or MethodInfo"
+ /// </summary>
+ internal static Exception ArgumentMustBeFieldInfoOrPropertInfoOrMethod() {
+ return new ArgumentException(Strings.ArgumentMustBeFieldInfoOrPropertInfoOrMethod);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be an instance member"
+ /// </summary>
+ internal static Exception ArgumentMustBeInstanceMember() {
+ return new ArgumentException(Strings.ArgumentMustBeInstanceMember);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be of an integer type"
+ /// </summary>
+ internal static Exception ArgumentMustBeInteger() {
+ return new ArgumentException(Strings.ArgumentMustBeInteger);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument for array index must be of type Int32"
+ /// </summary>
+ internal static Exception ArgumentMustBeArrayIndexType() {
+ return new ArgumentException(Strings.ArgumentMustBeArrayIndexType);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument must be single dimensional array type"
+ /// </summary>
+ internal static Exception ArgumentMustBeSingleDimensionalArrayType() {
+ return new ArgumentException(Strings.ArgumentMustBeSingleDimensionalArrayType);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument types do not match"
+ /// </summary>
+ internal static Exception ArgumentTypesMustMatch() {
+ return new ArgumentException(Strings.ArgumentTypesMustMatch);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot auto initialize elements of value type through property '{0}', use assignment instead"
+ /// </summary>
+ internal static Exception CannotAutoInitializeValueTypeElementThroughProperty(object p0) {
+ return new InvalidOperationException(Strings.CannotAutoInitializeValueTypeElementThroughProperty(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot auto initialize members of value type through property '{0}', use assignment instead"
+ /// </summary>
+ internal static Exception CannotAutoInitializeValueTypeMemberThroughProperty(object p0) {
+ return new InvalidOperationException(Strings.CannotAutoInitializeValueTypeMemberThroughProperty(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The type used in TypeAs Expression must be of reference or nullable type, {0} is neither"
+ /// </summary>
+ internal static Exception IncorrectTypeForTypeAs(object p0) {
+ return new ArgumentException(Strings.IncorrectTypeForTypeAs(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Coalesce used with type that cannot be null"
+ /// </summary>
+ internal static Exception CoalesceUsedOnNonNullType() {
+ return new InvalidOperationException(Strings.CoalesceUsedOnNonNullType);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "An expression of type '{0}' cannot be used to initialize an array of type '{1}'"
+ /// </summary>
+ internal static Exception ExpressionTypeCannotInitializeArrayType(object p0, object p1) {
+ return new InvalidOperationException(Strings.ExpressionTypeCannotInitializeArrayType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be used for constructor parameter of type '{1}'"
+ /// </summary>
+ internal static Exception ExpressionTypeDoesNotMatchConstructorParameter(object p0, object p1) {
+ return new ArgumentException(Strings.ExpressionTypeDoesNotMatchConstructorParameter(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like " Argument type '{0}' does not match the corresponding member type '{1}'"
+ /// </summary>
+ internal static Exception ArgumentTypeDoesNotMatchMember(object p0, object p1) {
+ return new ArgumentException(Strings.ArgumentTypeDoesNotMatchMember(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like " The member '{0}' is not declared on type '{1}' being created"
+ /// </summary>
+ internal static Exception ArgumentMemberNotDeclOnType(object p0, object p1) {
+ return new ArgumentException(Strings.ArgumentMemberNotDeclOnType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be used for parameter of type '{1}' of method '{2}'"
+ /// </summary>
+ internal static Exception ExpressionTypeDoesNotMatchMethodParameter(object p0, object p1, object p2) {
+ return new ArgumentException(Strings.ExpressionTypeDoesNotMatchMethodParameter(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be used for parameter of type '{1}'"
+ /// </summary>
+ internal static Exception ExpressionTypeDoesNotMatchParameter(object p0, object p1) {
+ return new ArgumentException(Strings.ExpressionTypeDoesNotMatchParameter(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be used for return type '{1}'"
+ /// </summary>
+ internal static Exception ExpressionTypeDoesNotMatchReturn(object p0, object p1) {
+ return new ArgumentException(Strings.ExpressionTypeDoesNotMatchReturn(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be used for assignment to type '{1}'"
+ /// </summary>
+ internal static Exception ExpressionTypeDoesNotMatchAssignment(object p0, object p1) {
+ return new ArgumentException(Strings.ExpressionTypeDoesNotMatchAssignment(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be used for label of type '{1}'"
+ /// </summary>
+ internal static Exception ExpressionTypeDoesNotMatchLabel(object p0, object p1) {
+ return new ArgumentException(Strings.ExpressionTypeDoesNotMatchLabel(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expression of type '{0}' cannot be invoked"
+ /// </summary>
+ internal static Exception ExpressionTypeNotInvocable(object p0) {
+ return new ArgumentException(Strings.ExpressionTypeNotInvocable(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Field '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static Exception FieldNotDefinedForType(object p0, object p1) {
+ return new ArgumentException(Strings.FieldNotDefinedForType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Instance field '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static Exception InstanceFieldNotDefinedForType(object p0, object p1) {
+ return new ArgumentException(Strings.InstanceFieldNotDefinedForType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Field '{0}.{1}' is not defined for type '{2}'"
+ /// </summary>
+ internal static Exception FieldInfoNotDefinedForType(object p0, object p1, object p2) {
+ return new ArgumentException(Strings.FieldInfoNotDefinedForType(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Incorrect number of indexes"
+ /// </summary>
+ internal static Exception IncorrectNumberOfIndexes() {
+ return new ArgumentException(Strings.IncorrectNumberOfIndexes);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Incorrect number of arguments supplied for lambda invocation"
+ /// </summary>
+ internal static Exception IncorrectNumberOfLambdaArguments() {
+ return new InvalidOperationException(Strings.IncorrectNumberOfLambdaArguments);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Incorrect number of parameters supplied for lambda declaration"
+ /// </summary>
+ internal static Exception IncorrectNumberOfLambdaDeclarationParameters() {
+ return new ArgumentException(Strings.IncorrectNumberOfLambdaDeclarationParameters);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Incorrect number of arguments supplied for call to method '{0}'"
+ /// </summary>
+ internal static Exception IncorrectNumberOfMethodCallArguments(object p0) {
+ return new ArgumentException(Strings.IncorrectNumberOfMethodCallArguments(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Incorrect number of arguments for constructor"
+ /// </summary>
+ internal static Exception IncorrectNumberOfConstructorArguments() {
+ return new ArgumentException(Strings.IncorrectNumberOfConstructorArguments);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like " Incorrect number of members for constructor"
+ /// </summary>
+ internal static Exception IncorrectNumberOfMembersForGivenConstructor() {
+ return new ArgumentException(Strings.IncorrectNumberOfMembersForGivenConstructor);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Incorrect number of arguments for the given members "
+ /// </summary>
+ internal static Exception IncorrectNumberOfArgumentsForMembers() {
+ return new ArgumentException(Strings.IncorrectNumberOfArgumentsForMembers);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Lambda type parameter must be derived from System.Delegate"
+ /// </summary>
+ internal static Exception LambdaTypeMustBeDerivedFromSystemDelegate() {
+ return new ArgumentException(Strings.LambdaTypeMustBeDerivedFromSystemDelegate);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Member '{0}' not field or property"
+ /// </summary>
+ internal static Exception MemberNotFieldOrProperty(object p0) {
+ return new ArgumentException(Strings.MemberNotFieldOrProperty(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Method {0} contains generic parameters"
+ /// </summary>
+ internal static Exception MethodContainsGenericParameters(object p0) {
+ return new ArgumentException(Strings.MethodContainsGenericParameters(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Method {0} is a generic method definition"
+ /// </summary>
+ internal static Exception MethodIsGeneric(object p0) {
+ return new ArgumentException(Strings.MethodIsGeneric(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The method '{0}.{1}' is not a property accessor"
+ /// </summary>
+ internal static Exception MethodNotPropertyAccessor(object p0, object p1) {
+ return new ArgumentException(Strings.MethodNotPropertyAccessor(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The property '{0}' has no 'get' accessor"
+ /// </summary>
+ internal static Exception PropertyDoesNotHaveGetter(object p0) {
+ return new ArgumentException(Strings.PropertyDoesNotHaveGetter(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The property '{0}' has no 'set' accessor"
+ /// </summary>
+ internal static Exception PropertyDoesNotHaveSetter(object p0) {
+ return new ArgumentException(Strings.PropertyDoesNotHaveSetter(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The property '{0}' has no 'get' or 'set' accessors"
+ /// </summary>
+ internal static Exception PropertyDoesNotHaveAccessor(object p0) {
+ return new ArgumentException(Strings.PropertyDoesNotHaveAccessor(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "'{0}' is not a member of type '{1}'"
+ /// </summary>
+ internal static Exception NotAMemberOfType(object p0, object p1) {
+ return new ArgumentException(Strings.NotAMemberOfType(p0, p1));
+ }
+
+ /// <summary>
+ /// NotImplementedException with message like "The operator '{0}' is not implemented for type '{1}'"
+ /// </summary>
+ internal static Exception OperatorNotImplementedForType(object p0, object p1) {
+ return new NotImplementedException(Strings.OperatorNotImplementedForType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "ParameterExpression of type '{0}' cannot be used for delegate parameter of type '{1}'"
+ /// </summary>
+ internal static Exception ParameterExpressionNotValidAsDelegate(object p0, object p1) {
+ return new ArgumentException(Strings.ParameterExpressionNotValidAsDelegate(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Property '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static Exception PropertyNotDefinedForType(object p0, object p1) {
+ return new ArgumentException(Strings.PropertyNotDefinedForType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Instance property '{0}' is not defined for type '{1}'"
+ /// </summary>
+ internal static Exception InstancePropertyNotDefinedForType(object p0, object p1) {
+ return new ArgumentException(Strings.InstancePropertyNotDefinedForType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Instance property '{0}' that takes no argument is not defined for type '{1}'"
+ /// </summary>
+ internal static Exception InstancePropertyWithoutParameterNotDefinedForType(object p0, object p1) {
+ return new ArgumentException(Strings.InstancePropertyWithoutParameterNotDefinedForType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Instance property '{0}{1}' is not defined for type '{2}'"
+ /// </summary>
+ internal static Exception InstancePropertyWithSpecifiedParametersNotDefinedForType(object p0, object p1, object p2) {
+ return new ArgumentException(Strings.InstancePropertyWithSpecifiedParametersNotDefinedForType(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Method '{0}' declared on type '{1}' cannot be called with instance of type '{2}'"
+ /// </summary>
+ internal static Exception InstanceAndMethodTypeMismatch(object p0, object p1, object p2) {
+ return new ArgumentException(Strings.InstanceAndMethodTypeMismatch(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Type {0} contains generic parameters"
+ /// </summary>
+ internal static Exception TypeContainsGenericParameters(object p0) {
+ return new ArgumentException(Strings.TypeContainsGenericParameters(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Type {0} is a generic type definition"
+ /// </summary>
+ internal static Exception TypeIsGeneric(object p0) {
+ return new ArgumentException(Strings.TypeIsGeneric(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Type '{0}' does not have a default constructor"
+ /// </summary>
+ internal static Exception TypeMissingDefaultConstructor(object p0) {
+ return new ArgumentException(Strings.TypeMissingDefaultConstructor(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "List initializers must contain at least one initializer"
+ /// </summary>
+ internal static Exception ListInitializerWithZeroMembers() {
+ return new ArgumentException(Strings.ListInitializerWithZeroMembers);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Element initializer method must be named 'Add'"
+ /// </summary>
+ internal static Exception ElementInitializerMethodNotAdd() {
+ return new ArgumentException(Strings.ElementInitializerMethodNotAdd);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Parameter '{0}' of element initializer method '{1}' must not be a pass by reference parameter"
+ /// </summary>
+ internal static Exception ElementInitializerMethodNoRefOutParam(object p0, object p1) {
+ return new ArgumentException(Strings.ElementInitializerMethodNoRefOutParam(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Element initializer method must have at least 1 parameter"
+ /// </summary>
+ internal static Exception ElementInitializerMethodWithZeroArgs() {
+ return new ArgumentException(Strings.ElementInitializerMethodWithZeroArgs);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Element initializer method must be an instance method"
+ /// </summary>
+ internal static Exception ElementInitializerMethodStatic() {
+ return new ArgumentException(Strings.ElementInitializerMethodStatic);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Type '{0}' is not IEnumerable"
+ /// </summary>
+ internal static Exception TypeNotIEnumerable(object p0) {
+ return new ArgumentException(Strings.TypeNotIEnumerable(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Type parameter is {0}. Expected a delegate."
+ /// </summary>
+ internal static Exception TypeParameterIsNotDelegate(object p0) {
+ return new InvalidOperationException(Strings.TypeParameterIsNotDelegate(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Unexpected coalesce operator."
+ /// </summary>
+ internal static Exception UnexpectedCoalesceOperator() {
+ return new InvalidOperationException(Strings.UnexpectedCoalesceOperator);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot cast from type '{0}' to type '{1}"
+ /// </summary>
+ internal static Exception InvalidCast(object p0, object p1) {
+ return new InvalidOperationException(Strings.InvalidCast(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled binary: {0}"
+ /// </summary>
+ internal static Exception UnhandledBinary(object p0) {
+ return new ArgumentException(Strings.UnhandledBinary(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled binding "
+ /// </summary>
+ internal static Exception UnhandledBinding() {
+ return new ArgumentException(Strings.UnhandledBinding);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled Binding Type: {0}"
+ /// </summary>
+ internal static Exception UnhandledBindingType(object p0) {
+ return new ArgumentException(Strings.UnhandledBindingType(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled convert: {0}"
+ /// </summary>
+ internal static Exception UnhandledConvert(object p0) {
+ return new ArgumentException(Strings.UnhandledConvert(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled Expression Type: {0}"
+ /// </summary>
+ internal static Exception UnhandledExpressionType(object p0) {
+ return new ArgumentException(Strings.UnhandledExpressionType(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled unary: {0}"
+ /// </summary>
+ internal static Exception UnhandledUnary(object p0) {
+ return new ArgumentException(Strings.UnhandledUnary(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unknown binding type"
+ /// </summary>
+ internal static Exception UnknownBindingType() {
+ return new ArgumentException(Strings.UnknownBindingType);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The user-defined operator method '{1}' for operator '{0}' must have identical parameter and return types."
+ /// </summary>
+ internal static Exception UserDefinedOpMustHaveConsistentTypes(object p0, object p1) {
+ return new ArgumentException(Strings.UserDefinedOpMustHaveConsistentTypes(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The user-defined operator method '{1}' for operator '{0}' must return the same type as its parameter or a derived type."
+ /// </summary>
+ internal static Exception UserDefinedOpMustHaveValidReturnType(object p0, object p1) {
+ return new ArgumentException(Strings.UserDefinedOpMustHaveValidReturnType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The user-defined operator method '{1}' for operator '{0}' must have associated boolean True and False operators."
+ /// </summary>
+ internal static Exception LogicalOperatorMustHaveBooleanOperators(object p0, object p1) {
+ return new ArgumentException(Strings.LogicalOperatorMustHaveBooleanOperators(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No method '{0}' exists on type '{1}'."
+ /// </summary>
+ internal static Exception MethodDoesNotExistOnType(object p0, object p1) {
+ return new InvalidOperationException(Strings.MethodDoesNotExistOnType(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No method '{0}' on type '{1}' is compatible with the supplied arguments."
+ /// </summary>
+ internal static Exception MethodWithArgsDoesNotExistOnType(object p0, object p1) {
+ return new InvalidOperationException(Strings.MethodWithArgsDoesNotExistOnType(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No generic method '{0}' on type '{1}' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic. "
+ /// </summary>
+ internal static Exception GenericMethodWithArgsDoesNotExistOnType(object p0, object p1) {
+ return new InvalidOperationException(Strings.GenericMethodWithArgsDoesNotExistOnType(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "More than one method '{0}' on type '{1}' is compatible with the supplied arguments."
+ /// </summary>
+ internal static Exception MethodWithMoreThanOneMatch(object p0, object p1) {
+ return new InvalidOperationException(Strings.MethodWithMoreThanOneMatch(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "More than one property '{0}' on type '{1}' is compatible with the supplied arguments."
+ /// </summary>
+ internal static Exception PropertyWithMoreThanOneMatch(object p0, object p1) {
+ return new InvalidOperationException(Strings.PropertyWithMoreThanOneMatch(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "An incorrect number of type args were specified for the declaration of a Func type."
+ /// </summary>
+ internal static Exception IncorrectNumberOfTypeArgsForFunc() {
+ return new ArgumentException(Strings.IncorrectNumberOfTypeArgsForFunc);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "An incorrect number of type args were specified for the declaration of an Action type."
+ /// </summary>
+ internal static Exception IncorrectNumberOfTypeArgsForAction() {
+ return new ArgumentException(Strings.IncorrectNumberOfTypeArgsForAction);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Argument type cannot be System.Void."
+ /// </summary>
+ internal static Exception ArgumentCannotBeOfTypeVoid() {
+ return new ArgumentException(Strings.ArgumentCannotBeOfTypeVoid);
+ }
+
+ /// <summary>
+ /// System.Reflection.AmbiguousMatchException with message like "More than one key matching '{0}' was found in the ExpandoObject."
+ /// </summary>
+ internal static Exception AmbiguousMatchInExpandoObject(object p0) {
+ return new System.Reflection.AmbiguousMatchException(Strings.AmbiguousMatchInExpandoObject(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "An element with the same key '{0}' already exists in the ExpandoObject."
+ /// </summary>
+ internal static Exception SameKeyExistsInExpando(object p0) {
+ return new ArgumentException(Strings.SameKeyExistsInExpando(p0));
+ }
+
+ /// <summary>
+ /// System.Collections.Generic.KeyNotFoundException with message like "The specified key '{0}' does not exist in the ExpandoObject."
+ /// </summary>
+ internal static Exception KeyDoesNotExistInExpando(object p0) {
+ return new System.Collections.Generic.KeyNotFoundException(Strings.KeyDoesNotExistInExpando(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No or Invalid rule produced"
+ /// </summary>
+ internal static Exception NoOrInvalidRuleProduced() {
+ return new InvalidOperationException(Strings.NoOrInvalidRuleProduced);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "First argument of delegate must be CallSite"
+ /// </summary>
+ internal static Exception FirstArgumentMustBeCallSite() {
+ return new ArgumentException(Strings.FirstArgumentMustBeCallSite);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Bind cannot return null."
+ /// </summary>
+ internal static Exception BindingCannotBeNull() {
+ return new InvalidOperationException(Strings.BindingCannotBeNull);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid operation: '{0}'"
+ /// </summary>
+ internal static Exception InvalidOperation(object p0) {
+ return new ArgumentException(Strings.InvalidOperation(p0));
+ }
+
+ /// <summary>
+ /// ArgumentOutOfRangeException with message like "{0} must be greater than or equal to {1}"
+ /// </summary>
+ internal static Exception OutOfRange(object p0, object p1) {
+ return new ArgumentOutOfRangeException(Strings.OutOfRange(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Queue empty."
+ /// </summary>
+ internal static Exception QueueEmpty() {
+ return new InvalidOperationException(Strings.QueueEmpty);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot redefine label '{0}' in an inner block."
+ /// </summary>
+ internal static Exception LabelTargetAlreadyDefined(object p0) {
+ return new InvalidOperationException(Strings.LabelTargetAlreadyDefined(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot jump to undefined label '{0}'."
+ /// </summary>
+ internal static Exception LabelTargetUndefined(object p0) {
+ return new InvalidOperationException(Strings.LabelTargetUndefined(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Control cannot leave a finally block."
+ /// </summary>
+ internal static Exception ControlCannotLeaveFinally() {
+ return new InvalidOperationException(Strings.ControlCannotLeaveFinally);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Control cannot leave a filter test."
+ /// </summary>
+ internal static Exception ControlCannotLeaveFilterTest() {
+ return new InvalidOperationException(Strings.ControlCannotLeaveFilterTest);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot jump to ambiguous label '{0}'."
+ /// </summary>
+ internal static Exception AmbiguousJump(object p0) {
+ return new InvalidOperationException(Strings.AmbiguousJump(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Control cannot enter a try block."
+ /// </summary>
+ internal static Exception ControlCannotEnterTry() {
+ return new InvalidOperationException(Strings.ControlCannotEnterTry);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Control cannot enter an expression--only statements can be jumped into."
+ /// </summary>
+ internal static Exception ControlCannotEnterExpression() {
+ return new InvalidOperationException(Strings.ControlCannotEnterExpression);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot jump to non-local label '{0}' with a value. Only jumps to labels defined in outer blocks can pass values."
+ /// </summary>
+ internal static Exception NonLocalJumpWithValue(object p0) {
+ return new InvalidOperationException(Strings.NonLocalJumpWithValue(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Extension should have been reduced."
+ /// </summary>
+ internal static Exception ExtensionNotReduced() {
+ return new InvalidOperationException(Strings.ExtensionNotReduced);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "CompileToMethod cannot compile constant '{0}' because it is a non-trivial value, such as a live object. Instead, create an expression tree that can construct this value."
+ /// </summary>
+ internal static Exception CannotCompileConstant(object p0) {
+ return new InvalidOperationException(Strings.CannotCompileConstant(p0));
+ }
+
+ /// <summary>
+ /// NotSupportedException with message like "Dynamic expressions are not supported by CompileToMethod. Instead, create an expression tree that uses System.Runtime.CompilerServices.CallSite."
+ /// </summary>
+ internal static Exception CannotCompileDynamic() {
+ return new NotSupportedException(Strings.CannotCompileDynamic);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Invalid lvalue for assignment: {0}."
+ /// </summary>
+ internal static Exception InvalidLvalue(object p0) {
+ return new InvalidOperationException(Strings.InvalidLvalue(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Invalid member type: {0}."
+ /// </summary>
+ internal static Exception InvalidMemberType(object p0) {
+ return new InvalidOperationException(Strings.InvalidMemberType(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "unknown lift type: '{0}'."
+ /// </summary>
+ internal static Exception UnknownLiftType(object p0) {
+ return new InvalidOperationException(Strings.UnknownLiftType(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid output directory."
+ /// </summary>
+ internal static Exception InvalidOutputDir() {
+ return new ArgumentException(Strings.InvalidOutputDir);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid assembly name or file extension."
+ /// </summary>
+ internal static Exception InvalidAsmNameOrExtension() {
+ return new ArgumentException(Strings.InvalidAsmNameOrExtension);
+ }
+
+ /// <summary>
+ /// NotSupportedException with message like "Collection is read-only."
+ /// </summary>
+ internal static Exception CollectionReadOnly() {
+ return new NotSupportedException(Strings.CollectionReadOnly);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Cannot create instance of {0} because it contains generic parameters"
+ /// </summary>
+ internal static Exception IllegalNewGenericParams(object p0) {
+ return new ArgumentException(Strings.IllegalNewGenericParams(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "variable '{0}' of type '{1}' referenced from scope '{2}', but it is not defined"
+ /// </summary>
+ internal static Exception UndefinedVariable(object p0, object p1, object p2) {
+ return new InvalidOperationException(Strings.UndefinedVariable(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Cannot close over byref parameter '{0}' referenced in lambda '{1}'"
+ /// </summary>
+ internal static Exception CannotCloseOverByRef(object p0, object p1) {
+ return new InvalidOperationException(Strings.CannotCloseOverByRef(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Unexpected VarArgs call to method '{0}'"
+ /// </summary>
+ internal static Exception UnexpectedVarArgsCall(object p0) {
+ return new InvalidOperationException(Strings.UnexpectedVarArgsCall(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Rethrow statement is valid only inside a Catch block."
+ /// </summary>
+ internal static Exception RethrowRequiresCatch() {
+ return new InvalidOperationException(Strings.RethrowRequiresCatch);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Try expression is not allowed inside a filter body."
+ /// </summary>
+ internal static Exception TryNotAllowedInFilter() {
+ return new InvalidOperationException(Strings.TryNotAllowedInFilter);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "When called from '{0}', rewriting a node of type '{1}' must return a non-null value of the same type. Alternatively, override '{2}' and change it to not visit children of this type."
+ /// </summary>
+ internal static Exception MustRewriteToSameNode(object p0, object p1, object p2) {
+ return new InvalidOperationException(Strings.MustRewriteToSameNode(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Rewriting child expression from type '{0}' to type '{1}' is not allowed, because it would change the meaning of the operation. If this is intentional, override '{2}' and change it to allow this rewrite."
+ /// </summary>
+ internal static Exception MustRewriteChildToSameType(object p0, object p1, object p2) {
+ return new InvalidOperationException(Strings.MustRewriteChildToSameType(p0, p1, p2));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Rewritten expression calls operator method '{0}', but the original node had no operator method. If this is is intentional, override '{1}' and change it to allow this rewrite."
+ /// </summary>
+ internal static Exception MustRewriteWithoutMethod(object p0, object p1) {
+ return new InvalidOperationException(Strings.MustRewriteWithoutMethod(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentNullException with message like "The value null is not of type '{0}' and cannot be used in this collection."
+ /// </summary>
+ internal static Exception InvalidNullValue(object p0) {
+ return new ArgumentNullException(Strings.InvalidNullValue(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "The value '{0}' is not of type '{1}' and cannot be used in this collection."
+ /// </summary>
+ internal static Exception InvalidObjectType(object p0, object p1) {
+ return new ArgumentException(Strings.InvalidObjectType(p0, p1));
+ }
+
+ /// <summary>
+ /// NotSupportedException with message like "TryExpression is not supported as an argument to method '{0}' because it has an argument with by-ref type. Construct the tree so the TryExpression is not nested inside of this expression."
+ /// </summary>
+ internal static Exception TryNotSupportedForMethodsWithRefArgs(object p0) {
+ return new NotSupportedException(Strings.TryNotSupportedForMethodsWithRefArgs(p0));
+ }
+
+ /// <summary>
+ /// NotSupportedException with message like "TryExpression is not supported as a child expression when accessing a member on type '{0}' because it is a value type. Construct the tree so the TryExpression is not nested inside of this expression."
+ /// </summary>
+ internal static Exception TryNotSupportedForValueTypeInstances(object p0) {
+ return new NotSupportedException(Strings.TryNotSupportedForValueTypeInstances(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Collection was modified; enumeration operation may not execute."
+ /// </summary>
+ internal static Exception CollectionModifiedWhileEnumerating() {
+ return new InvalidOperationException(Strings.CollectionModifiedWhileEnumerating);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Enumeration has either not started or has already finished."
+ /// </summary>
+ internal static Exception EnumerationIsDone() {
+ return new InvalidOperationException(Strings.EnumerationIsDone);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Dynamic operations can only be performed in homogenous AppDomain."
+ /// </summary>
+ internal static Exception HomogenousAppDomainRequired() {
+ return new InvalidOperationException(Strings.HomogenousAppDomainRequired);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Test value of type '{0}' cannot be used for the comparison method parameter of type '{1}'"
+ /// </summary>
+ internal static Exception TestValueTypeDoesNotMatchComparisonMethodParameter(object p0, object p1) {
+ return new ArgumentException(Strings.TestValueTypeDoesNotMatchComparisonMethodParameter(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Switch value of type '{0}' cannot be used for the comparison method parameter of type '{1}'"
+ /// </summary>
+ internal static Exception SwitchValueTypeDoesNotMatchComparisonMethodParameter(object p0, object p1) {
+ return new ArgumentException(Strings.SwitchValueTypeDoesNotMatchComparisonMethodParameter(p0, p1));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "An IDynamicMetaObjectProvider {0} created an invalid DynamicMetaObject instance."
+ /// </summary>
+ internal static Exception InvalidMetaObjectCreated(object p0) {
+ return new InvalidOperationException(Strings.InvalidMetaObjectCreated(p0));
+ }
+
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Extension.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Extension.cs
new file mode 100644
index 00000000000..f42f7a8516a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Extension.cs
@@ -0,0 +1,14 @@
+#if CODEPLEX_40
+using System;
+#else
+using System; using Microsoft;
+#endif
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Indicates that a method is an extension method, or that a class or assembly contains extension methods.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
+ public sealed class ExtensionAttribute : Attribute { }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Function.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Function.cs
new file mode 100644
index 00000000000..be68a4f7145
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Function.cs
@@ -0,0 +1,711 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+namespace System {
+#else
+namespace Microsoft {
+#endif
+
+ #if MICROSOFT_SCRIPTING_CORE
+
+ /// <summary>
+ /// Encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ public delegate TResult Func<TResult>();
+
+ /// <summary>
+ /// Encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg">The first parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ public delegate TResult Func<T, TResult>(T arg);
+
+ #endif
+
+ #region Generated Func Types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_func_types from: generate_dynsites.py
+
+#if MICROSOFT_SCRIPTING_CORE
+
+ /// <summary>
+ /// Encapsulates a method that has two parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
+
+ /// <summary>
+ /// Encapsulates a method that has three parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
+
+ /// <summary>
+ /// Encapsulates a method that has four parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+
+ /// <summary>
+ /// Encapsulates a method that has five parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+
+ /// <summary>
+ /// Encapsulates a method that has six parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
+
+ /// <summary>
+ /// Encapsulates a method that has seven parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
+
+ /// <summary>
+ /// Encapsulates a method that has eight parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
+
+ /// <summary>
+ /// Encapsulates a method that has nine parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
+
+ /// <summary>
+ /// Encapsulates a method that has ten parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
+
+ /// <summary>
+ /// Encapsulates a method that has eleven parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
+
+ /// <summary>
+ /// Encapsulates a method that has twelve parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
+
+ /// <summary>
+ /// Encapsulates a method that has thirteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13);
+
+ /// <summary>
+ /// Encapsulates a method that has fourteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
+
+ /// <summary>
+ /// Encapsulates a method that has fifteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
+
+ /// <summary>
+ /// Encapsulates a method that has sixteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T16">The type of the sixteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg16">The sixteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
+#else
+
+ /// <summary>
+ /// Encapsulates a method that has nine parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
+
+ /// <summary>
+ /// Encapsulates a method that has ten parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
+
+ /// <summary>
+ /// Encapsulates a method that has eleven parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
+
+ /// <summary>
+ /// Encapsulates a method that has twelve parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
+
+ /// <summary>
+ /// Encapsulates a method that has thirteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13);
+
+ /// <summary>
+ /// Encapsulates a method that has fourteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
+
+ /// <summary>
+ /// Encapsulates a method that has fifteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
+
+ /// <summary>
+ /// Encapsulates a method that has sixteen parameters and returns a value of the type specified by the TResult parameter.
+ /// </summary>
+ /// <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T9">The type of the ninth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="T16">The type of the sixteenth parameter of the method that this delegate encapsulates.</typeparam>
+ /// <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+ /// <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg9">The ninth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+ /// <param name="arg16">The sixteenth parameter of the method that this delegate encapsulates.</param>
+ /// <returns>The return value of the method that this delegate encapsulates.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
+
+#endif
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Helpers.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Helpers.cs
new file mode 100644
index 00000000000..ec62bed8ba4
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/Helpers.cs
@@ -0,0 +1,57 @@
+
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+ // Miscellaneous helpers that don't belong anywhere else
+ internal static class Helpers {
+
+ internal static T CommonNode<T>(T first, T second, Func<T, T> parent) where T : class {
+ var cmp = EqualityComparer<T>.Default;
+ if (cmp.Equals(first, second)) {
+ return first;
+ }
+ var set = new Set<T>(cmp);
+ for (T t = first; t != null; t = parent(t)) {
+ set.Add(t);
+ }
+ for (T t = second; t != null; t = parent(t)) {
+ if (set.Contains(t)) {
+ return t;
+ }
+ }
+ return null;
+ }
+
+ internal static void IncrementCount<T>(T key, Dictionary<T, int> dict) {
+ int count;
+ dict.TryGetValue(key, out count);
+ dict[key] = count + 1;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/IRuntimeVariables.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/IRuntimeVariables.cs
new file mode 100644
index 00000000000..72abfe2a0c9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/IRuntimeVariables.cs
@@ -0,0 +1,39 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// An interface to represent values of runtime variables.
+ /// </summary>
+ public interface IRuntimeVariables {
+ /// <summary>
+ /// Count of the variables.
+ /// </summary>
+ int Count { get; }
+
+ /// <summary>
+ /// An indexer to get/set the values of the runtime variables.
+ /// </summary>
+ /// <param name="index">An index of the runtime variable.</param>
+ /// <returns>The value of the runtime variable.</returns>
+ object this[int index] { get; set; }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyCollectionBuilder.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyCollectionBuilder.cs
new file mode 100644
index 00000000000..e9c24a93bf9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyCollectionBuilder.cs
@@ -0,0 +1,525 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Utils;
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ /// <summary>
+ /// The builder for read only collection.
+ /// </summary>
+ /// <typeparam name="T">The type of the collection element.</typeparam>
+ [Serializable]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
+ public sealed class ReadOnlyCollectionBuilder<T> : IList<T>, System.Collections.IList {
+ private const int DefaultCapacity = 4;
+
+ private T[] _items;
+ private int _size;
+ private int _version;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ static readonly T[] _emptyArray = new T[0];
+
+ /// <summary>
+ /// Constructs a ReadOnlyCollectionBuilder.
+ /// </summary>
+ public ReadOnlyCollectionBuilder() {
+ _items = _emptyArray;
+ }
+
+ /// <summary>
+ /// Constructs a ReadOnlyCollectionBuilder with a given initial capacity.
+ /// The contents are empty but builder will have reserved room for the given
+ /// number of elements before any reallocations are required.
+ /// </summary>
+ public ReadOnlyCollectionBuilder(int capacity) {
+ ContractUtils.Requires(capacity >= 0, "capacity");
+ _items = new T[capacity];
+ }
+
+ /// <summary>
+ /// Constructs a ReadOnlyCollectionBuilder, copying contents of the given collection.
+ /// </summary>
+ /// <param name="collection"></param>
+ public ReadOnlyCollectionBuilder(IEnumerable<T> collection) {
+ ContractUtils.Requires(collection != null, "collection");
+
+ ICollection<T> c = collection as ICollection<T>;
+ if (c != null) {
+ int count = c.Count;
+ _items = new T[count];
+ c.CopyTo(_items, 0);
+ _size = count;
+ } else {
+ _size = 0;
+ _items = new T[DefaultCapacity];
+
+ using (IEnumerator<T> en = collection.GetEnumerator()) {
+ while (en.MoveNext()) {
+ Add(en.Current);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets and sets the capacity of this ReadOnlyCollectionBuilder
+ /// </summary>
+ public int Capacity {
+ get { return _items.Length; }
+ set {
+ ContractUtils.Requires(value >= _size, "value");
+
+ if (value != _items.Length) {
+ if (value > 0) {
+ T[] newItems = new T[value];
+ if (_size > 0) {
+ Array.Copy(_items, 0, newItems, 0, _size);
+ }
+ _items = newItems;
+ } else {
+ _items = _emptyArray;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns number of elements in the ReadOnlyCollectionBuilder.
+ /// </summary>
+ public int Count {
+ get { return _size; }
+ }
+
+ #region IList<T> Members
+
+ /// <summary>
+ /// Returns the index of the first occurrence of a given value in the builder.
+ /// </summary>
+ /// <param name="item">An item to search for.</param>
+ /// <returns>The index of the first occurrence of an item.</returns>
+ public int IndexOf(T item) {
+ return Array.IndexOf(_items, item, 0, _size);
+ }
+
+ /// <summary>
+ /// Inserts an item to the <see cref="ReadOnlyCollectionBuilder{T}"/> at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index at which item should be inserted.</param>
+ /// <param name="item">The object to insert into the <see cref="ReadOnlyCollectionBuilder{T}"/>.</param>
+ public void Insert(int index, T item) {
+ ContractUtils.Requires(index <= _size, "index");
+
+ if (_size == _items.Length) {
+ EnsureCapacity(_size + 1);
+ }
+ if (index < _size) {
+ Array.Copy(_items, index, _items, index + 1, _size - index);
+ }
+ _items[index] = item;
+ _size++;
+ _version++;
+ }
+
+ /// <summary>
+ /// Removes the <see cref="ReadOnlyCollectionBuilder{T}"/> item at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the item to remove.</param>
+ public void RemoveAt(int index) {
+ ContractUtils.Requires(index >= 0 && index < _size, "index");
+
+ _size--;
+ if (index < _size) {
+ Array.Copy(_items, index + 1, _items, index, _size - index);
+ }
+ _items[_size] = default(T);
+ _version++;
+ }
+
+ /// <summary>
+ /// Gets or sets the element at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the element to get or set.</param>
+ /// <returns>The element at the specified index.</returns>
+ public T this[int index] {
+ get {
+ ContractUtils.Requires(index < _size, "index");
+ return _items[index];
+ }
+ set {
+ ContractUtils.Requires(index < _size, "index");
+ _items[index] = value;
+ _version++;
+ }
+ }
+
+ #endregion
+
+ #region ICollection<T> Members
+
+ /// <summary>
+ /// Adds an item to the <see cref="ReadOnlyCollectionBuilder{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see cref="ReadOnlyCollectionBuilder{T}"/>.</param>
+ public void Add(T item) {
+ if (_size == _items.Length) {
+ EnsureCapacity(_size + 1);
+ }
+ _items[_size++] = item;
+ _version++;
+ }
+
+ /// <summary>
+ /// Removes all items from the <see cref="ReadOnlyCollectionBuilder{T}"/>.
+ /// </summary>
+ public void Clear() {
+ if (_size > 0) {
+ Array.Clear(_items, 0, _size);
+ _size = 0;
+ }
+ _version++;
+ }
+
+ /// <summary>
+ /// Determines whether the <see cref="ReadOnlyCollectionBuilder{T}"/> contains a specific value
+ /// </summary>
+ /// <param name="item">the object to locate in the <see cref="ReadOnlyCollectionBuilder{T}"/>.</param>
+ /// <returns>true if item is found in the <see cref="ReadOnlyCollectionBuilder{T}"/>; otherwise, false.</returns>
+ public bool Contains(T item) {
+ if ((Object)item == null) {
+ for (int i = 0; i < _size; i++) {
+ if ((Object)_items[i] == null) {
+ return true;
+ }
+ }
+ return false;
+ } else {
+ EqualityComparer<T> c = EqualityComparer<T>.Default;
+ for (int i = 0; i < _size; i++) {
+ if (c.Equals(_items[i], item)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="ReadOnlyCollectionBuilder{T}"/> to an <see cref="Array"/>,
+ /// starting at particular <see cref="Array"/> index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ReadOnlyCollectionBuilder{T}"/>.</param>
+ /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
+ public void CopyTo(T[] array, int arrayIndex) {
+ Array.Copy(_items, 0, array, arrayIndex, _size);
+ }
+
+ bool ICollection<T>.IsReadOnly {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Removes the first occurrence of a specific object from the <see cref="ReadOnlyCollectionBuilder{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to remove from the <see cref="ReadOnlyCollectionBuilder{T}"/>.</param>
+ /// <returns>true if item was successfully removed from the <see cref="ReadOnlyCollectionBuilder{T}"/>;
+ /// otherwise, false. This method also returns false if item is not found in the original <see cref="ReadOnlyCollectionBuilder{T}"/>.
+ /// </returns>
+ public bool Remove(T item) {
+ int index = IndexOf(item);
+ if (index >= 0) {
+ RemoveAt(index);
+ return true;
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ #region IEnumerable<T> Members
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the collection.
+ /// </summary>
+ /// <returns>A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.</returns>
+ public IEnumerator<T> GetEnumerator() {
+ return new Enumerator(this);
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ #endregion
+
+ #region IList Members
+
+ bool System.Collections.IList.IsReadOnly {
+ get { return false; }
+ }
+
+ int System.Collections.IList.Add(object value) {
+ ValidateNullValue(value, "value");
+ try {
+ Add((T)value);
+ } catch (InvalidCastException) {
+ ThrowInvalidTypeException(value, "value");
+ }
+ return Count - 1;
+ }
+
+ bool System.Collections.IList.Contains(object value) {
+ if (IsCompatibleObject(value)) {
+ return Contains((T)value);
+ } else return false;
+ }
+
+ int System.Collections.IList.IndexOf(object value) {
+ if (IsCompatibleObject(value)) {
+ return IndexOf((T)value);
+ }
+ return -1;
+ }
+
+ void System.Collections.IList.Insert(int index, object value) {
+ ValidateNullValue(value, "value");
+ try {
+ Insert(index, (T)value);
+ } catch (InvalidCastException) {
+ ThrowInvalidTypeException(value, "value");
+ }
+ }
+
+ bool System.Collections.IList.IsFixedSize {
+ get { return false; }
+ }
+
+ void System.Collections.IList.Remove(object value) {
+ if (IsCompatibleObject(value)) {
+ Remove((T)value);
+ }
+ }
+
+ object System.Collections.IList.this[int index] {
+ get {
+ return this[index];
+ }
+ set {
+ ValidateNullValue(value, "value");
+
+ try {
+ this[index] = (T)value;
+ } catch (InvalidCastException) {
+ ThrowInvalidTypeException(value, "value");
+ }
+ }
+ }
+
+ #endregion
+
+ #region ICollection Members
+
+ void System.Collections.ICollection.CopyTo(Array array, int index) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.Requires(array.Rank == 1, "array");
+ Array.Copy(_items, 0, array, index, _size);
+ }
+
+ bool System.Collections.ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object System.Collections.ICollection.SyncRoot {
+ get {
+ if (_syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Reverses the order of the elements in the entire <see cref="ReadOnlyCollectionBuilder{T}"/>.
+ /// </summary>
+ public void Reverse() {
+ Reverse(0, Count);
+ }
+
+ /// <summary>
+ /// Reverses the order of the elements in the specified range.
+ /// </summary>
+ /// <param name="index">The zero-based starting index of the range to reverse.</param>
+ /// <param name="count">The number of elements in the range to reverse.</param>
+ public void Reverse(int index, int count) {
+ ContractUtils.Requires(index >= 0, "index");
+ ContractUtils.Requires(count >= 0, "count");
+
+ Array.Reverse(_items, index, count);
+ _version++;
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="ReadOnlyCollectionBuilder{T}"/> to a new array.
+ /// </summary>
+ /// <returns>An array containing copies of the elements of the <see cref="ReadOnlyCollectionBuilder{T}"/>.</returns>
+ public T[] ToArray() {
+ T[] array = new T[_size];
+ Array.Copy(_items, 0, array, 0, _size);
+ return array;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="ReadOnlyCollection{T}"/> containing all of the the elements of the <see cref="ReadOnlyCollectionBuilder{T}"/>,
+ /// avoiding copying the elements to the new array if possible. Resets the <see cref="ReadOnlyCollectionBuilder{T}"/> after the
+ /// <see cref="ReadOnlyCollection{T}"/> has been created.
+ /// </summary>
+ /// <returns>A new instance of <see cref="ReadOnlyCollection{T}"/>.</returns>
+ public ReadOnlyCollection<T> ToReadOnlyCollection() {
+ // Can we use the stored array?
+ T[] items;
+ if (_size == _items.Length) {
+ items = _items;
+ } else {
+ items = ToArray();
+ }
+ _items = _emptyArray;
+ _size = 0;
+ _version++;
+
+ return new TrueReadOnlyCollection<T>(items);
+ }
+
+ private void EnsureCapacity(int min) {
+ if (_items.Length < min) {
+ int newCapacity = DefaultCapacity;
+ if (_items.Length > 0) {
+ newCapacity = _items.Length * 2;
+ }
+ if (newCapacity < min) {
+ newCapacity = min;
+ }
+ Capacity = newCapacity;
+ }
+ }
+
+ private static bool IsCompatibleObject(object value) {
+ return ((value is T) || (value == null && default(T) == null));
+ }
+
+ private static void ValidateNullValue(object value, string argument) {
+ if (value == null && !(default(T) == null)) {
+ throw new ArgumentException(Strings.InvalidNullValue(typeof(T)), argument);
+ }
+ }
+
+ private static void ThrowInvalidTypeException(object value, string argument) {
+ throw new ArgumentException(Strings.InvalidObjectType(value != null ? value.GetType() : (object)"null", typeof(T)), argument);
+ }
+
+ [Serializable]
+ private class Enumerator : IEnumerator<T>, System.Collections.IEnumerator {
+ private readonly ReadOnlyCollectionBuilder<T> _builder;
+ private readonly int _version;
+
+ private int _index;
+ private T _current;
+
+ internal Enumerator(ReadOnlyCollectionBuilder<T> builder) {
+ _builder = builder;
+ _version = builder._version;
+ _index = 0;
+ _current = default(T);
+ }
+
+ #region IEnumerator<T> Members
+
+ public T Current {
+ get { return _current; }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose() {
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ #region IEnumerator Members
+
+ object System.Collections.IEnumerator.Current {
+ get {
+ if (_index == 0 || _index > _builder._size) {
+ throw Error.EnumerationIsDone();
+ }
+ return _current;
+ }
+ }
+
+ public bool MoveNext() {
+ if (_version == _builder._version) {
+ if (_index < _builder._size) {
+ _current = _builder._items[_index++];
+ return true;
+ } else {
+ _index = _builder._size + 1;
+ _current = default(T);
+ return false;
+ }
+ } else {
+ throw Error.CollectionModifiedWhileEnumerating();
+ }
+ }
+
+ #endregion
+
+ #region IEnumerator Members
+
+ void System.Collections.IEnumerator.Reset() {
+ if (_version != _builder._version) {
+ throw Error.CollectionModifiedWhileEnumerating();
+ }
+ _index = 0;
+ _current = default(T);
+ }
+
+ #endregion
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyDictionary.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyDictionary.cs
new file mode 100644
index 00000000000..3d444f371b9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReadOnlyDictionary.cs
@@ -0,0 +1,205 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+#if CODEPLEX_40
+using System.Linq.Expressions;
+#else
+using Microsoft.Linq.Expressions;
+#endif
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+
+ // Like ReadOnlyCollection<T>: wraps an IDictionary<K, V> in a read-only wrapper
+ internal sealed class ReadOnlyDictionary<K, V> : IDictionary<K, V> {
+
+ // For wrapping non-readonly Keys, Values collections
+ // Not used for standard dictionaries, which return read-only Keys and Values
+ private sealed class ReadOnlyWrapper<T> : ICollection<T> {
+ // no idea why this warning is here
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ private readonly ICollection<T> _collection;
+
+ internal ReadOnlyWrapper(ICollection<T> collection) {
+ _collection = collection;
+ }
+
+ #region ICollection<T> Members
+
+ public void Add(T item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ public void Clear() {
+ throw Error.CollectionReadOnly();
+ }
+
+ public bool Contains(T item) {
+ return _collection.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex) {
+ _collection.CopyTo(array, arrayIndex);
+ }
+
+ public int Count {
+ get { return _collection.Count; }
+ }
+
+ public bool IsReadOnly {
+ get { return true; }
+ }
+
+ public bool Remove(T item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ #endregion
+
+ #region IEnumerable<T> Members
+
+ public IEnumerator<T> GetEnumerator() {
+ return _collection.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return _collection.GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ private readonly IDictionary<K, V> _dict;
+
+ internal ReadOnlyDictionary(IDictionary<K, V> dict) {
+ ReadOnlyDictionary<K, V> rodict = dict as ReadOnlyDictionary<K, V>;
+ _dict = (rodict != null) ? rodict._dict : dict;
+ }
+
+ #region IDictionary<K,V> Members
+
+ public bool ContainsKey(K key) {
+ return _dict.ContainsKey(key);
+ }
+
+ public ICollection<K> Keys {
+ get {
+ ICollection<K> keys = _dict.Keys;
+ if (!keys.IsReadOnly) {
+ return new ReadOnlyWrapper<K>(keys);
+ }
+ return keys;
+ }
+ }
+
+ public bool TryGetValue(K key, out V value) {
+ return _dict.TryGetValue(key, out value);
+ }
+
+ public ICollection<V> Values {
+ get {
+ ICollection<V> values = _dict.Values;
+ if (!values.IsReadOnly) {
+ return new ReadOnlyWrapper<V>(values);
+ }
+ return values;
+ }
+ }
+
+ public V this[K key] {
+ get {
+ return _dict[key];
+ }
+ }
+
+
+ void IDictionary<K, V>.Add(K key, V value) {
+ throw Error.CollectionReadOnly();
+ }
+
+ bool IDictionary<K, V>.Remove(K key) {
+ throw Error.CollectionReadOnly();
+ }
+
+ V IDictionary<K, V>.this[K key] {
+ get {
+ return _dict[key];
+ }
+ set {
+ throw Error.CollectionReadOnly();
+ }
+ }
+
+ #endregion
+
+ #region ICollection<KeyValuePair<K,V>> Members
+
+ public bool Contains(KeyValuePair<K, V> item) {
+ return _dict.Contains(item);
+ }
+
+ public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) {
+ _dict.CopyTo(array, arrayIndex);
+ }
+
+ public int Count {
+ get { return _dict.Count; }
+ }
+
+ public bool IsReadOnly {
+ get { return true; }
+ }
+
+ void ICollection<KeyValuePair<K, V>>.Add(KeyValuePair<K, V> item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ void ICollection<KeyValuePair<K, V>>.Clear() {
+ throw Error.CollectionReadOnly();
+ }
+
+ bool ICollection<KeyValuePair<K,V>>.Remove(KeyValuePair<K, V> item) {
+ throw Error.CollectionReadOnly();
+ }
+
+ #endregion
+
+ #region IEnumerable<KeyValuePair<K,V>> Members
+
+ public IEnumerator<KeyValuePair<K, V>> GetEnumerator() {
+ return _dict.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return _dict.GetEnumerator();
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReferenceEqualityComparer.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReferenceEqualityComparer.cs
new file mode 100644
index 00000000000..236217c5012
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/ReferenceEqualityComparer.cs
@@ -0,0 +1,43 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+#if !CODEPLEX_40
+using Microsoft.Runtime.CompilerServices;
+#endif
+
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+ internal sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T> {
+ internal static readonly ReferenceEqualityComparer<T> Instance = new ReferenceEqualityComparer<T>();
+
+ private ReferenceEqualityComparer() { }
+
+ public bool Equals(T x, T y) {
+ return object.ReferenceEquals(x, y);
+ }
+
+ public int GetHashCode(T obj) {
+ return RuntimeHelpers.GetHashCode(obj);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/StrongBox.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/StrongBox.cs
new file mode 100644
index 00000000000..e302b2bdb60
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/StrongBox.cs
@@ -0,0 +1,69 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+
+ /// <summary>
+ /// Holds a reference to a value.
+ /// </summary>
+ /// <typeparam name="T">The type of the value that the <see cref = "StrongBox{T}"></see> references.</typeparam>
+ public class StrongBox<T> : IStrongBox {
+ /// <summary>
+ /// Gets the strongly typed value associated with the <see cref = "StrongBox{T}"></see>
+ /// <remarks>This is explicitly exposed as a field instead of a property to enable loading the address of the field.</remarks>
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]
+ public T Value;
+
+ /// <summary>
+ /// Initializes a new StrongBox which can receive a value when used in a reference call.
+ /// </summary>
+ public StrongBox() {
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref = "StrongBox{T}"></see> with the specified value.
+ /// </summary>
+ /// <param name="value">A value that the <see cref = "StrongBox{T}"></see> will reference.</param>
+ public StrongBox(T value) {
+ Value = value;
+ }
+
+ object IStrongBox.Value {
+ get {
+ return Value;
+ }
+ set {
+ Value = (T)value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Defines a property for accessing the value that an object references.
+ /// </summary>
+ public interface IStrongBox {
+ /// <summary>
+ /// Gets or sets the value the object references.
+ /// </summary>
+ object Value { get; set; }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TrueReadOnlyCollection.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TrueReadOnlyCollection.cs
new file mode 100644
index 00000000000..68a7d53ee05
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TrueReadOnlyCollection.cs
@@ -0,0 +1,40 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if CODEPLEX_40
+using System.Dynamic.Utils;
+#else
+using Microsoft.Scripting.Utils;
+#endif
+
+#if CODEPLEX_40
+namespace System.Runtime.CompilerServices {
+#else
+namespace Microsoft.Runtime.CompilerServices {
+#endif
+ sealed class TrueReadOnlyCollection<T> : ReadOnlyCollection<T> {
+ /// <summary>
+ /// Creates instnace of TrueReadOnlyCollection, wrapping passed in array.
+ /// !!! DOES NOT COPY THE ARRAY !!!
+ /// </summary>
+ internal TrueReadOnlyCollection(T[] list)
+ : base(list) {
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs
new file mode 100644
index 00000000000..10e2c553cdc
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs
@@ -0,0 +1,128 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Microsoft Public License, please send an email to
+ * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System; using Microsoft;
+
+
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+
+#if CODEPLEX_40
+namespace System.Dynamic.Utils {
+#else
+namespace Microsoft.Scripting.Utils {
+#endif
+
+ // Extensions on System.Type and friends
+ internal static class TypeExtensions {
+
+ /// <summary>
+ /// Creates an open delegate for the given (dynamic)method.
+ /// </summary>
+ internal static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
+ Debug.Assert(methodInfo != null && delegateType != null);
+
+ var dm = methodInfo as DynamicMethod;
+ if (dm != null) {
+ return dm.CreateDelegate(delegateType);
+ } else {
+ return Delegate.CreateDelegate(delegateType, methodInfo);
+ }
+ }
+
+ /// <summary>
+ /// Creates a closed delegate for the given (dynamic)method.
+ /// </summary>
+ internal static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
+ Debug.Assert(methodInfo != null && delegateType != null);
+
+ var dm = methodInfo as DynamicMethod;
+ if (dm != null) {
+ return dm.CreateDelegate(delegateType, target);
+ } else {
+ return Delegate.CreateDelegate(delegateType, target, methodInfo);
+ }
+ }
+
+ internal static Type GetReturnType(this MethodBase mi) {
+ return (mi.IsConstructor) ? mi.DeclaringType : ((MethodInfo)mi).ReturnType;
+ }
+
+ private static readonly CacheDict<MethodBase, ParameterInfo[]> _ParamInfoCache = new CacheDict<MethodBase, ParameterInfo[]>(75);
+
+ internal static ParameterInfo[] GetParametersCached(this MethodBase method) {
+ ParameterInfo[] pis;
+ lock (_ParamInfoCache) {
+ if (!_ParamInfoCache.TryGetValue(method, out pis)) {
+ _ParamInfoCache[method] = pis = method.GetParameters();
+ }
+ }
+ return pis;
+ }
+
+ // Expression trees/compiler just use IsByRef, why do we need this?
+ // (see LambdaCompiler.EmitArguments for usage in the compiler)
+ internal static bool IsByRefParameter(this ParameterInfo pi) {
+ // not using IsIn/IsOut properties as they are not available in Silverlight:
+ if (pi.ParameterType.IsByRef) return true;
+
+ return (pi.Attributes & (ParameterAttributes.Out)) == ParameterAttributes.Out;
+ }
+
+ // Returns the matching method if the parameter types are reference
+ // assignable from the provided type arguments, otherwise null.
+ internal static MethodInfo GetMethodValidated(
+ this Type type,
+ string name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Type[] types,
+ ParameterModifier[] modifiers) {
+
+ var method = type.GetMethod(name, bindingAttr, binder, types, modifiers);
+
+ return method.MatchesArgumentTypes(types) ? method : null;
+ }
+
+ /// <summary>
+ /// Returns true if the method's parameter types are reference assignable from
+ /// the argument types, otherwise false.
+ ///
+ /// An example that can make the method return false is that
+ /// typeof(double).GetMethod("op_Equality", ..., new[] { typeof(double), typeof(int) })
+ /// returns a method with two double parameters, which doesn't match the provided
+ /// argument types.
+ /// </summary>
+ /// <returns></returns>
+ private static bool MatchesArgumentTypes(this MethodInfo mi, Type[] argTypes) {
+ if (mi == null || argTypes == null) {
+ return false;
+ }
+ var ps = mi.GetParameters();
+
+ if (ps.Length != argTypes.Length) {
+ return false;
+ }
+
+ for (int i = 0; i < ps.Length; i++) {
+ if (!TypeUtils.AreReferenceAssignable(ps[i].ParameterType, argTypes[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}