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>2014-01-09 23:39:18 +0400
committerMarek Safar <marek.safar@gmail.com>2014-01-09 23:40:09 +0400
commitb3f05d8b00f7fa0e7a747f2b51db68afbb9c4b1b (patch)
treee2515eca9034a71595955690775e96e14f5bb4ec /mcs/class/dlr
parent57b915d78f47f7248e1180099ceb2d3667449a33 (diff)
[System.Core] Add dynamic interpreter
Diffstat (limited to 'mcs/class/dlr')
-rw-r--r--mcs/class/dlr/README8
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Actions/Dummy.cs5
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/BinaryExpression.cs133
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/ConstantExpression.cs226
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/EmptyStatements.cs45
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/LightLambdaExpression.cs149
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/UnaryExpression.cs82
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/Utils.cs111
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs76
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/CompilerHelpers.cs906
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/ConstantCheck.cs128
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.Generated.cs110
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.cs87
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/BranchLabel.cs108
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/ILightCallSiteBinder.cs34
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs243
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ArrayOperations.cs111
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.Generated.cs905
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs296
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs595
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DivInstruction.cs132
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructionN.cs76
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructions.Generated.cs509
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicSplatInstruction.cs55
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs161
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/FieldOperations.cs94
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs146
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/Instruction.cs73
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs115
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs1001
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LabelInfo.cs309
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs146
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LocalAccess.cs374
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs162
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NumericConvertInstruction.cs254
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs117
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs163
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/InterpretedFrame.cs297
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Interpreter.cs262
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs1645
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightDelegateCreator.cs194
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.Generated.cs724
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.cs272
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambdaClosureVisitor.cs260
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LocalVariables.cs266
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LoopCompiler.cs323
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/RuntimeVariables.cs46
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/BigIntegerV4.cs614
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/Complex64.cs276
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs34
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs185
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ArgumentArray.cs76
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/DynamicNull.cs27
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ExceptionHelpers.cs79
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ScriptingRuntimeHelpers.cs261
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ArrayUtils.cs354
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/Assert.cs78
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CacheDict.cs114
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionExtensions.cs156
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionUtils.cs322
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ContractUtils.cs233
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/DynamicUtils.cs297
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionFactory.Generated.cs1050
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionUtils.cs111
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/HybridReferenceDictionary.cs170
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ListEqualityComparer.cs34
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/MathUtils.cs1229
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReferenceEqualityComparer.cs48
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReflectionUtils.cs1951
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/StringUtils.cs269
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/TypeUtils.cs375
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting/ArgumentTypeException.cs38
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting/InvalidImplementationException.cs38
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting/PlatformAdaptationLayer.cs471
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/NotNullAttribute.cs40
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/ParamDictionaryAttribute.cs55
-rw-r--r--mcs/class/dlr/Runtime/Microsoft.Scripting/Stubs.cs116
77 files changed, 21635 insertions, 0 deletions
diff --git a/mcs/class/dlr/README b/mcs/class/dlr/README
new file mode 100644
index 00000000000..7ec5bea3410
--- /dev/null
+++ b/mcs/class/dlr/README
@@ -0,0 +1,8 @@
+This is fork of Microsoft DLR source code. The original code was published at
+http://dlr.codeplex.com/ which had the code used for .NET 4.0
+System.Linq.Expression public API. Since them the code was migrated to
+https://github.com/IronLanguages/main but it no longer has the goal to offer
+compatible System.Linq.Expression API and we cannot use some part of it.
+
+We want to have minimum local changes. Importatant changes need to be marked
+using easily recognizable marker (like MONO_INTERPRETER) for easier merging. \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Actions/Dummy.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Actions/Dummy.cs
new file mode 100644
index 00000000000..880a99a8e2a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Actions/Dummy.cs
@@ -0,0 +1,5 @@
+namespace Microsoft.Scripting.Actions {
+ class Dummy
+ {
+ }
+} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/BinaryExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/BinaryExpression.cs
new file mode 100644
index 00000000000..10f8a9658c9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/BinaryExpression.cs
@@ -0,0 +1,133 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Reflection;
+using System.Dynamic;
+using Microsoft.Scripting.Utils;
+using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+namespace Microsoft.Scripting.Ast {
+ public static partial class Utils {
+#if !MONO_INTERPRETER
+ /// <summary>
+ /// Null coalescing expression
+ /// {result} ::= ((tmp = {_left}) == null) ? {right} : tmp
+ /// '??' operator in C#.
+ /// </summary>
+ public static Expression Coalesce(Expression left, Expression right, out ParameterExpression temp) {
+ return CoalesceInternal(left, right, null, false, out temp);
+ }
+
+ /// <summary>
+ /// True coalescing expression.
+ /// {result} ::= IsTrue(tmp = {left}) ? {right} : tmp
+ /// Generalized AND semantics.
+ /// </summary>
+ public static Expression CoalesceTrue(Expression left, Expression right, MethodInfo isTrue, out ParameterExpression temp) {
+ ContractUtils.RequiresNotNull(isTrue, "isTrue");
+ return CoalesceInternal(left, right, isTrue, false, out temp);
+ }
+
+ /// <summary>
+ /// False coalescing expression.
+ /// {result} ::= IsTrue(tmp = {left}) ? tmp : {right}
+ /// Generalized OR semantics.
+ /// </summary>
+ public static Expression CoalesceFalse(Expression left, Expression right, MethodInfo isTrue, out ParameterExpression temp) {
+ ContractUtils.RequiresNotNull(isTrue, "isTrue");
+ return CoalesceInternal(left, right, isTrue, true, out temp);
+ }
+
+ private static Expression CoalesceInternal(Expression left, Expression right, MethodInfo isTrue, bool isReverse, out ParameterExpression temp) {
+ ContractUtils.RequiresNotNull(left, "left");
+ ContractUtils.RequiresNotNull(right, "right");
+
+ // A bit too strict, but on a safe side.
+ ContractUtils.Requires(left.Type == right.Type, "Expression types must match");
+
+ temp = Expression.Variable(left.Type, "tmp_left");
+
+ Expression condition;
+ if (isTrue != null) {
+ ContractUtils.Requires(isTrue.ReturnType == typeof(bool), "isTrue", "Predicate must return bool.");
+ ParameterInfo[] parameters = isTrue.GetParameters();
+ ContractUtils.Requires(parameters.Length == 1, "isTrue", "Predicate must take one parameter.");
+ ContractUtils.Requires(isTrue.IsStatic && isTrue.IsPublic, "isTrue", "Predicate must be public and static.");
+
+ Type pt = parameters[0].ParameterType;
+ ContractUtils.Requires(TypeUtils.CanAssign(pt, left.Type), "left", "Incorrect left expression type");
+ condition = Expression.Call(isTrue, Expression.Assign(temp, left));
+ } else {
+ ContractUtils.Requires(TypeUtils.CanCompareToNull(left.Type), "left", "Incorrect left expression type");
+ condition = Expression.Equal(Expression.Assign(temp, left), AstUtils.Constant(null, left.Type));
+ }
+
+ Expression t, f;
+ if (isReverse) {
+ t = temp;
+ f = right;
+ } else {
+ t = right;
+ f = temp;
+ }
+
+ return Expression.Condition(condition, t, f);
+ }
+
+ public static Expression Coalesce(LambdaBuilder builder, Expression left, Expression right) {
+ ParameterExpression temp;
+ Expression result = Coalesce(left, right, out temp);
+ builder.AddHiddenVariable(temp);
+ return result;
+ }
+
+ /// <summary>
+ /// True coalescing expression.
+ /// {result} ::= IsTrue(tmp = {left}) ? {right} : tmp
+ /// Generalized AND semantics.
+ /// </summary>
+ public static Expression CoalesceTrue(LambdaBuilder builder, Expression left, Expression right, MethodInfo isTrue) {
+ ContractUtils.RequiresNotNull(isTrue, "isTrue");
+ ParameterExpression temp;
+ Expression result = CoalesceTrue(left, right, isTrue, out temp);
+ builder.AddHiddenVariable(temp);
+ return result;
+ }
+
+ /// <summary>
+ /// False coalescing expression.
+ /// {result} ::= IsTrue(tmp = {left}) ? tmp : {right}
+ /// Generalized OR semantics.
+ /// </summary>
+ public static Expression CoalesceFalse(LambdaBuilder builder, Expression left, Expression right, MethodInfo isTrue) {
+ ContractUtils.RequiresNotNull(isTrue, "isTrue");
+ ParameterExpression temp;
+ Expression result = CoalesceFalse(left, right, isTrue, out temp);
+ builder.AddHiddenVariable(temp);
+ return result;
+ }
+#endif
+ public static BinaryExpression Update(this BinaryExpression expression, Expression left, Expression right) {
+ return expression.Update(left, expression.Conversion, right);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/ConstantExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/ConstantExpression.cs
new file mode 100644
index 00000000000..7c75d149125
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/ConstantExpression.cs
@@ -0,0 +1,226 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+#if FEATURE_NUMERICS
+using BigInt = System.Numerics.BigInteger;
+using Complex = System.Numerics.Complex;
+#endif
+
+using System;
+using System.Reflection;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Math;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Ast {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
+ public static partial class Utils {
+ private static readonly ConstantExpression TrueLiteral = Expression.Constant(true, typeof(bool));
+ private static readonly ConstantExpression FalseLiteral = Expression.Constant(false, typeof(bool));
+ private static readonly ConstantExpression NullLiteral = Expression.Constant(null, typeof(object));
+ private static readonly ConstantExpression EmptyStringLiteral = Expression.Constant(String.Empty, typeof(string));
+ private static readonly ConstantExpression[] IntCache = new ConstantExpression[100];
+
+ /// <summary>
+ /// Wraps the given value in a WeakReference and returns a tree that will retrieve
+ /// the value from the WeakReference.
+ /// </summary>
+ public static MemberExpression WeakConstant(object value) {
+ System.Diagnostics.Debug.Assert(!(value is Expression));
+ return Expression.Property(
+ Constant(new WeakReference(value)),
+ typeof(WeakReference).GetDeclaredProperty("Target")
+ );
+ }
+
+ public static ConstantExpression Constant(object value, Type type) {
+ return Expression.Constant(value, type);
+ }
+
+ // The helper API should return ConstantExpression after SymbolConstantExpression goes away
+ public static Expression Constant(object value) {
+ if (value == null) {
+ return NullLiteral;
+ }
+
+ BigInteger bi = value as BigInteger;
+ if ((object)bi != null) {
+ return BigIntegerConstant(bi);
+#if FEATURE_NUMERICS
+ } else if (value is BigInt) {
+ return BigIntConstant((BigInt)value);
+ } else if (value is Complex) {
+ return ComplexConstant((Complex)value);
+#endif
+ } else if (value is Complex64) {
+ return Complex64Constant((Complex64)value);
+ } else if (value is Type) {
+ return Expression.Constant(value, typeof(Type));
+ } else if (value is ConstructorInfo) {
+ return Expression.Constant(value, typeof(ConstructorInfo));
+ } else if (value is EventInfo) {
+ return Expression.Constant(value, typeof(EventInfo));
+ } else if (value is FieldInfo) {
+ return Expression.Constant(value, typeof(FieldInfo));
+ } else if (value is MethodInfo) {
+ return Expression.Constant(value, typeof(MethodInfo));
+ } else if (value is PropertyInfo) {
+ return Expression.Constant(value, typeof(PropertyInfo));
+ } else {
+ Type t = value.GetType();
+ if (!t.GetTypeInfo().IsEnum) {
+ switch (t.GetTypeCode()) {
+ case TypeCode.Boolean:
+ return (bool)value ? TrueLiteral : FalseLiteral;
+ case TypeCode.Int32:
+ int x = (int)value;
+ int cacheIndex = x + 2;
+ if (cacheIndex >= 0 && cacheIndex < IntCache.Length) {
+ ConstantExpression res;
+ if ((res = IntCache[cacheIndex]) == null) {
+ IntCache[cacheIndex] = res = Constant(x, typeof(int));
+ }
+ return res;
+ }
+ break;
+ case TypeCode.String:
+ if (String.IsNullOrEmpty((string)value)) {
+ return EmptyStringLiteral;
+ }
+ break;
+ }
+ }
+ return Expression.Constant(value);
+ }
+ }
+
+ private static Expression BigIntegerConstant(BigInteger value) {
+ int ival;
+ if (value.AsInt32(out ival)) {
+ return Expression.Call(
+ new Func<int, BigInteger>(BigInteger.Create).GetMethodInfo(),
+ Constant(ival)
+ );
+ }
+
+ long lval;
+ if (value.AsInt64(out lval)) {
+ return Expression.Call(
+ new Func<long, BigInteger>(BigInteger.Create).GetMethodInfo(),
+ Constant(lval)
+ );
+ }
+
+#if !FEATURE_NUMERICS
+ return Expression.Call(
+ new Func<int, uint[], BigInteger>(CompilerHelpers.CreateBigInteger).Method,
+ Constant((int)value.Sign),
+ CreateArray<uint>(value.GetWords())
+ );
+#else
+ return Expression.Call(
+ new Func<bool, byte[], BigInteger>(CompilerHelpers.CreateBigInteger).GetMethodInfo(),
+ Constant(value.Sign < 0),
+ CreateArray<byte>(value.Abs().ToByteArray())
+ );
+ }
+
+ private static Expression BigIntConstant(BigInt value) {
+ int ival;
+ if (value.AsInt32(out ival)) {
+ return Expression.Call(
+ new Func<int, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
+ Constant(ival)
+ );
+ }
+
+ long lval;
+ if (value.AsInt64(out lval)) {
+ return Expression.Call(
+ new Func<long, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
+ Constant(lval)
+ );
+ }
+
+ return Expression.Call(
+ new Func<bool, byte[], BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
+ Constant(value.Sign < 0),
+ CreateArray<byte>(value.Abs().ToByteArray())
+ );
+#endif
+ }
+
+ private static Expression CreateArray<T>(T[] array) {
+ // TODO: could we use blobs?
+ Expression[] init = new Expression[array.Length];
+ for (int i = 0; i < init.Length; i++) {
+ init[i] = Constant(array[i]);
+ }
+ return Expression.NewArrayInit(typeof(T), init);
+ }
+
+#if FEATURE_NUMERICS
+ private static Expression ComplexConstant(Complex value) {
+ if (value.Real != 0.0) {
+ if (value.Imaginary() != 0.0) {
+ return Expression.Call(
+ new Func<double, double, Complex>(MathUtils.MakeComplex).GetMethodInfo(),
+ Constant(value.Real),
+ Constant(value.Imaginary())
+ );
+ } else {
+ return Expression.Call(
+ new Func<double, Complex>(MathUtils.MakeReal).GetMethodInfo(),
+ Constant(value.Real)
+ );
+ }
+ } else {
+ return Expression.Call(
+ new Func<double, Complex>(MathUtils.MakeImaginary).GetMethodInfo(),
+ Constant(value.Imaginary())
+ );
+ }
+ }
+#endif
+
+ private static Expression Complex64Constant(Complex64 value) {
+ if (value.Real != 0.0) {
+ if (value.Imag != 0.0) {
+ return Expression.Call(
+ new Func<double, double, Complex64>(Complex64.Make).GetMethodInfo(),
+ Constant(value.Real),
+ Constant(value.Imag)
+ );
+ } else {
+ return Expression.Call(
+ new Func<double, Complex64>(Complex64.MakeReal).GetMethodInfo(),
+ Constant(value.Real)
+ );
+ }
+ } else {
+ return Expression.Call(
+ new Func<double, Complex64>(Complex64.MakeImaginary).GetMethodInfo(),
+ Constant(value.Imag)
+ );
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/EmptyStatements.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/EmptyStatements.cs
new file mode 100644
index 00000000000..0968a2ca616
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/EmptyStatements.cs
@@ -0,0 +1,45 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Dynamic;
+
+namespace Microsoft.Scripting.Ast {
+ public static partial class Utils {
+ private static readonly DefaultExpression VoidInstance = Expression.Empty();
+
+ public static DefaultExpression Empty() {
+ return VoidInstance;
+ }
+
+ public static DefaultExpression Default(Type type) {
+ if (type == typeof(void)) {
+ return Empty();
+ }
+ return Expression.Default(type);
+ }
+ }
+}
+
+
+
+
+
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/LightLambdaExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/LightLambdaExpression.cs
new file mode 100644
index 00000000000..6b2a08e3443
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/LightLambdaExpression.cs
@@ -0,0 +1,149 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Scripting.Interpreter;
+using Microsoft.Scripting.Generation;
+
+namespace Microsoft.Scripting.Ast {
+ public class LightLambdaExpression : Expression {
+ private readonly Expression _body;
+ private readonly Type _retType;
+ private readonly string _name;
+ private readonly IList<ParameterExpression> _args;
+
+ internal LightLambdaExpression(Type retType, Expression body, string name, IList<ParameterExpression> args) {
+ _body = body;
+ _name = name;
+ _args = args;
+ _retType = retType;
+ }
+
+ public Expression Body {
+ get {
+ return _body;
+ }
+ }
+
+ public string Name {
+ get {
+ return _name;
+ }
+ }
+
+ public IList<ParameterExpression> Parameters {
+ get {
+ return _args;
+ }
+ }
+
+ internal virtual LambdaExpression ReduceToLambdaWorker() {
+ throw new InvalidOperationException();
+ }
+
+ public Delegate Compile() {
+ return Compile(-1);
+ }
+
+ public Delegate Compile(int compilationThreshold) {
+ return new LightCompiler(compilationThreshold).CompileTop(this).CreateDelegate();
+ }
+
+ public override ExpressionType NodeType {
+ get { return ExpressionType.Extension; }
+ }
+
+ public override bool CanReduce {
+ get { return true; }
+ }
+
+ public override Expression Reduce() {
+ return ReduceToLambdaWorker();
+ }
+
+ public Type ReturnType {
+ get {
+ return _retType;
+ }
+ }
+ }
+
+ internal class TypedLightLambdaExpression : LightLambdaExpression {
+ private readonly Type _delegateType;
+
+ internal TypedLightLambdaExpression(Type retType, Type delegateType, Expression body, string name, IList<ParameterExpression> args)
+ : base(retType, body, name, args) {
+ _delegateType = delegateType;
+ }
+
+ internal override LambdaExpression ReduceToLambdaWorker() {
+ return Expression.Lambda(
+ _delegateType,
+ Body,
+ Name,
+ Parameters
+ );
+ }
+
+ public override Type Type {
+ get { return _delegateType; }
+ }
+ }
+
+ public class LightExpression<T> : LightLambdaExpression {
+ internal LightExpression(Type retType, Expression body, string name, IList<ParameterExpression> args)
+ : base(retType, body, name, args) {
+ }
+
+ public Expression<T> ReduceToLambda() {
+ return Expression.Lambda<T>(Body, Name, Parameters);
+ }
+
+ public override Type Type {
+ get { return typeof(T); }
+ }
+
+ public new T Compile() {
+ return Compile(-1);
+ }
+
+ public new T Compile(int compilationThreshold) {
+ return (T)(object)new LightCompiler(compilationThreshold).CompileTop(this).CreateDelegate();
+ }
+
+ internal override LambdaExpression ReduceToLambdaWorker() {
+ return ReduceToLambda();
+ }
+ }
+
+ public static partial class Utils {
+ public static LightExpression<T> LightLambda<T>(Type retType, Expression body, string name, IList<ParameterExpression> args) {
+ return new LightExpression<T>(retType, body, name, args);
+ }
+
+ public static LightLambdaExpression LightLambda(Type retType, Type delegateType, Expression body, string name, IList<ParameterExpression> args) {
+ return new TypedLightLambdaExpression(retType, delegateType, body, name, args);
+ }
+ }
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/UnaryExpression.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/UnaryExpression.cs
new file mode 100644
index 00000000000..19477b2320e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/UnaryExpression.cs
@@ -0,0 +1,82 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+using System.Reflection;
+
+namespace Microsoft.Scripting.Ast {
+ public static partial class Utils {
+ /// <summary>
+ /// Converts an expression to a void type.
+ /// </summary>
+ /// <param name="expression">An <see cref="Expression"/> to convert to void. </param>
+ /// <returns>An <see cref="Expression" /> that has the <see cref="P:System.Linq.Expressions.Expression.NodeType" /> property equal to <see cref="F:System.Linq.Expressions.ExpressionType.ConvertChecked" /> and the <see cref="P:System.Linq.Expressions.UnaryExpression.Operand" /> and <see cref="P:System.Linq.Expressions.Expression.Type" /> property set to void.</returns>
+ public static Expression Void(Expression expression) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+ if (expression.Type == typeof(void)) {
+ return expression;
+ }
+ return Expression.Block(expression, Utils.Empty());
+ }
+
+ public static Expression Convert(Expression expression, Type type) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+
+ if (expression.Type == type) {
+ return expression;
+ }
+
+ if (expression.Type == typeof(void)) {
+ return Expression.Block(expression, Utils.Default(type));
+ }
+
+ if (type == typeof(void)) {
+ return Void(expression);
+ }
+
+ // TODO: this is not the right level for this to be at. It should
+ // be pushed into languages if they really want this behavior.
+ if (type == typeof(object)) {
+ return Box(expression);
+ }
+
+ return Expression.Convert(expression, type);
+ }
+
+ /// <summary>
+ /// Returns an expression that boxes a given value. Uses boxed objects cache for Int32 and Boolean types.
+ /// </summary>
+ public static Expression Box(Expression expression) {
+ MethodInfo m;
+ if (expression.Type == typeof(int)) {
+ m = ScriptingRuntimeHelpers.Int32ToObjectMethod;
+ } else if (expression.Type == typeof(bool)) {
+ m = ScriptingRuntimeHelpers.BooleanToObjectMethod;
+ } else {
+ m = null;
+ }
+
+ return Expression.Convert(expression, typeof(object), m);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/Utils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/Utils.cs
new file mode 100644
index 00000000000..165a42458e8
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Ast/Utils.cs
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Reflection;
+using System.Dynamic;
+using Microsoft.Scripting.Utils;
+using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+namespace Microsoft.Scripting.Ast {
+ [Flags]
+ public enum ExpressionAccess {
+ None = 0,
+ Read = 1,
+ Write = 2,
+ ReadWrite = Read | Write,
+ }
+
+ public static partial class Utils {
+ /// <summary>
+ /// Determines whether specified expression type represents an assignment.
+ /// </summary>
+ /// <returns>
+ /// True if the expression type represents an assignment.
+ /// </returns>
+ /// <remarks>
+ /// Note that some other nodes can also assign to variables, members or array items:
+ /// MemberInit, NewArrayInit, Call with ref params, New with ref params, Dynamic with ref params.
+ /// </remarks>
+ public static bool IsAssignment(this ExpressionType type) {
+ return IsWriteOnlyAssignment(type) || IsReadWriteAssignment(type);
+ }
+
+ public static bool IsWriteOnlyAssignment(this ExpressionType type) {
+ return type == ExpressionType.Assign;
+ }
+
+ public static bool IsReadWriteAssignment(this ExpressionType type) {
+ switch (type) {
+ // unary:
+ case ExpressionType.PostDecrementAssign:
+ case ExpressionType.PostIncrementAssign:
+ case ExpressionType.PreDecrementAssign:
+ case ExpressionType.PreIncrementAssign:
+
+ // binary - compound:
+ case ExpressionType.AddAssign:
+ case ExpressionType.AddAssignChecked:
+ case ExpressionType.AndAssign:
+ case ExpressionType.DivideAssign:
+ case ExpressionType.ExclusiveOrAssign:
+ case ExpressionType.LeftShiftAssign:
+ case ExpressionType.ModuloAssign:
+ case ExpressionType.MultiplyAssign:
+ case ExpressionType.MultiplyAssignChecked:
+ case ExpressionType.OrAssign:
+ case ExpressionType.PowerAssign:
+ case ExpressionType.RightShiftAssign:
+ case ExpressionType.SubtractAssign:
+ case ExpressionType.SubtractAssignChecked:
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Determines if the left child of the given expression is read or written to or both.
+ /// </summary>
+ public static ExpressionAccess GetLValueAccess(this ExpressionType type) {
+ if (type.IsReadWriteAssignment()) {
+ return ExpressionAccess.ReadWrite;
+ }
+
+ if (type.IsWriteOnlyAssignment()) {
+ return ExpressionAccess.Write;
+ }
+
+ return ExpressionAccess.Read;
+ }
+
+ public static bool IsLValue(this ExpressionType type) {
+ // see Expression.RequiresCanWrite
+ switch (type) {
+ case ExpressionType.Index:
+ case ExpressionType.MemberAccess:
+ case ExpressionType.Parameter:
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs
new file mode 100644
index 00000000000..a3aac34473a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/DebugOptions.cs
@@ -0,0 +1,76 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System.Security;
+using System;
+
+namespace Microsoft.Scripting {
+
+ /// <summary>
+ /// This class holds onto internal debugging options used in this assembly.
+ /// These options can be set via environment variables DLR_{option-name}.
+ /// Boolean options map "true" to true and other values to false.
+ ///
+ /// These options are for internal debugging only, and should not be
+ /// exposed through any public APIs.
+ /// </summary>
+ internal static class DebugOptions {
+
+ private static bool ReadOption(string name) {
+#if SILVERLIGHT
+ return false;
+#else
+ string envVar = ReadString(name);
+ return envVar != null && envVar.ToLowerInvariant() == "true";
+#endif
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "name")]
+ private static bool ReadDebugOption(string name) {
+#if DEBUG
+ return ReadOption(name);
+#else
+ return false;
+#endif
+ }
+
+ private static string ReadString(string name) {
+#if FEATURE_PROCESS
+ try {
+ return Environment.GetEnvironmentVariable("DLR_" + name);
+ } catch (SecurityException) {
+ return null;
+ }
+#else
+ return null;
+#endif
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "name")]
+ private static string ReadDebugString(string name) {
+#if DEBUG
+ return ReadString(name);
+#else
+ return null;
+#endif
+ }
+
+ private readonly static bool _trackPerformance = ReadDebugOption("TrackPerformance");
+
+ internal static bool TrackPerformance {
+ get { return _trackPerformance; }
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/CompilerHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/CompilerHelpers.cs
new file mode 100644
index 00000000000..919d1b5b5e5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/CompilerHelpers.cs
@@ -0,0 +1,906 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_NUMERICS
+using BigInt = System.Numerics.BigInteger;
+#endif
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#endif
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Dynamic;
+using System.Linq;
+using System.Reflection;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Actions;
+using Microsoft.Scripting.Ast;
+using Microsoft.Scripting.Interpreter;
+using Microsoft.Scripting.Math;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+namespace Microsoft.Scripting.Generation {
+ // TODO: keep this?
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ public delegate void ActionRef<T0, T1>(ref T0 arg0, ref T1 arg1);
+
+ public static class CompilerHelpers {
+ public static readonly MethodAttributes PublicStatic = MethodAttributes.Public | MethodAttributes.Static;
+ private static readonly MethodInfo _CreateInstanceMethod = typeof(ScriptingRuntimeHelpers).GetMethod("CreateInstance");
+
+ private static int _Counter; // for generating unique names for lambda methods
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ public static object GetMissingValue(Type type) {
+ ContractUtils.RequiresNotNull(type, "type");
+
+ if (type.IsByRef) type = type.GetElementType();
+ if (type.IsEnum()) return Activator.CreateInstance(type);
+
+ switch (type.GetTypeCode()) {
+ default:
+ case TypeCode.Object:
+ // struct
+ if (type.IsSealed() && type.IsValueType()) {
+ return Activator.CreateInstance(type);
+ } else if (type == typeof(object)) {
+ // parameter of type object receives the actual Missing value
+ return Missing.Value;
+ } else if (!type.IsValueType()) {
+ return null;
+ } else {
+ throw Error.CantCreateDefaultTypeFor(type);
+ }
+ case TypeCode.Empty:
+ case TypeCode.DBNull:
+ case TypeCode.String:
+ return null;
+
+ case TypeCode.Boolean: return false;
+ case TypeCode.Char: return '\0';
+ case TypeCode.SByte: return (sbyte)0;
+ case TypeCode.Byte: return (byte)0;
+ case TypeCode.Int16: return (short)0;
+ case TypeCode.UInt16: return (ushort)0;
+ case TypeCode.Int32: return (int)0;
+ case TypeCode.UInt32: return (uint)0;
+ case TypeCode.Int64: return 0L;
+ case TypeCode.UInt64: return 0UL;
+ case TypeCode.Single: return 0.0f;
+ case TypeCode.Double: return 0.0D;
+ case TypeCode.Decimal: return (decimal)0;
+ case TypeCode.DateTime: return DateTime.MinValue;
+ }
+ }
+
+ public static bool IsStatic(MethodBase mi) {
+ return mi.IsConstructor || mi.IsStatic;
+ }
+
+ /// <summary>
+ /// True if the MethodBase is method which is going to construct an object
+ /// </summary>
+ public static bool IsConstructor(MethodBase mb) {
+ if (mb.IsConstructor) {
+ return true;
+ }
+
+ if (mb.IsGenericMethod) {
+ MethodInfo mi = mb as MethodInfo;
+
+ if (mi.GetGenericMethodDefinition() == _CreateInstanceMethod) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static T[] MakeRepeatedArray<T>(T item, int count) {
+ T[] ret = new T[count];
+ for (int i = 0; i < count; i++) ret[i] = item;
+ return ret;
+ }
+
+ public static bool IsComparisonOperator(ExpressionType op) {
+ switch (op) {
+ case ExpressionType.LessThan: return true;
+ case ExpressionType.LessThanOrEqual: return true;
+ case ExpressionType.GreaterThan: return true;
+ case ExpressionType.GreaterThanOrEqual: return true;
+ case ExpressionType.Equal: return true;
+ case ExpressionType.NotEqual: return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Returns the System.Type for any object, including null. The type of null
+ /// is represented by None.Type and all other objects just return the
+ /// result of Object.GetType
+ /// </summary>
+ public static Type GetType(object obj) {
+ if (obj == null) {
+ return typeof(DynamicNull);
+ }
+
+ return obj.GetType();
+ }
+
+ /// <summary>
+ /// Simply returns a Type[] from calling GetType on each element of args.
+ /// </summary>
+ public static Type[] GetTypes(object[] args) {
+ Type[] types = new Type[args.Length];
+ for (int i = 0; i < args.Length; i++) {
+ types[i] = GetType(args[i]);
+ }
+ return types;
+ }
+
+ /// <summary>
+ /// EMITTED
+ /// Used by default method binder to check types of splatted arguments.
+ /// </summary>
+ public static bool TypesEqual(IList args, int start, Type[] types) {
+ for (int i = 0; i < types.Length; i++) {
+ object arg = args[start + i];
+ if (types[i] != (arg != null ? arg.GetType() : null)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static bool CanOptimizeMethod(MethodBase method) {
+ if (method.ContainsGenericParameters ||
+ method.IsProtected() ||
+ method.IsPrivate ||
+ !method.DeclaringType.IsVisible()) {
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Given a MethodInfo which may be declared on a non-public type this attempts to
+ /// return a MethodInfo which will dispatch to the original MethodInfo but is declared
+ /// on a public type.
+ ///
+ /// Returns the original method if the method if a public version cannot be found.
+ /// </summary>
+ public static MethodInfo TryGetCallableMethod(Type targetType, MethodInfo method) {
+ if (method.DeclaringType == null || method.DeclaringType.IsVisible()) {
+ return method;
+ }
+
+ // first try and get it from the base type we're overriding...
+ MethodInfo baseMethod = method.GetRuntimeBaseDefinition();
+
+ if (baseMethod.DeclaringType.IsVisible() || baseMethod.DeclaringType.IsInterface()) {
+ // We need to instantiate the method as GetBaseDefinition might return a generic definition of the base method:
+ if (baseMethod.IsGenericMethodDefinition) {
+ baseMethod = baseMethod.MakeGenericMethod(method.GetGenericArguments());
+ }
+ return baseMethod;
+ }
+
+#if WIN8 // TODO: interface map, method handle
+ foreach (Type iface in targetType.GetImplementedInterfaces()) {
+ dynamic mapping = ((dynamic)targetType).GetInterfaceMap(iface);
+ for (int i = 0; i < mapping.TargetMethods.Length; i++) {
+ MethodInfo targetMethod = mapping.TargetMethods[i];
+ if (targetMethod != null && ((dynamic)targetMethod).MethodHandle == ((dynamic)method).MethodHandle) {
+ return mapping.InterfaceMethods[i];
+ }
+ }
+ }
+#else
+ // maybe we can get it from an interface on the type this
+ // method came from...
+ foreach (Type iface in targetType.GetImplementedInterfaces()) {
+ if (iface.IsPublic()) {
+ InterfaceMapping mapping = targetType.GetInterfaceMap(iface);
+ for (int i = 0; i < mapping.TargetMethods.Length; i++) {
+ MethodInfo targetMethod = mapping.TargetMethods[i];
+ if (targetMethod != null && targetMethod.MethodHandle == method.MethodHandle) {
+ return mapping.InterfaceMethods[i];
+ }
+ }
+ }
+ }
+#endif
+ return method;
+ }
+
+ /// <summary>
+ /// Non-public types can have public members that we find when calling type.GetMember(...). This
+ /// filters out the non-visible members by attempting to resolve them to the correct visible type.
+ ///
+ /// If no correct visible type can be found then the member is not visible and we won't call it.
+ /// </summary>
+ public static IEnumerable<MemberInfo> FilterNonVisibleMembers(Type targetType, IEnumerable<MemberInfo> members) {
+ if (targetType.IsVisible()) {
+ return members;
+ } else {
+ return FilterNonVisibleMembersIterator(targetType, members);
+ }
+ }
+
+ public static IEnumerable<MemberInfo> FilterNonVisibleMembersIterator(Type targetType, IEnumerable<MemberInfo> members) {
+ foreach (var member in members) {
+ MemberInfo visible = TryGetVisibleMember(targetType, member);
+ if (visible != null) {
+ yield return visible;
+ }
+ }
+ }
+
+ public static MemberInfo TryGetVisibleMember(Type targetType, MemberInfo member) {
+ MethodInfo method;
+ PropertyInfo property;
+ EventInfo evnt;
+
+ MethodInfo mi;
+ MemberInfo visible = null;
+
+ if ((method = member as MethodInfo) != null) {
+ mi = TryGetCallableMethod(targetType, method);
+ if (CompilerHelpers.IsVisible(mi)) {
+ visible = mi;
+ }
+ } else if ((property = member as PropertyInfo) != null) {
+ mi = TryGetCallableMethod(targetType, property.GetGetMethod() ?? property.GetSetMethod());
+ if (CompilerHelpers.IsVisible(mi)) {
+ visible = mi.DeclaringType.GetDeclaredProperty(property.Name);
+ }
+ } else if ((evnt = member as EventInfo) != null) {
+ mi = TryGetCallableMethod(targetType, evnt.GetAddMethod() ?? evnt.GetRemoveMethod() ?? evnt.GetRaiseMethod());
+ if (CompilerHelpers.IsVisible(mi)) {
+ visible = mi.DeclaringType.GetDeclaredEvent(evnt.Name);
+ }
+ }
+
+ // all others can't be exposed out this way
+ return visible;
+ }
+
+#if !WIN8
+ /// <summary>
+ /// Sees if two MemberInfos point to the same underlying construct in IL. This
+ /// ignores the ReflectedType property which exists on MemberInfos which
+ /// causes direct comparisons to be false even if they are the same member.
+ /// </summary>
+ public static bool MemberEquals(this MemberInfo self, MemberInfo other) {
+ if ((self == null) != (other == null)) {
+ // one null, the other isn't.
+ return false;
+ } else if (self == null) {
+ // both null
+ return true;
+ }
+
+ if (self.MemberType != other.MemberType) {
+ return false;
+ }
+
+ switch (self.MemberType) {
+ case MemberTypes.Field:
+ return ((FieldInfo)self).FieldHandle.Equals(((FieldInfo)other).FieldHandle);
+ case MemberTypes.Method:
+ return ((MethodInfo)self).MethodHandle.Equals(((MethodInfo)other).MethodHandle);
+ case MemberTypes.Constructor:
+ return ((ConstructorInfo)self).MethodHandle.Equals(((ConstructorInfo)other).MethodHandle);
+ case MemberTypes.NestedType:
+ case MemberTypes.TypeInfo:
+ return ((Type)self).TypeHandle.Equals(((Type)other).TypeHandle);
+ case MemberTypes.Event:
+ case MemberTypes.Property:
+ default:
+ return
+ ((MemberInfo)self).Module == ((MemberInfo)other).Module &&
+ ((MemberInfo)self).MetadataToken == ((MemberInfo)other).MetadataToken;
+ }
+ }
+#endif
+
+ public static bool IsVisible(MethodBase info) {
+ return info.IsPublic && (info.DeclaringType == null || info.DeclaringType.IsVisible());
+ }
+
+ public static bool IsVisible(FieldInfo info) {
+ return info.IsPublic && (info.DeclaringType == null || info.DeclaringType.IsVisible());
+ }
+
+ public static bool IsProtected(this MethodBase info) {
+ return info.IsFamily || info.IsFamilyOrAssembly;
+ }
+
+ public static bool IsProtected(this FieldInfo info) {
+ return info.IsFamily || info.IsFamilyOrAssembly;
+ }
+
+ public static bool IsProtected(this Type type) {
+ return type.GetTypeInfo().IsNestedFamily || type.GetTypeInfo().IsNestedFamORAssem;
+ }
+
+ public static Type GetVisibleType(object value) {
+ return GetVisibleType(GetType(value));
+ }
+
+ public static Type GetVisibleType(Type t) {
+ while (!t.IsVisible()) {
+ t = t.GetBaseType();
+ }
+ return t;
+ }
+
+ public static MethodBase[] GetConstructors(Type t, bool privateBinding) {
+ return GetConstructors(t, privateBinding, false);
+ }
+
+ public static MethodBase[] GetConstructors(Type t, bool privateBinding, bool includeProtected) {
+ if (t.IsArray) {
+ // The JIT verifier doesn't like new int[](3) even though it appears as a ctor.
+ // We could do better and return newarr in the future.
+ return new MethodBase[] { GetArrayCtor(t) };
+ }
+
+ BindingFlags bf = BindingFlags.Instance | BindingFlags.Public;
+ if (privateBinding || includeProtected) {
+ bf |= BindingFlags.NonPublic;
+ }
+
+ IEnumerable<ConstructorInfo> ctors = t.GetDeclaredConstructors().WithBindingFlags(bf);
+
+ // leave in protected ctors, even if we're not in private binding mode.
+ if (!privateBinding && includeProtected) {
+ ctors = FilterConstructorsToPublicAndProtected(ctors);
+ }
+
+ if (t.IsValueType()
+#if !SILVERLIGHT && !WIN8 && !WP75
+ && t != typeof(ArgIterator)
+#endif
+) {
+ // structs don't define a parameterless ctor, add a generic method for that.
+ List<MethodBase> result = new List<MethodBase>();
+ result.Add(GetStructDefaultCtor(t));
+ result.AddRange(ctors.Cast<ConstructorInfo, MethodBase>());
+ return result.ToArray();
+ } else {
+ return ctors.ToArray();
+ }
+ }
+
+ public static IEnumerable<ConstructorInfo> FilterConstructorsToPublicAndProtected(IEnumerable<ConstructorInfo> ctors) {
+ foreach (var ctor in ctors) {
+ if (ctor.IsPublic || ctor.IsProtected()) {
+ yield return ctor;
+ }
+ }
+ }
+
+ private static MethodBase GetStructDefaultCtor(Type t) {
+ return typeof(ScriptingRuntimeHelpers).GetDeclaredMethods("CreateInstance").Single().MakeGenericMethod(t);
+ }
+
+ private static MethodBase GetArrayCtor(Type t) {
+ return typeof(ScriptingRuntimeHelpers).GetDeclaredMethods("CreateArray").Single().MakeGenericMethod(t.GetElementType());
+ }
+
+ #region Type Conversions
+
+ public static MethodInfo GetImplicitConverter(Type fromType, Type toType) {
+ return GetConverter(fromType, fromType, toType, "op_Implicit") ?? GetConverter(toType, fromType, toType, "op_Implicit");
+ }
+
+ public static MethodInfo GetExplicitConverter(Type fromType, Type toType) {
+ return GetConverter(fromType, fromType, toType, "op_Explicit") ?? GetConverter(toType, fromType, toType, "op_Explicit");
+ }
+
+ private static MethodInfo GetConverter(Type type, Type fromType, Type toType, string opMethodName) {
+ foreach (MethodInfo mi in type.GetInheritedMembers(opMethodName).WithBindingFlags(BindingFlags.Public | BindingFlags.Static)) {
+ if ((mi.DeclaringType == null || mi.DeclaringType.IsVisible()) && mi.IsPublic &&
+ mi.ReturnType == toType && mi.GetParameters()[0].ParameterType.IsAssignableFrom(fromType)) {
+ return mi;
+ }
+ }
+ return null;
+ }
+
+ public static bool TryImplicitConversion(Object value, Type to, out object result) {
+ if (CompilerHelpers.TryImplicitConvert(value, to, to.GetInheritedMethods("op_Implicit").WithBindingFlags(BindingFlags.Public | BindingFlags.Static), out result)) {
+ return true;
+ }
+
+ Type curType = CompilerHelpers.GetType(value);
+ do {
+ if (CompilerHelpers.TryImplicitConvert(value, to, curType.GetInheritedMethods("op_Implicit").WithBindingFlags(BindingFlags.Public | BindingFlags.Static), out result)) {
+ return true;
+ }
+ curType = curType.GetBaseType();
+ } while (curType != null);
+
+ return false;
+ }
+
+ private static bool TryImplicitConvert(Object value, Type to, IEnumerable<MethodInfo> implicitConv, out object result) {
+ foreach (MethodInfo mi in implicitConv) {
+ if (to.IsValueType() == mi.ReturnType.IsValueType() && to.IsAssignableFrom(mi.ReturnType)) {
+ if (mi.IsStatic) {
+ result = mi.Invoke(null, new object[] { value });
+ } else {
+ result = mi.Invoke(value, ArrayUtils.EmptyObjects);
+ }
+ return true;
+ }
+ }
+
+ result = null;
+ return false;
+ }
+
+ public static bool IsStrongBox(object target) {
+ Type t = CompilerHelpers.GetType(target);
+
+ return IsStrongBox(t);
+ }
+
+ public static bool IsStrongBox(Type t) {
+ return t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(StrongBox<>);
+ }
+
+ /// <summary>
+ /// Returns a value which indicates failure when a OldConvertToAction of ImplicitTry or
+ /// ExplicitTry.
+ /// </summary>
+ public static Expression GetTryConvertReturnValue(Type type) {
+ Expression res;
+ var info = type.GetTypeInfo();
+ if (info.IsInterface || info.IsClass || (info.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))) {
+ res = AstUtils.Constant(null, type);
+ } else {
+ res = AstUtils.Constant(Activator.CreateInstance(type));
+ }
+
+ return res;
+ }
+
+ public static bool HasTypeConverter(Type fromType, Type toType) {
+#if FEATURE_TYPECONVERTER
+ TypeConverter _;
+ return TryGetTypeConverter(fromType, toType, out _);
+#else
+ return false;
+#endif
+ }
+
+ public static bool TryApplyTypeConverter(object value, Type toType, out object result) {
+#if FEATURE_TYPECONVERTER
+ TypeConverter converter;
+ if (value != null && CompilerHelpers.TryGetTypeConverter(value.GetType(), toType, out converter)) {
+ result = converter.ConvertFrom(value);
+ return true;
+ } else {
+ result = value;
+ return false;
+ }
+#else
+ result = value;
+ return false;
+#endif
+ }
+
+#if FEATURE_TYPECONVERTER
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
+ public static bool TryGetTypeConverter(Type fromType, Type toType, out TypeConverter converter) {
+ ContractUtils.RequiresNotNull(fromType, "fromType");
+ ContractUtils.RequiresNotNull(toType, "toType");
+
+ // try available type conversions...
+ foreach (TypeConverterAttribute tca in toType.GetCustomAttributes(typeof(TypeConverterAttribute), true)) {
+ try {
+ converter = Activator.CreateInstance(Type.GetType(tca.ConverterTypeName)) as TypeConverter;
+ } catch (Exception) {
+ converter = null;
+ }
+
+ if (converter != null && converter.CanConvertFrom(fromType)) {
+ return true;
+ }
+ }
+
+ converter = null;
+ return false;
+ }
+#endif
+
+ #endregion
+
+#if !MONO_INTERPRETER
+ public static MethodBase[] GetMethodTargets(object obj) {
+ Type t = CompilerHelpers.GetType(obj);
+
+ if (typeof(Delegate).IsAssignableFrom(t)) {
+ MethodInfo mi = t.GetMethod("Invoke");
+ return new MethodBase[] { mi };
+ } else if (typeof(BoundMemberTracker).IsAssignableFrom(t)) {
+ BoundMemberTracker bmt = obj as BoundMemberTracker;
+ if (bmt.BoundTo.MemberType == TrackerTypes.Method) {
+ }
+ } else if (typeof(MethodGroup).IsAssignableFrom(t)) {
+ } else if (typeof(MemberGroup).IsAssignableFrom(t)) {
+ } else {
+ return MakeCallSignatureForCallableObject(t);
+ }
+
+ return null;
+ }
+#endif
+
+ private static MethodBase[] MakeCallSignatureForCallableObject(Type t) {
+ List<MethodBase> res = new List<MethodBase>();
+ foreach (MethodInfo method in t.GetInheritedMethods("Call")) {
+ if (method.IsSpecialName) {
+ res.Add(method);
+ }
+ }
+ return res.ToArray();
+ }
+
+ public static Type[] GetSiteTypes(IList<Expression> arguments, Type returnType) {
+ int count = arguments.Count;
+
+ Type[] ret = new Type[count + 1];
+
+ for (int i = 0; i < count; i++) {
+ ret[i] = arguments[i].Type;
+ }
+
+ ret[count] = returnType;
+ return ret;
+ }
+
+ public static Type[] GetExpressionTypes(Expression[] expressions) {
+ ContractUtils.RequiresNotNull(expressions, "expressions");
+
+ Type[] res = new Type[expressions.Length];
+ for (int i = 0; i < res.Length; i++) {
+ ContractUtils.RequiresNotNull(expressions[i], "expressions[i]");
+
+ res[i] = expressions[i].Type;
+ }
+
+ return res;
+ }
+
+ public static Type MakeCallSiteType(params Type[] types) {
+ return typeof(CallSite<>).MakeGenericType(DelegateHelpers.MakeDelegate(types));
+ }
+
+ public static Type MakeCallSiteDelegateType(Type[] types) {
+ return DelegateHelpers.MakeDelegate(types);
+ }
+
+ /// <summary>
+ /// Creates an interpreted delegate for the lambda.
+ /// </summary>
+ /// <param name="lambda">The lambda to compile.</param>
+ /// <returns>A delegate which can interpret the lambda.</returns>
+ public static Delegate LightCompile(this LambdaExpression lambda) {
+ return new LightCompiler(-1).CompileTop(lambda).CreateDelegate();
+ }
+
+ /// <summary>
+ /// Creates an interpreted delegate for the lambda.
+ /// </summary>
+ /// <param name="lambda">The lambda to compile.</param>
+ /// <param name="compilationThreshold">The number of iterations before the interpreter starts compiling</param>
+ /// <returns>A delegate which can interpret the lambda.</returns>
+ public static Delegate LightCompile(this LambdaExpression lambda, int compilationThreshold) {
+ return new LightCompiler(compilationThreshold).CompileTop(lambda).CreateDelegate();
+ }
+
+ /// <summary>
+ /// Creates an interpreted delegate for the lambda.
+ /// </summary>
+ /// <typeparam name="T">The lambda's delegate type.</typeparam>
+ /// <param name="lambda">The lambda to compile.</param>
+ /// <returns>A delegate which can interpret the lambda.</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
+ public static T LightCompile<T>(this Expression<T> lambda) {
+ return (T)(object)LightCompile((LambdaExpression)lambda);
+ }
+
+ /// <summary>
+ /// Creates an interpreted delegate for the lambda.
+ /// </summary>
+ /// <param name="lambda">The lambda to compile.</param>
+ /// <param name="compilationThreshold">The number of iterations before the interpreter starts compiling</param>
+ /// <returns>A delegate which can interpret the lambda.</returns>
+ public static T LightCompile<T>(this Expression<T> lambda, int compilationThreshold) {
+ return (T)(object)LightCompile((LambdaExpression)lambda, compilationThreshold);
+ }
+
+#if FEATURE_REFEMIT
+ /// <summary>
+ /// Compiles the lambda into a method definition.
+ /// </summary>
+ /// <param name="lambda">the lambda to compile</param>
+ /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
+ /// <param name="emitDebugSymbols">A parameter that indicates if debugging information should be emitted to a PDB symbol store.</param>
+ public static void CompileToMethod(this LambdaExpression lambda, MethodBuilder method, bool emitDebugSymbols) {
+#if FEATURE_PDBEMIT
+ if (emitDebugSymbols) {
+ var module = method.Module as ModuleBuilder;
+ ContractUtils.Requires(module != null, "method", "MethodBuilder does not have a valid ModuleBuilder");
+ lambda.CompileToMethod(method, DebugInfoGenerator.CreatePdbGenerator());
+ return;
+ }
+#endif
+
+#if WIN8 // TODO
+ ((dynamic)lambda).CompileToMethod(method);
+#else
+ lambda.CompileToMethod(method);
+#endif
+ }
+#endif
+
+ /// <summary>
+ /// Compiles the LambdaExpression.
+ ///
+ /// If the lambda is compiled with emitDebugSymbols, it will be
+ /// generated into a TypeBuilder. Otherwise, this method is the same as
+ /// calling LambdaExpression.Compile()
+ ///
+ /// This is a workaround for a CLR limitiation: DynamicMethods cannot
+ /// have debugging information.
+ /// </summary>
+ /// <param name="lambda">the lambda to compile</param>
+ /// <param name="emitDebugSymbols">true to generate a debuggable method, false otherwise</param>
+ /// <returns>the compiled delegate</returns>
+ public static T Compile<T>(this Expression<T> lambda, bool emitDebugSymbols) {
+#if FEATURE_PDBEMIT && FEATURE_REFEMIT
+ if (emitDebugSymbols) {
+ return CompileToMethod(lambda, DebugInfoGenerator.CreatePdbGenerator(), true);
+ }
+#endif
+ return lambda.Compile();
+ }
+
+#if FEATURE_REFEMIT
+ /// <summary>
+ /// Compiles the LambdaExpression, emitting it into a new type, and
+ /// optionally making it debuggable.
+ ///
+ /// This is a workaround for a CLR limitiation: DynamicMethods cannot
+ /// have debugging information.
+ /// </summary>
+ /// <param name="lambda">the lambda to compile</param>
+ /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
+ /// <param name="emitDebugSymbols">True if debug symbols (PDBs) are emitted by the <paramref name="debugInfoGenerator"/>.</param>
+ /// <returns>the compiled delegate</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
+ public static T CompileToMethod<T>(Expression<T> lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
+ return (T)(object)CompileToMethod((LambdaExpression)lambda, debugInfoGenerator, emitDebugSymbols);
+ }
+
+ public static Delegate CompileToMethod(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
+ string methodName = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
+
+ var type = Snippets.Shared.DefineType(methodName, typeof(object), false, emitDebugSymbols).TypeBuilder;
+ var rewriter = new DebuggableCodeRewriter(type);
+ lambda = (LambdaExpression)rewriter.Visit(lambda);
+
+ //Create a unique method name when the lambda doesn't have a name or the name is empty.
+ var method = type.DefineMethod(methodName, CompilerHelpers.PublicStatic);
+
+ lambda.CompileToMethod(method, debugInfoGenerator);
+ var finished = type.CreateType();
+
+ rewriter.InitializeFields(finished);
+
+ return finished.GetMethod(method.Name).CreateDelegate(lambda.Type);
+ }
+
+ /// <summary>
+ /// Removes all live objects and places them in static fields of a type.
+ /// </summary>
+ private sealed class DebuggableCodeRewriter : DynamicExpressionVisitor {
+ private readonly Dictionary<object, FieldBuilder> _fields = new Dictionary<object, FieldBuilder>(ReferenceEqualityComparer<object>.Instance);
+ private readonly TypeBuilder _type;
+ private readonly HashSet<string> _methodNames = new HashSet<string>();
+
+ internal DebuggableCodeRewriter(TypeBuilder type) {
+ _type = type;
+ }
+
+ internal void InitializeFields(Type type) {
+ foreach (var pair in _fields) {
+ type.GetInheritedFields(pair.Value.Name).First().SetValue(null, pair.Key);
+ }
+ }
+
+ protected override Expression VisitLambda<T>(Expression<T> node) {
+ if (_methodNames.Contains(node.Name)) {
+ int count = _methodNames.Count;
+
+ string newName;
+ do {
+ newName = node.Name + "$" + count++;
+ } while (_methodNames.Contains(newName));
+
+ _methodNames.Add(newName);
+ return Expression.Lambda<T>(
+ base.Visit(node.Body),
+ newName,
+ node.TailCall,
+ node.Parameters
+ );
+ } else {
+ _methodNames.Add(node.Name);
+ return base.VisitLambda<T>(node);
+ }
+ }
+
+ protected override Expression VisitExtension(Expression node) {
+ // LightDynamicExpressions override Visit but we want to really reduce them
+ // because they reduce to DynamicExpressions.
+ LightDynamicExpression lightDyn = node as LightDynamicExpression;
+ if (lightDyn != null) {
+ return Visit(lightDyn.Reduce());
+ }
+
+ return Visit(node.Reduce());
+ }
+
+ protected override Expression VisitConstant(ConstantExpression node) {
+ if (CanEmitConstant(node.Value, node.Type)) {
+ return node;
+ }
+
+ FieldBuilder field;
+ if (!_fields.TryGetValue(node.Value, out field)) {
+ field = _type.DefineField(
+ "$constant" + _fields.Count,
+ GetVisibleType(node.Value.GetType()),
+ FieldAttributes.Public | FieldAttributes.Static
+ );
+ _fields.Add(node.Value, field);
+ }
+
+ Expression result = Expression.Field(null, field);
+ if (result.Type != node.Type) {
+ result = Expression.Convert(result, node.Type);
+ }
+ return result;
+ }
+
+ protected override Expression VisitDynamic(DynamicExpression node) {
+ return Visit(Reduce(node));
+ }
+ }
+#endif
+
+ public static string GetUniqueMethodName() {
+ return "lambda_method" + "$" + System.Threading.Interlocked.Increment(ref _Counter);
+ }
+
+#if FEATURE_LCG
+ // Matches ILGen.TryEmitConstant
+ public static bool CanEmitConstant(object value, Type type) {
+ if (value == null || CanEmitILConstant(type)) {
+ return true;
+ }
+
+ Type t = value as Type;
+ if (t != null && ILGen.ShouldLdtoken(t)) {
+ return true;
+ }
+
+ MethodBase mb = value as MethodBase;
+ if (mb != null && ILGen.ShouldLdtoken(mb)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ // Matches ILGen.TryEmitILConstant
+ internal static bool CanEmitILConstant(Type type) {
+ switch (type.GetTypeCode()) {
+ 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;
+ }
+#endif
+
+ /// <summary>
+ /// Reduces the provided DynamicExpression into site.Target(site, *args).
+ /// </summary>
+ public static Expression Reduce(DynamicExpression node) {
+ // Store the callsite as a constant
+ var siteConstant = AstUtils.Constant(CallSite.Create(node.DelegateType, node.Binder));
+
+ // ($site = siteExpr).Target.Invoke($site, *args)
+ var site = Expression.Variable(siteConstant.Type, "$site");
+ return Expression.Block(
+ new[] { site },
+ Expression.Call(
+ Expression.Field(
+ Expression.Assign(site, siteConstant),
+ siteConstant.Type.GetDeclaredField("Target")
+ ),
+ node.DelegateType.GetMethod("Invoke"),
+ ArrayUtils.Insert(site, node.Arguments)
+ )
+ );
+ }
+
+ #region Factories
+#if !FEATURE_NUMERICS
+ [CLSCompliant(false)]
+ public static BigInteger CreateBigInteger(int sign, uint[] data) {
+ return new BigInteger(sign, data);
+ }
+#else
+ public static BigInteger CreateBigInteger(bool isNegative, byte[] data) {
+ return new BigInteger(CreateBigInt(isNegative, data));
+ }
+
+ public static BigInt CreateBigInt(int value) {
+ return (BigInt)value;
+ }
+
+ public static BigInt CreateBigInt(long value) {
+ return (BigInt)value;
+ }
+
+ public static BigInt CreateBigInt(bool isNegative, byte[] data) {
+ BigInt res = new BigInt(data);
+ return isNegative ? -res : res;
+ }
+
+#endif
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/ConstantCheck.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/ConstantCheck.cs
new file mode 100644
index 00000000000..89cbbfe91cc
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/ConstantCheck.cs
@@ -0,0 +1,128 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System.Diagnostics;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Generation {
+
+ public static class ConstantCheck {
+
+ /// <summary>
+ /// Tests to see if the expression is a constant with the given value.
+ /// </summary>
+ /// <param name="expression">The expression to examine</param>
+ /// <param name="value">The constant value to check for.</param>
+ /// <returns>true/false</returns>
+ public static bool Check(Expression expression, object value) {
+ ContractUtils.RequiresNotNull(expression, "expression");
+ return IsConstant(expression, value);
+ }
+
+
+ /// <summary>
+ /// Tests to see if the expression is a constant with the given value.
+ /// </summary>
+ /// <param name="e">The expression to examine</param>
+ /// <param name="value">The constant value to check for.</param>
+ /// <returns>true/false</returns>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
+ internal static bool IsConstant(Expression e, object value) {
+ switch (e.NodeType) {
+ case ExpressionType.AndAlso:
+ return CheckAndAlso((BinaryExpression)e, value);
+
+ case ExpressionType.OrElse:
+ return CheckOrElse((BinaryExpression)e, value);
+
+ case ExpressionType.Constant:
+ return CheckConstant((ConstantExpression)e, value);
+
+ case ExpressionType.TypeIs:
+ return Check((TypeBinaryExpression)e, value);
+
+ default:
+ return false;
+ }
+ }
+
+ //CONFORMING
+ internal static bool IsNull(Expression e) {
+ return IsConstant(e, null);
+ }
+
+
+ private static bool CheckAndAlso(BinaryExpression node, object value) {
+ Debug.Assert(node.NodeType == ExpressionType.AndAlso);
+
+ if (node.Method != null) {
+ return false;
+ }
+ //TODO: we can propagate through conversion, but it may not worth it.
+ if (node.Conversion != null) {
+ return false;
+ }
+
+ if (value is bool) {
+ if ((bool)value) {
+ return IsConstant(node.Left, true) && IsConstant(node.Right, true);
+ } else {
+ // if left isn't a constant it has to be evaluated
+ return IsConstant(node.Left, false);
+ }
+ }
+ return false;
+ }
+
+ private static bool CheckOrElse(BinaryExpression node, object value) {
+ Debug.Assert(node.NodeType == ExpressionType.OrElse);
+
+ if (node.Method != null) {
+ return false;
+ }
+
+ if (value is bool) {
+ if ((bool)value) {
+ return IsConstant(node.Left, true);
+ } else {
+ return IsConstant(node.Left, false) && IsConstant(node.Right, false);
+ }
+ }
+ return false;
+ }
+
+ private static bool CheckConstant(ConstantExpression node, object value) {
+ if (value == null) {
+ return node.Value == null;
+ } else {
+ return value.Equals(node.Value);
+ }
+ }
+
+ private static bool Check(TypeBinaryExpression node, object value) {
+ // allow constant TypeIs expressions to be optimized away
+ if (value is bool && ((bool)value) == true) {
+ return node.TypeOperand.IsAssignableFrom(node.Expression.Type);
+ }
+ return false;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.Generated.cs
new file mode 100644
index 00000000000..2b5bd93d0fa
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.Generated.cs
@@ -0,0 +1,110 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Linq;
+using System.Diagnostics;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Generation {
+ internal static partial class DelegateHelpers {
+
+ #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
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ internal static Type MakeDelegate(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 MakeCustomDelegate(types);
+ }
+
+ Type returnType = types[types.Length - 1];
+ if (returnType == typeof(void)) {
+ types = types.RemoveLast();
+ 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
+ }
+ } else {
+ 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
+ }
+ }
+ throw Assert.Unreachable;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.cs
new file mode 100644
index 00000000000..b2ef101c769
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Generation/DelegateHelpers.cs
@@ -0,0 +1,87 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+using System.Threading;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Generation {
+ internal static partial class DelegateHelpers {
+
+ private static Dictionary<ICollection<Type>, Type> _DelegateTypes;
+
+ private static Type MakeCustomDelegate(Type[] types) {
+ if (_DelegateTypes == null) {
+ Interlocked.CompareExchange(
+ ref _DelegateTypes,
+ new Dictionary<ICollection<Type>, Type>(ListEqualityComparer<Type>.Instance),
+ null
+ );
+ }
+
+ bool found;
+ Type type;
+
+ //
+ // LOCK to retrieve the delegate type, if any
+ //
+
+ lock (_DelegateTypes) {
+ found = _DelegateTypes.TryGetValue(types, out type);
+ }
+
+ if (!found && type != null) {
+ return type;
+ }
+
+ //
+ // Create new delegate type
+ //
+
+ type = MakeNewCustomDelegate(types);
+
+ //
+ // LOCK to insert new delegate into the cache. If we already have one (racing threads), use the one from the cache
+ //
+
+ lock (_DelegateTypes) {
+ Type conflict;
+ if (_DelegateTypes.TryGetValue(types, out conflict) && conflict != null) {
+ type = conflict;
+ } else {
+ _DelegateTypes[types] = type;
+ }
+ }
+
+ return type;
+ }
+
+ private static Type MakeNewCustomDelegate(Type[] types) {
+#if FEATURE_REFEMIT
+ Type returnType = types[types.Length - 1];
+ Type[] parameters = types.RemoveLast();
+
+ return Snippets.Shared.DefineDelegate("Delegate" + types.Length, returnType, parameters);
+#else
+ throw new NotSupportedException("Signature not supported on this platform");
+#endif
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/BranchLabel.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/BranchLabel.cs
new file mode 100644
index 00000000000..de0b6db37c4
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/BranchLabel.cs
@@ -0,0 +1,108 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal struct RuntimeLabel {
+ public readonly int Index;
+ public readonly int StackDepth;
+ public readonly int ContinuationStackDepth;
+
+ public RuntimeLabel(int index, int continuationStackDepth, int stackDepth) {
+ Index = index;
+ ContinuationStackDepth = continuationStackDepth;
+ StackDepth = stackDepth;
+ }
+
+ public override string ToString() {
+ return String.Format("->{0} C({1}) S({2})", Index, ContinuationStackDepth, StackDepth);
+ }
+ }
+
+ public sealed class BranchLabel {
+ internal const int UnknownIndex = Int32.MinValue;
+ internal const int UnknownDepth = Int32.MinValue;
+
+ internal int _labelIndex = UnknownIndex;
+ internal int _targetIndex = UnknownIndex;
+ internal int _stackDepth = UnknownDepth;
+ internal int _continuationStackDepth = UnknownDepth;
+
+ // Offsets of forward branching instructions targetting this label
+ // that need to be updated after we emit the label.
+ private List<int> _forwardBranchFixups;
+
+ public BranchLabel() {
+ }
+
+ internal int LabelIndex {
+ get { return _labelIndex; }
+ set { _labelIndex = value; }
+ }
+
+ internal bool HasRuntimeLabel {
+ get { return _labelIndex != UnknownIndex; }
+ }
+
+ internal int TargetIndex {
+ get { return _targetIndex; }
+ }
+
+ internal RuntimeLabel ToRuntimeLabel() {
+ Debug.Assert(_targetIndex != UnknownIndex && _stackDepth != UnknownDepth && _continuationStackDepth != UnknownDepth);
+ return new RuntimeLabel(_targetIndex, _continuationStackDepth, _stackDepth);
+ }
+
+ internal void Mark(InstructionList instructions) {
+ ContractUtils.Requires(_targetIndex == UnknownIndex && _stackDepth == UnknownDepth && _continuationStackDepth == UnknownDepth);
+
+ _stackDepth = instructions.CurrentStackDepth;
+ _continuationStackDepth = instructions.CurrentContinuationsDepth;
+ _targetIndex = instructions.Count;
+
+ if (_forwardBranchFixups != null) {
+ foreach (var branchIndex in _forwardBranchFixups) {
+ FixupBranch(instructions, branchIndex);
+ }
+ _forwardBranchFixups = null;
+ }
+ }
+
+ internal void AddBranch(InstructionList instructions, int branchIndex) {
+ Debug.Assert(((_targetIndex == UnknownIndex) == (_stackDepth == UnknownDepth)));
+ Debug.Assert(((_targetIndex == UnknownIndex) == (_continuationStackDepth == UnknownDepth)));
+
+ if (_targetIndex == UnknownIndex) {
+ if (_forwardBranchFixups == null) {
+ _forwardBranchFixups = new List<int>();
+ }
+ _forwardBranchFixups.Add(branchIndex);
+ } else {
+ FixupBranch(instructions, branchIndex);
+ }
+ }
+
+ internal void FixupBranch(InstructionList instructions, int branchIndex) {
+ Debug.Assert(_targetIndex != UnknownIndex);
+ instructions.FixupBranch(branchIndex, _targetIndex - branchIndex);
+ }
+ }
+
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/ILightCallSiteBinder.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/ILightCallSiteBinder.cs
new file mode 100644
index 00000000000..8535961f86b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/ILightCallSiteBinder.cs
@@ -0,0 +1,34 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+using System.Reflection;
+using Microsoft.Scripting.Interpreter;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+
+namespace Microsoft.Scripting.Interpreter {
+ public interface ILightCallSiteBinder {
+ bool AcceptsArgumentArray { get; }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs
new file mode 100644
index 00000000000..c6b7eb8d829
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs
@@ -0,0 +1,243 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Diagnostics;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal abstract class AddInstruction : Instruction {
+ private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private AddInstruction() {
+ }
+
+ internal sealed class AddInt32 : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(unchecked((Int32)l + (Int32)r));
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddInt16 : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Int16)unchecked((Int16)l + (Int16)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddInt64 : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Int64)unchecked((Int64)l + (Int64)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddUInt16 : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt16)unchecked((UInt16)l + (UInt16)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddUInt32 : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt32)unchecked((UInt32)l + (UInt32)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddUInt64 : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt64)unchecked((Int16)l + (Int16)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddSingle : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Single)((Single)l + (Single)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddDouble : AddInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Double)l + (Double)r;
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ public static Instruction Create(Type type) {
+ Debug.Assert(!type.IsEnum());
+ switch (type.GetTypeCode()) {
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new AddInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new AddInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new AddInt64());
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new AddUInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new AddUInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new AddUInt64());
+ case TypeCode.Single: return _Single ?? (_Single = new AddSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new AddDouble());
+
+ default:
+ throw Assert.Unreachable;
+ }
+ }
+
+ public override string ToString() {
+ return "Add()";
+ }
+ }
+
+ internal abstract class AddOvfInstruction : Instruction {
+ private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private AddOvfInstruction() {
+ }
+
+ internal sealed class AddOvfInt32 : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(checked((Int32)l + (Int32)r));
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfInt16 : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Int16)checked((Int16)l + (Int16)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfInt64 : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Int64)checked((Int64)l + (Int64)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfUInt16 : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt16)checked((UInt16)l + (UInt16)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfUInt32 : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt32)checked((UInt32)l + (UInt32)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfUInt64 : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt64)checked((Int16)l + (Int16)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfSingle : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Single)((Single)l + (Single)r);
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ internal sealed class AddOvfDouble : AddOvfInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Double)l + (Double)r;
+ frame.StackIndex--;
+ return +1;
+ }
+ }
+
+ public static Instruction Create(Type type) {
+ Debug.Assert(!type.IsEnum());
+ switch (type.GetTypeCode()) {
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new AddOvfInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new AddOvfInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new AddOvfInt64());
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new AddOvfUInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new AddOvfUInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new AddOvfUInt64());
+ case TypeCode.Single: return _Single ?? (_Single = new AddOvfSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new AddOvfDouble());
+
+ default:
+ throw Assert.Unreachable;
+ }
+ }
+
+ public override string ToString() {
+ return "AddOvf()";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ArrayOperations.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ArrayOperations.cs
new file mode 100644
index 00000000000..0c5a9e16a7b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ArrayOperations.cs
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+
+namespace Microsoft.Scripting.Interpreter {
+ public sealed class NewArrayInitInstruction<TElement> : Instruction {
+ private readonly int _elementCount;
+
+ internal NewArrayInitInstruction(int elementCount) {
+ _elementCount = elementCount;
+ }
+
+ public override int ConsumedStack { get { return _elementCount; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ TElement[] array = new TElement[_elementCount];
+ for (int i = _elementCount - 1; i >= 0; i--) {
+ array[i] = (TElement)frame.Pop();
+ }
+ frame.Push(array);
+ return +1;
+ }
+ }
+
+ public sealed class NewArrayInstruction<TElement> : Instruction {
+ internal NewArrayInstruction() { }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ int length = (int)frame.Pop();
+ frame.Push(new TElement[length]);
+ return +1;
+ }
+ }
+
+ public sealed class NewArrayBoundsInstruction : Instruction {
+ private readonly Type _elementType;
+ private readonly int _rank;
+
+ internal NewArrayBoundsInstruction(Type elementType, int rank) {
+ _elementType = elementType;
+ _rank = rank;
+ }
+
+ public override int ConsumedStack { get { return _rank; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var lengths = new int[_rank];
+ for (int i = _rank - 1; i >= 0; i--) {
+ lengths[i] = (int)frame.Pop();
+ }
+ var array = Array.CreateInstance(_elementType, lengths);
+ frame.Push(array);
+ return +1;
+ }
+ }
+
+ public sealed class GetArrayItemInstruction<TElement> : Instruction {
+ internal GetArrayItemInstruction() { }
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ int index = (int)frame.Pop();
+ TElement[] array = (TElement[])frame.Pop();
+ frame.Push(array[index]);
+ return +1;
+ }
+
+ public override string InstructionName {
+ get { return "GetArrayItem"; }
+ }
+ }
+
+ public sealed class SetArrayItemInstruction<TElement> : Instruction {
+ internal SetArrayItemInstruction() { }
+
+ public override int ConsumedStack { get { return 3; } }
+ public override int ProducedStack { get { return 0; } }
+
+ public override int Run(InterpretedFrame frame) {
+ TElement value = (TElement)frame.Pop();
+ int index = (int)frame.Pop();
+ TElement[] array = (TElement[])frame.Pop();
+ array[index] = value;
+ return +1;
+ }
+
+ public override string InstructionName {
+ get { return "SetArrayItem"; }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.Generated.cs
new file mode 100644
index 00000000000..19163eedc6e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.Generated.cs
@@ -0,0 +1,905 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, please send an email to
+ * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Threading;
+using Microsoft.Scripting.Utils;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Runtime;
+
+using System.Dynamic;
+
+namespace Microsoft.Scripting.Interpreter {
+ #region Generated Reflected Caller
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_all from: generate_reflected_calls.py
+
+ public partial class CallInstruction {
+ private const int MaxHelpers = 10;
+ private const int MaxArgs = 3;
+
+ public virtual object InvokeInstance(object instance, params object[] args) {
+ switch(args.Length) {
+ case 0: return Invoke(instance);
+ case 1: return Invoke(instance, args[0]);
+ case 2: return Invoke(instance, args[0], args[1]);
+ case 3: return Invoke(instance, args[0], args[1], args[2]);
+ case 4: return Invoke(instance, args[0], args[1], args[2], args[3]);
+ case 5: return Invoke(instance, args[0], args[1], args[2], args[3], args[4]);
+ case 6: return Invoke(instance, args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return Invoke(instance, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ case 8: return Invoke(instance, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ public virtual object Invoke(params object[] args) {
+ switch(args.Length) {
+ case 0: return Invoke();
+ case 1: return Invoke(args[0]);
+ case 2: return Invoke(args[0], args[1]);
+ case 3: return Invoke(args[0], args[1], args[2]);
+ case 4: return Invoke(args[0], args[1], args[2], args[3]);
+ case 5: return Invoke(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return Invoke(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return Invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ case 8: return Invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ case 9: return Invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
+ default: throw new InvalidOperationException();
+ }
+ }
+
+ public virtual object Invoke() { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2, object arg3) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7) { throw new InvalidOperationException(); }
+ public virtual object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8) { throw new InvalidOperationException(); }
+
+ /// <summary>
+ /// Fast creation works if we have a known primitive types for the entire
+ /// method siganture. If we have any non-primitive types then FastCreate
+ /// falls back to SlowCreate which works for all types.
+ ///
+ /// Fast creation is fast because it avoids using reflection (MakeGenericType
+ /// and Activator.CreateInstance) to create the types. It does this through
+ /// calling a series of generic methods picking up each strong type of the
+ /// signature along the way. When it runs out of types it news up the
+ /// appropriate CallInstruction with the strong-types that have been built up.
+ ///
+ /// One relaxation is that for return types which are non-primitive types
+ /// we can fallback to object due to relaxed delegates.
+ /// </summary>
+ private static CallInstruction FastCreate(MethodInfo target, ParameterInfo[] pi) {
+ Type t = TryGetParameterOrReturnType(target, pi, 0);
+ if (t == null) {
+ return new ActionCallInstruction(target);
+ }
+
+ if (t.IsEnum()) return SlowCreate(target, pi);
+ switch (t.GetTypeCode()) {
+ case TypeCode.Object: {
+ if (t != typeof(object) && (IndexIsNotReturnType(0, target, pi) || t.IsValueType())) {
+ // if we're on the return type relaxed delegates makes it ok to use object
+ goto default;
+ }
+ return FastCreate<Object>(target, pi);
+ }
+ case TypeCode.Int16: return FastCreate<Int16>(target, pi);
+ case TypeCode.Int32: return FastCreate<Int32>(target, pi);
+ case TypeCode.Int64: return FastCreate<Int64>(target, pi);
+ case TypeCode.Boolean: return FastCreate<Boolean>(target, pi);
+ case TypeCode.Char: return FastCreate<Char>(target, pi);
+ case TypeCode.Byte: return FastCreate<Byte>(target, pi);
+ case TypeCode.Decimal: return FastCreate<Decimal>(target, pi);
+ case TypeCode.DateTime: return FastCreate<DateTime>(target, pi);
+ case TypeCode.Double: return FastCreate<Double>(target, pi);
+ case TypeCode.Single: return FastCreate<Single>(target, pi);
+ case TypeCode.UInt16: return FastCreate<UInt16>(target, pi);
+ case TypeCode.UInt32: return FastCreate<UInt32>(target, pi);
+ case TypeCode.UInt64: return FastCreate<UInt64>(target, pi);
+ case TypeCode.String: return FastCreate<String>(target, pi);
+ case TypeCode.SByte: return FastCreate<SByte>(target, pi);
+ default: return SlowCreate(target, pi);
+ }
+ }
+
+ private static CallInstruction FastCreate<T0>(MethodInfo target, ParameterInfo[] pi) {
+ Type t = TryGetParameterOrReturnType(target, pi, 1);
+ if (t == null) {
+ if (target.ReturnType == typeof(void)) {
+ return new ActionCallInstruction<T0>(target);
+ }
+ return new FuncCallInstruction<T0>(target);
+ }
+
+ if (t.IsEnum()) return SlowCreate(target, pi);
+ switch (t.GetTypeCode()) {
+ case TypeCode.Object: {
+ if (t != typeof(object) && (IndexIsNotReturnType(1, target, pi) || t.IsValueType())) {
+ // if we're on the return type relaxed delegates makes it ok to use object
+ goto default;
+ }
+ return FastCreate<T0, Object>(target, pi);
+ }
+ case TypeCode.Int16: return FastCreate<T0, Int16>(target, pi);
+ case TypeCode.Int32: return FastCreate<T0, Int32>(target, pi);
+ case TypeCode.Int64: return FastCreate<T0, Int64>(target, pi);
+ case TypeCode.Boolean: return FastCreate<T0, Boolean>(target, pi);
+ case TypeCode.Char: return FastCreate<T0, Char>(target, pi);
+ case TypeCode.Byte: return FastCreate<T0, Byte>(target, pi);
+ case TypeCode.Decimal: return FastCreate<T0, Decimal>(target, pi);
+ case TypeCode.DateTime: return FastCreate<T0, DateTime>(target, pi);
+ case TypeCode.Double: return FastCreate<T0, Double>(target, pi);
+ case TypeCode.Single: return FastCreate<T0, Single>(target, pi);
+ case TypeCode.UInt16: return FastCreate<T0, UInt16>(target, pi);
+ case TypeCode.UInt32: return FastCreate<T0, UInt32>(target, pi);
+ case TypeCode.UInt64: return FastCreate<T0, UInt64>(target, pi);
+ case TypeCode.String: return FastCreate<T0, String>(target, pi);
+ case TypeCode.SByte: return FastCreate<T0, SByte>(target, pi);
+ default: return SlowCreate(target, pi);
+ }
+ }
+
+ private static CallInstruction FastCreate<T0, T1>(MethodInfo target, ParameterInfo[] pi) {
+ Type t = TryGetParameterOrReturnType(target, pi, 2);
+ if (t == null) {
+ if (target.ReturnType == typeof(void)) {
+ return new ActionCallInstruction<T0, T1>(target);
+ }
+ return new FuncCallInstruction<T0, T1>(target);
+ }
+
+ if (t.IsEnum()) return SlowCreate(target, pi);
+ switch (t.GetTypeCode()) {
+ case TypeCode.Object: {
+ Debug.Assert(pi.Length == 2);
+ if (t.IsValueType()) goto default;
+
+ return new FuncCallInstruction<T0, T1, Object>(target);
+ }
+ case TypeCode.Int16: return new FuncCallInstruction<T0, T1, Int16>(target);
+ case TypeCode.Int32: return new FuncCallInstruction<T0, T1, Int32>(target);
+ case TypeCode.Int64: return new FuncCallInstruction<T0, T1, Int64>(target);
+ case TypeCode.Boolean: return new FuncCallInstruction<T0, T1, Boolean>(target);
+ case TypeCode.Char: return new FuncCallInstruction<T0, T1, Char>(target);
+ case TypeCode.Byte: return new FuncCallInstruction<T0, T1, Byte>(target);
+ case TypeCode.Decimal: return new FuncCallInstruction<T0, T1, Decimal>(target);
+ case TypeCode.DateTime: return new FuncCallInstruction<T0, T1, DateTime>(target);
+ case TypeCode.Double: return new FuncCallInstruction<T0, T1, Double>(target);
+ case TypeCode.Single: return new FuncCallInstruction<T0, T1, Single>(target);
+ case TypeCode.UInt16: return new FuncCallInstruction<T0, T1, UInt16>(target);
+ case TypeCode.UInt32: return new FuncCallInstruction<T0, T1, UInt32>(target);
+ case TypeCode.UInt64: return new FuncCallInstruction<T0, T1, UInt64>(target);
+ case TypeCode.String: return new FuncCallInstruction<T0, T1, String>(target);
+ case TypeCode.SByte: return new FuncCallInstruction<T0, T1, SByte>(target);
+ default: return SlowCreate(target, pi);
+ }
+ }
+
+ private static Type GetHelperType(MethodInfo info, Type[] arrTypes) {
+ Type t;
+ if (info.ReturnType == typeof(void)) {
+ switch (arrTypes.Length) {
+ case 0: t = typeof(ActionCallInstruction); break;
+ case 1: t = typeof(ActionCallInstruction<>).MakeGenericType(arrTypes); break;
+ case 2: t = typeof(ActionCallInstruction<,>).MakeGenericType(arrTypes); break;
+ case 3: t = typeof(ActionCallInstruction<,,>).MakeGenericType(arrTypes); break;
+ case 4: t = typeof(ActionCallInstruction<,,,>).MakeGenericType(arrTypes); break;
+ case 5: t = typeof(ActionCallInstruction<,,,,>).MakeGenericType(arrTypes); break;
+ case 6: t = typeof(ActionCallInstruction<,,,,,>).MakeGenericType(arrTypes); break;
+ case 7: t = typeof(ActionCallInstruction<,,,,,,>).MakeGenericType(arrTypes); break;
+ case 8: t = typeof(ActionCallInstruction<,,,,,,,>).MakeGenericType(arrTypes); break;
+ case 9: t = typeof(ActionCallInstruction<,,,,,,,,>).MakeGenericType(arrTypes); break;
+ default: throw new InvalidOperationException();
+ }
+ } else {
+ switch (arrTypes.Length) {
+ case 1: t = typeof(FuncCallInstruction<>).MakeGenericType(arrTypes); break;
+ case 2: t = typeof(FuncCallInstruction<,>).MakeGenericType(arrTypes); break;
+ case 3: t = typeof(FuncCallInstruction<,,>).MakeGenericType(arrTypes); break;
+ case 4: t = typeof(FuncCallInstruction<,,,>).MakeGenericType(arrTypes); break;
+ case 5: t = typeof(FuncCallInstruction<,,,,>).MakeGenericType(arrTypes); break;
+ case 6: t = typeof(FuncCallInstruction<,,,,,>).MakeGenericType(arrTypes); break;
+ case 7: t = typeof(FuncCallInstruction<,,,,,,>).MakeGenericType(arrTypes); break;
+ case 8: t = typeof(FuncCallInstruction<,,,,,,,>).MakeGenericType(arrTypes); break;
+ case 9: t = typeof(FuncCallInstruction<,,,,,,,,>).MakeGenericType(arrTypes); break;
+ case 10: t = typeof(FuncCallInstruction<,,,,,,,,,>).MakeGenericType(arrTypes); break;
+ default: throw new InvalidOperationException();
+ }
+ }
+ return t;
+ }
+ public static MethodInfo CacheFunc<TRet>(Func<TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, TRet>(Func<T0, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, TRet>(Func<T0, T1, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, TRet>(Func<T0, T1, T2, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, T3, TRet>(Func<T0, T1, T2, T3, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, T3, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, T3, T4, TRet>(Func<T0, T1, T2, T3, T4, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, T3, T4, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, T3, T4, T5, TRet>(Func<T0, T1, T2, T3, T4, T5, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, T3, T4, T5, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, T3, T4, T5, T6, TRet>(Func<T0, T1, T2, T3, T4, T5, T6, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, T3, T4, T5, T6, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(Func<T0, T1, T2, T3, T4, T5, T6, T7, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheFunc<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new FuncCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction(Action method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0>(Action<T0> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1>(Action<T0, T1> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2>(Action<T0, T1, T2> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2, T3>(Action<T0, T1, T2, T3> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2, T3>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2, T3, T4>(Action<T0, T1, T2, T3, T4> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2, T3, T4>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2, T3, T4, T5>(Action<T0, T1, T2, T3, T4, T5> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2, T3, T4, T5>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2, T3, T4, T5, T6>(Action<T0, T1, T2, T3, T4, T5, T6> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2, T3, T4, T5, T6>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2, T3, T4, T5, T6, T7>(Action<T0, T1, T2, T3, T4, T5, T6, T7> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7>(method);
+ }
+ return info;
+ }
+
+ public static MethodInfo CacheAction<T0, T1, T2, T3, T4, T5, T6, T7, T8>(Action<T0, T1, T2, T3, T4, T5, T6, T7, T8> method) {
+ var info = method.GetMethodInfo();
+ lock (_cache) {
+ _cache[info] = new ActionCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8>(method);
+ }
+ return info;
+ }
+
+ }
+
+ internal sealed class ActionCallInstruction : CallInstruction {
+ private readonly Action _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 0; } }
+
+ public ActionCallInstruction(Action target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action)target.CreateDelegate(typeof(Action));
+ }
+
+ public override object Invoke() {
+ _target();
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target();
+ frame.StackIndex -= 0;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0> : CallInstruction {
+ private readonly Action<T0> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 1; } }
+
+ public ActionCallInstruction(Action<T0> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0>)target.CreateDelegate(typeof(Action<T0>));
+ }
+
+ public override object Invoke(object arg0) {
+ _target(arg0 != null ? (T0)arg0 : default(T0));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 1;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1> : CallInstruction {
+ private readonly Action<T0, T1> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 2; } }
+
+ public ActionCallInstruction(Action<T0, T1> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1>)target.CreateDelegate(typeof(Action<T0, T1>));
+ }
+
+ public override object Invoke(object arg0, object arg1) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 2], (T1)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 2;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2> : CallInstruction {
+ private readonly Action<T0, T1, T2> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 3; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2>)target.CreateDelegate(typeof(Action<T0, T1, T2>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 3], (T1)frame.Data[frame.StackIndex - 2], (T2)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 3;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2, T3> : CallInstruction {
+ private readonly Action<T0, T1, T2, T3> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 4; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2, T3> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2, T3>)target.CreateDelegate(typeof(Action<T0, T1, T2, T3>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 4], (T1)frame.Data[frame.StackIndex - 3], (T2)frame.Data[frame.StackIndex - 2], (T3)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 4;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2, T3, T4> : CallInstruction {
+ private readonly Action<T0, T1, T2, T3, T4> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 5; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2, T3, T4> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2, T3, T4>)target.CreateDelegate(typeof(Action<T0, T1, T2, T3, T4>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 5], (T1)frame.Data[frame.StackIndex - 4], (T2)frame.Data[frame.StackIndex - 3], (T3)frame.Data[frame.StackIndex - 2], (T4)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 5;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2, T3, T4, T5> : CallInstruction {
+ private readonly Action<T0, T1, T2, T3, T4, T5> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 6; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2, T3, T4, T5> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2, T3, T4, T5>)target.CreateDelegate(typeof(Action<T0, T1, T2, T3, T4, T5>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 6], (T1)frame.Data[frame.StackIndex - 5], (T2)frame.Data[frame.StackIndex - 4], (T3)frame.Data[frame.StackIndex - 3], (T4)frame.Data[frame.StackIndex - 2], (T5)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 6;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2, T3, T4, T5, T6> : CallInstruction {
+ private readonly Action<T0, T1, T2, T3, T4, T5, T6> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 7; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2, T3, T4, T5, T6> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2, T3, T4, T5, T6>)target.CreateDelegate(typeof(Action<T0, T1, T2, T3, T4, T5, T6>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5), arg6 != null ? (T6)arg6 : default(T6));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 7], (T1)frame.Data[frame.StackIndex - 6], (T2)frame.Data[frame.StackIndex - 5], (T3)frame.Data[frame.StackIndex - 4], (T4)frame.Data[frame.StackIndex - 3], (T5)frame.Data[frame.StackIndex - 2], (T6)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 7;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7> : CallInstruction {
+ private readonly Action<T0, T1, T2, T3, T4, T5, T6, T7> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 8; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2, T3, T4, T5, T6, T7> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2, T3, T4, T5, T6, T7>)target.CreateDelegate(typeof(Action<T0, T1, T2, T3, T4, T5, T6, T7>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5), arg6 != null ? (T6)arg6 : default(T6), arg7 != null ? (T7)arg7 : default(T7));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 8], (T1)frame.Data[frame.StackIndex - 7], (T2)frame.Data[frame.StackIndex - 6], (T3)frame.Data[frame.StackIndex - 5], (T4)frame.Data[frame.StackIndex - 4], (T5)frame.Data[frame.StackIndex - 3], (T6)frame.Data[frame.StackIndex - 2], (T7)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 8;
+ return 1;
+ }
+ }
+
+ internal sealed class ActionCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8> : CallInstruction {
+ private readonly Action<T0, T1, T2, T3, T4, T5, T6, T7, T8> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 9; } }
+
+ public ActionCallInstruction(Action<T0, T1, T2, T3, T4, T5, T6, T7, T8> target) {
+ _target = target;
+ }
+
+ public ActionCallInstruction(MethodInfo target) {
+ _target = (Action<T0, T1, T2, T3, T4, T5, T6, T7, T8>)target.CreateDelegate(typeof(Action<T0, T1, T2, T3, T4, T5, T6, T7, T8>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8) {
+ _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5), arg6 != null ? (T6)arg6 : default(T6), arg7 != null ? (T7)arg7 : default(T7), arg8 != null ? (T8)arg8 : default(T8));
+ return null;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ _target((T0)frame.Data[frame.StackIndex - 9], (T1)frame.Data[frame.StackIndex - 8], (T2)frame.Data[frame.StackIndex - 7], (T3)frame.Data[frame.StackIndex - 6], (T4)frame.Data[frame.StackIndex - 5], (T5)frame.Data[frame.StackIndex - 4], (T6)frame.Data[frame.StackIndex - 3], (T7)frame.Data[frame.StackIndex - 2], (T8)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 9;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<TRet> : CallInstruction {
+ private readonly Func<TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 0; } }
+
+ public FuncCallInstruction(Func<TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<TRet>)target.CreateDelegate(typeof(Func<TRet>));
+ }
+
+ public override object Invoke() {
+ return _target();
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 0] = _target();
+ frame.StackIndex -= -1;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, TRet> : CallInstruction {
+ private readonly Func<T0, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 1; } }
+
+ public FuncCallInstruction(Func<T0, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, TRet>)target.CreateDelegate(typeof(Func<T0, TRet>));
+ }
+
+ public override object Invoke(object arg0) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 1] = _target((T0)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 0;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, TRet> : CallInstruction {
+ private readonly Func<T0, T1, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 2; } }
+
+ public FuncCallInstruction(Func<T0, T1, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, TRet>)target.CreateDelegate(typeof(Func<T0, T1, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 2] = _target((T0)frame.Data[frame.StackIndex - 2], (T1)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 1;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 3; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 3] = _target((T0)frame.Data[frame.StackIndex - 3], (T1)frame.Data[frame.StackIndex - 2], (T2)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 2;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, T3, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, T3, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 4; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, T3, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, T3, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, T3, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 4] = _target((T0)frame.Data[frame.StackIndex - 4], (T1)frame.Data[frame.StackIndex - 3], (T2)frame.Data[frame.StackIndex - 2], (T3)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 3;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, T3, T4, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, T3, T4, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 5; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, T3, T4, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, T3, T4, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, T3, T4, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 5] = _target((T0)frame.Data[frame.StackIndex - 5], (T1)frame.Data[frame.StackIndex - 4], (T2)frame.Data[frame.StackIndex - 3], (T3)frame.Data[frame.StackIndex - 2], (T4)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 4;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, T3, T4, T5, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, T3, T4, T5, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 6; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, T3, T4, T5, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, T3, T4, T5, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, T3, T4, T5, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 6] = _target((T0)frame.Data[frame.StackIndex - 6], (T1)frame.Data[frame.StackIndex - 5], (T2)frame.Data[frame.StackIndex - 4], (T3)frame.Data[frame.StackIndex - 3], (T4)frame.Data[frame.StackIndex - 2], (T5)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 5;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, T3, T4, T5, T6, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, T3, T4, T5, T6, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 7; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, T3, T4, T5, T6, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, T3, T4, T5, T6, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, T3, T4, T5, T6, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5), arg6 != null ? (T6)arg6 : default(T6));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 7] = _target((T0)frame.Data[frame.StackIndex - 7], (T1)frame.Data[frame.StackIndex - 6], (T2)frame.Data[frame.StackIndex - 5], (T3)frame.Data[frame.StackIndex - 4], (T4)frame.Data[frame.StackIndex - 3], (T5)frame.Data[frame.StackIndex - 2], (T6)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 6;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, T3, T4, T5, T6, T7, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 8; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, T3, T4, T5, T6, T7, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, T3, T4, T5, T6, T7, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, T3, T4, T5, T6, T7, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5), arg6 != null ? (T6)arg6 : default(T6), arg7 != null ? (T7)arg7 : default(T7));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 8] = _target((T0)frame.Data[frame.StackIndex - 8], (T1)frame.Data[frame.StackIndex - 7], (T2)frame.Data[frame.StackIndex - 6], (T3)frame.Data[frame.StackIndex - 5], (T4)frame.Data[frame.StackIndex - 4], (T5)frame.Data[frame.StackIndex - 3], (T6)frame.Data[frame.StackIndex - 2], (T7)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 7;
+ return 1;
+ }
+ }
+
+ internal sealed class FuncCallInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet> : CallInstruction {
+ private readonly Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet> _target;
+ public override MethodInfo Info { get { return _target.GetMethodInfo(); } }
+ public override int ArgumentCount { get { return 9; } }
+
+ public FuncCallInstruction(Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet> target) {
+ _target = target;
+ }
+
+ public FuncCallInstruction(MethodInfo target) {
+ _target = (Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>)target.CreateDelegate(typeof(Func<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>));
+ }
+
+ public override object Invoke(object arg0, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8) {
+ return _target(arg0 != null ? (T0)arg0 : default(T0), arg1 != null ? (T1)arg1 : default(T1), arg2 != null ? (T2)arg2 : default(T2), arg3 != null ? (T3)arg3 : default(T3), arg4 != null ? (T4)arg4 : default(T4), arg5 != null ? (T5)arg5 : default(T5), arg6 != null ? (T6)arg6 : default(T6), arg7 != null ? (T7)arg7 : default(T7), arg8 != null ? (T8)arg8 : default(T8));
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 9] = _target((T0)frame.Data[frame.StackIndex - 9], (T1)frame.Data[frame.StackIndex - 8], (T2)frame.Data[frame.StackIndex - 7], (T3)frame.Data[frame.StackIndex - 6], (T4)frame.Data[frame.StackIndex - 5], (T5)frame.Data[frame.StackIndex - 4], (T6)frame.Data[frame.StackIndex - 3], (T7)frame.Data[frame.StackIndex - 2], (T8)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 8;
+ return 1;
+ }
+ }
+
+ internal sealed partial class MethodInfoCallInstruction : CallInstruction {
+ public override object Invoke() {
+ return InvokeWorker();
+ }
+ public override object Invoke(object arg0) {
+ return InvokeWorker(arg0);
+ }
+ public override object Invoke(object arg0, object arg1) {
+ return InvokeWorker(arg0, arg1);
+ }
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs
new file mode 100644
index 00000000000..fc69ed342e3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs
@@ -0,0 +1,296 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, please send an email to
+ * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+using System.Security;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ public abstract partial class CallInstruction : Instruction {
+ public abstract MethodInfo Info { get; }
+
+ /// <summary>
+ /// The number of arguments including "this" for instance methods.
+ /// </summary>
+ public abstract int ArgumentCount { get; }
+
+ #region Construction
+
+ internal CallInstruction() { }
+
+ private static readonly Dictionary<MethodInfo, CallInstruction> _cache = new Dictionary<MethodInfo, CallInstruction>();
+
+ /// <exception cref="SecurityException">Instruction can't be created due to insufficient privileges.</exception>
+ public static CallInstruction Create(MethodInfo info) {
+ return Create(info, info.GetParameters());
+ }
+
+ /// <exception cref="SecurityException">Instruction can't be created due to insufficient privileges.</exception>
+ public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters) {
+ int argumentCount = parameters.Length;
+ if (!info.IsStatic) {
+ argumentCount++;
+ }
+
+ // A workaround for CLR bug #796414 (Unable to create delegates for Array.Get/Set):
+ // T[]::Address - not supported by ETs due to T& return value
+ if (info.DeclaringType != null && info.DeclaringType.IsArray && (info.Name == "Get" || info.Name == "Set")) {
+ return GetArrayAccessor(info, argumentCount);
+ }
+
+ if (ReflectionUtils.IsDynamicMethod(info) || !info.IsStatic && info.DeclaringType.IsValueType()) {
+ return new MethodInfoCallInstruction(info, argumentCount);
+ }
+
+ if (argumentCount >= MaxHelpers) {
+ // no delegate for this size, fallback to reflection invoke
+ return new MethodInfoCallInstruction(info, argumentCount);
+ }
+
+ foreach (ParameterInfo pi in parameters) {
+ if (pi.ParameterType.IsByRef) {
+ // we don't support ref args via generics.
+ return new MethodInfoCallInstruction(info, argumentCount);
+ }
+ }
+
+ // see if we've created one w/ a delegate
+ CallInstruction res;
+ if (ShouldCache(info)) {
+ lock (_cache) {
+ if (_cache.TryGetValue(info, out res)) {
+ return res;
+ }
+ }
+ }
+
+ // create it
+ try {
+ if (argumentCount < MaxArgs) {
+ res = FastCreate(info, parameters);
+ } else {
+ res = SlowCreate(info, parameters);
+ }
+ } catch (TargetInvocationException tie) {
+ if (!(tie.InnerException is NotSupportedException)) {
+ throw tie.InnerException;
+ }
+
+ res = new MethodInfoCallInstruction(info, argumentCount);
+ } catch (NotSupportedException) {
+ // if Delegate.CreateDelegate can't handle the method fallback to
+ // the slow reflection version. For example this can happen w/
+ // a generic method defined on an interface and implemented on a class or
+ // a virtual generic method.
+ res = new MethodInfoCallInstruction(info, argumentCount);
+ }
+
+ // cache it for future users if it's a reasonable method to cache
+ if (ShouldCache(info)) {
+ lock (_cache) {
+ _cache[info] = res;
+ }
+ }
+
+ return res;
+ }
+
+ private static CallInstruction GetArrayAccessor(MethodInfo info, int argumentCount) {
+ Type arrayType = info.DeclaringType;
+ bool isGetter = info.Name == "Get";
+ switch (arrayType.GetArrayRank()) {
+ case 1:
+ return Create(isGetter ?
+ arrayType.GetMethod("GetValue", new[] { typeof(int)}) :
+ new Action<Array, int, object>(ArrayItemSetter1).GetMethodInfo()
+ );
+
+ case 2:
+ return Create(isGetter ?
+ arrayType.GetMethod("GetValue", new[] { typeof(int), typeof(int) }) :
+ new Action<Array, int, int, object>(ArrayItemSetter2).GetMethodInfo()
+ );
+
+ case 3:
+ return Create(isGetter ?
+ arrayType.GetMethod("GetValue", new[] { typeof(int), typeof(int), typeof(int) }) :
+ new Action<Array, int, int, int, object>(ArrayItemSetter3).GetMethodInfo()
+ );
+
+ default:
+ return new MethodInfoCallInstruction(info, argumentCount);
+ }
+ }
+
+ public static void ArrayItemSetter1(Array array, int index0, object value) {
+ array.SetValue(value, index0);
+ }
+
+ public static void ArrayItemSetter2(Array array, int index0, int index1, object value) {
+ array.SetValue(value, index0, index1);
+ }
+
+ public static void ArrayItemSetter3(Array array, int index0, int index1, int index2, object value) {
+ array.SetValue(value, index0, index1, index2);
+ }
+
+ private static bool ShouldCache(MethodInfo info) {
+ return !ReflectionUtils.IsDynamicMethod(info);
+ }
+
+ /// <summary>
+ /// Gets the next type or null if no more types are available.
+ /// </summary>
+ private static Type TryGetParameterOrReturnType(MethodInfo target, ParameterInfo[] pi, int index) {
+ if (!target.IsStatic) {
+ index--;
+ if (index < 0) {
+ return target.DeclaringType;
+ }
+ }
+
+ if (index < pi.Length) {
+ // next in signature
+ return pi[index].ParameterType;
+ }
+
+ if (target.ReturnType == typeof(void) || index > pi.Length) {
+ // no more parameters
+ return null;
+ }
+
+ // last parameter on Invoke is return type
+ return target.ReturnType;
+ }
+
+ private static bool IndexIsNotReturnType(int index, MethodInfo target, ParameterInfo[] pi) {
+ return pi.Length != index || (pi.Length == index && !target.IsStatic);
+ }
+
+ /// <summary>
+ /// Uses reflection to create new instance of the appropriate ReflectedCaller
+ /// </summary>
+ private static CallInstruction SlowCreate(MethodInfo info, ParameterInfo[] pis) {
+ List<Type> types = new List<Type>();
+ if (!info.IsStatic) types.Add(info.DeclaringType);
+ foreach (ParameterInfo pi in pis) {
+ types.Add(pi.ParameterType);
+ }
+ if (info.ReturnType != typeof(void)) {
+ types.Add(info.ReturnType);
+ }
+ Type[] arrTypes = types.ToArray();
+
+ return (CallInstruction)Activator.CreateInstance(GetHelperType(info, arrTypes), info);
+ }
+
+ #endregion
+
+ #region Instruction
+
+ public sealed override int ProducedStack { get { return Info.ReturnType == typeof(void) ? 0 : 1; } }
+ public sealed override int ConsumedStack { get { return ArgumentCount; } }
+
+ public sealed override string InstructionName {
+ get { return "Call"; }
+ }
+
+ public override string ToString() {
+ return "Call(" + Info + ")";
+ }
+
+ #endregion
+ }
+
+ internal sealed partial class MethodInfoCallInstruction : CallInstruction {
+ private readonly MethodInfo _target;
+ private readonly int _argumentCount;
+
+ public override MethodInfo Info { get { return _target; } }
+ public override int ArgumentCount { get { return _argumentCount; } }
+
+ internal MethodInfoCallInstruction(MethodInfo target, int argumentCount) {
+ _target = target;
+ _argumentCount = argumentCount;
+ }
+
+ public override object Invoke(params object[] args) {
+ return InvokeWorker(args);
+ }
+
+ public override object InvokeInstance(object instance, params object[] args) {
+ if (_target.IsStatic) {
+ try {
+ return _target.Invoke(null, args);
+ } catch (TargetInvocationException e) {
+ throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ }
+ }
+
+ try {
+ return _target.Invoke(instance, args);
+ } catch (TargetInvocationException e) {
+ throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ }
+ }
+
+ private object InvokeWorker(params object[] args) {
+ if (_target.IsStatic) {
+ try {
+ return _target.Invoke(null, args);
+ } catch (TargetInvocationException e) {
+ throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ }
+ }
+
+ try {
+ return _target.Invoke(args[0], GetNonStaticArgs(args));
+ } catch (TargetInvocationException e) {
+ throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ }
+ }
+
+ private static object[] GetNonStaticArgs(object[] args) {
+ object[] newArgs = new object[args.Length - 1];
+ for (int i = 0; i < newArgs.Length; i++) {
+ newArgs[i] = args[i + 1];
+ }
+ return newArgs;
+ }
+
+ public sealed override int Run(InterpretedFrame frame) {
+ int first = frame.StackIndex - _argumentCount;
+ object[] args = new object[_argumentCount];
+ for (int i = 0; i < args.Length; i++) {
+ args[i] = frame.Data[first + i];
+ }
+
+ object ret = Invoke(args);
+ if (_target.ReturnType != typeof(void)) {
+ frame.Data[first] = ret;
+ frame.StackIndex = first + 1;
+ } else {
+ frame.StackIndex = first;
+ }
+ return 1;
+ }
+ }
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs
new file mode 100644
index 00000000000..376488e08f9
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs
@@ -0,0 +1,595 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_TASKS
+using System.Threading.Tasks;
+#endif
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using Microsoft.Scripting.Ast;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ using LoopFunc = Func<object[], StrongBox<object>[], InterpretedFrame, int>;
+
+ internal abstract class OffsetInstruction : Instruction {
+ internal const int Unknown = Int32.MinValue;
+ internal const int CacheSize = 32;
+
+ // the offset to jump to (relative to this instruction):
+ protected int _offset = Unknown;
+
+ public int Offset { get { return _offset; } }
+ public abstract Instruction[] Cache { get; }
+
+ public Instruction Fixup(int offset) {
+ Debug.Assert(_offset == Unknown && offset != Unknown);
+ _offset = offset;
+
+ var cache = Cache;
+ if (cache != null && offset >= 0 && offset < cache.Length) {
+ return cache[offset] ?? (cache[offset] = this);
+ }
+
+ return this;
+ }
+
+ public override string ToDebugString(int instructionIndex, object cookie, Func<int, int> labelIndexer, IList<object> objects) {
+ return ToString() + (_offset != Unknown ? " -> " + (instructionIndex + _offset).ToString() : "");
+ }
+
+ public override string ToString() {
+ return InstructionName + (_offset == Unknown ? "(?)" : "(" + _offset + ")");
+ }
+ }
+
+ internal sealed class BranchFalseInstruction : OffsetInstruction {
+ private static Instruction[] _cache;
+
+ public override Instruction[] Cache {
+ get {
+ if (_cache == null) {
+ _cache = new Instruction[CacheSize];
+ }
+ return _cache;
+ }
+ }
+
+ internal BranchFalseInstruction() {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ Debug.Assert(_offset != Unknown);
+
+ if (!(bool)frame.Pop()) {
+ return _offset;
+ }
+
+ return +1;
+ }
+ }
+
+ internal sealed class BranchTrueInstruction : OffsetInstruction {
+ private static Instruction[] _cache;
+
+ public override Instruction[] Cache {
+ get {
+ if (_cache == null) {
+ _cache = new Instruction[CacheSize];
+ }
+ return _cache;
+ }
+ }
+
+ internal BranchTrueInstruction() {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ Debug.Assert(_offset != Unknown);
+
+ if ((bool)frame.Pop()) {
+ return _offset;
+ }
+
+ return +1;
+ }
+ }
+
+ internal sealed class CoalescingBranchInstruction : OffsetInstruction {
+ private static Instruction[] _cache;
+
+ public override Instruction[] Cache {
+ get {
+ if (_cache == null) {
+ _cache = new Instruction[CacheSize];
+ }
+ return _cache;
+ }
+ }
+
+ internal CoalescingBranchInstruction() {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ Debug.Assert(_offset != Unknown);
+
+ if (frame.Peek() != null) {
+ return _offset;
+ }
+
+ return +1;
+ }
+ }
+
+ internal class BranchInstruction : OffsetInstruction {
+ private static Instruction[][][] _caches;
+
+ public override Instruction[] Cache {
+ get {
+ if (_caches == null) {
+ _caches = new Instruction[2][][] { new Instruction[2][], new Instruction[2][] };
+ }
+ return _caches[ConsumedStack][ProducedStack] ?? (_caches[ConsumedStack][ProducedStack] = new Instruction[CacheSize]);
+ }
+ }
+
+ internal readonly bool _hasResult;
+ internal readonly bool _hasValue;
+
+ internal BranchInstruction()
+ : this(false, false) {
+ }
+
+ public BranchInstruction(bool hasResult, bool hasValue) {
+ _hasResult = hasResult;
+ _hasValue = hasValue;
+ }
+
+ public override int ConsumedStack {
+ get { return _hasValue ? 1 : 0; }
+ }
+
+ public override int ProducedStack {
+ get { return _hasResult ? 1 : 0; }
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ Debug.Assert(_offset != Unknown);
+
+ return _offset;
+ }
+ }
+
+ internal abstract class IndexedBranchInstruction : Instruction {
+ protected const int CacheSize = 32;
+
+ internal readonly int _labelIndex;
+
+ public IndexedBranchInstruction(int labelIndex) {
+ _labelIndex = labelIndex;
+ }
+
+ public RuntimeLabel GetLabel(InterpretedFrame frame) {
+ return frame.Interpreter._labels[_labelIndex];
+ }
+
+ public override string ToDebugString(int instructionIndex, object cookie, Func<int, int> labelIndexer, IList<object> objects) {
+ int targetIndex = labelIndexer(_labelIndex);
+ return ToString() + (targetIndex != BranchLabel.UnknownIndex ? " -> " + targetIndex.ToString() : "");
+ }
+
+ public override string ToString() {
+ return InstructionName + "[" + _labelIndex + "]";
+ }
+ }
+
+ /// <summary>
+ /// This instruction implements a goto expression that can jump out of any expression.
+ /// It pops values (arguments) from the evaluation stack that the expression tree nodes in between
+ /// the goto expression and the target label node pushed and not consumed yet.
+ /// A goto expression can jump into a node that evaluates arguments only if it carries
+ /// a value and jumps right after the first argument (the carried value will be used as the first argument).
+ /// Goto can jump into an arbitrary child of a BlockExpression since the block doesn’t accumulate values
+ /// on evaluation stack as its child expressions are being evaluated.
+ ///
+ /// Goto needs to execute any finally blocks on the way to the target label.
+ /// <example>
+ /// {
+ /// f(1, 2, try { g(3, 4, try { goto L } finally { ... }, 6) } finally { ... }, 7, 8)
+ /// L: ...
+ /// }
+ /// </example>
+ /// The goto expression here jumps to label L while having 4 items on evaluation stack (1, 2, 3 and 4).
+ /// The jump needs to execute both finally blocks, the first one on stack level 4 the
+ /// second one on stack level 2. So, it needs to jump the first finally block, pop 2 items from the stack,
+ /// run second finally block and pop another 2 items from the stack and set instruction pointer to label L.
+ ///
+ /// Goto also needs to rethrow ThreadAbortException iff it jumps out of a catch handler and
+ /// the current thread is in "abort requested" state.
+ /// </summary>
+ internal sealed class GotoInstruction : IndexedBranchInstruction {
+ private const int Variants = 4;
+ private static readonly GotoInstruction[] Cache = new GotoInstruction[Variants * CacheSize];
+
+ private readonly bool _hasResult;
+
+ // TODO: We can remember hasValue in label and look it up when calculating stack balance. That would save some cache.
+ private readonly bool _hasValue;
+
+ // The values should technically be Consumed = 1, Produced = 1 for gotos that target a label whose continuation depth
+ // is different from the current continuation depth. However, in case of forward gotos, we don't not know that is the
+ // case until the label is emitted. By then the consumed and produced stack information is useless.
+ // The important thing here is that the stack balance is 0.
+ public override int ConsumedContinuations { get { return 0; } }
+ public override int ProducedContinuations { get { return 0; } }
+
+ public override int ConsumedStack {
+ get { return _hasValue ? 1 : 0; }
+ }
+
+ public override int ProducedStack {
+ get { return _hasResult ? 1 : 0; }
+ }
+
+ private GotoInstruction(int targetIndex, bool hasResult, bool hasValue)
+ : base(targetIndex) {
+ _hasResult = hasResult;
+ _hasValue = hasValue;
+ }
+
+ internal static GotoInstruction Create(int labelIndex, bool hasResult, bool hasValue) {
+ if (labelIndex < CacheSize) {
+ var index = Variants * labelIndex | (hasResult ? 2 : 0) | (hasValue ? 1 : 0);
+ return Cache[index] ?? (Cache[index] = new GotoInstruction(labelIndex, hasResult, hasValue));
+ }
+ return new GotoInstruction(labelIndex, hasResult, hasValue);
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ // Are we jumping out of catch/finally while aborting the current thread?
+ Interpreter.AbortThreadIfRequested(frame, _labelIndex);
+
+ // goto the target label or the current finally continuation:
+ return frame.Goto(_labelIndex, _hasValue ? frame.Pop() : Interpreter.NoValue);
+ }
+ }
+
+ internal sealed class EnterTryFinallyInstruction : IndexedBranchInstruction {
+ private readonly static EnterTryFinallyInstruction[] Cache = new EnterTryFinallyInstruction[CacheSize];
+
+ public override int ProducedContinuations { get { return 1; } }
+
+ private EnterTryFinallyInstruction(int targetIndex)
+ : base(targetIndex) {
+ }
+
+ internal static EnterTryFinallyInstruction Create(int labelIndex) {
+ if (labelIndex < CacheSize) {
+ return Cache[labelIndex] ?? (Cache[labelIndex] = new EnterTryFinallyInstruction(labelIndex));
+ }
+ return new EnterTryFinallyInstruction(labelIndex);
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ // Push finally.
+ frame.PushContinuation(_labelIndex);
+ return 1;
+ }
+ }
+
+ /// <summary>
+ /// The first instruction of finally block.
+ /// </summary>
+ internal sealed class EnterFinallyInstruction : Instruction {
+ internal static readonly Instruction Instance = new EnterFinallyInstruction();
+
+ public override int ProducedStack { get { return 2; } }
+ public override int ConsumedContinuations { get { return 1; } }
+
+ private EnterFinallyInstruction() {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.PushPendingContinuation();
+ frame.RemoveContinuation();
+ return 1;
+ }
+ }
+
+ /// <summary>
+ /// The last instruction of finally block.
+ /// </summary>
+ internal sealed class LeaveFinallyInstruction : Instruction {
+ internal static readonly Instruction Instance = new LeaveFinallyInstruction();
+
+ public override int ConsumedStack { get { return 2; } }
+
+ private LeaveFinallyInstruction() {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.PopPendingContinuation();
+
+ // jump to goto target or to the next finally:
+ return frame.YieldToPendingContinuation();
+ }
+ }
+
+ // no-op: we need this just to balance the stack depth.
+ internal sealed class EnterExceptionHandlerInstruction : Instruction {
+ internal static readonly EnterExceptionHandlerInstruction Void = new EnterExceptionHandlerInstruction(false);
+ internal static readonly EnterExceptionHandlerInstruction NonVoid = new EnterExceptionHandlerInstruction(true);
+
+ // True if try-expression is non-void.
+ private readonly bool _hasValue;
+
+ private EnterExceptionHandlerInstruction(bool hasValue) {
+ _hasValue = hasValue;
+ }
+
+ // If an exception is throws in try-body the expression result of try-body is not evaluated and loaded to the stack.
+ // So the stack doesn't contain the try-body's value when we start executing the handler.
+ // However, while emitting instructions try block falls thru the catch block with a value on stack.
+ // We need to declare it consumed so that the stack state upon entry to the handler corresponds to the real
+ // stack depth after throw jumped to this catch block.
+ public override int ConsumedStack { get { return _hasValue ? 1 : 0; } }
+
+ // A variable storing the current exception is pushed to the stack by exception handling.
+ // Catch handlers: The value is immediately popped and stored into a local.
+ // Fault handlers: The value is kept on stack during fault handler evaluation.
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ // nop (the exception value is pushed by the interpreter in HandleCatch)
+ return 1;
+ }
+ }
+
+ /// <summary>
+ /// The last instruction of a catch exception handler.
+ /// </summary>
+ internal sealed class LeaveExceptionHandlerInstruction : IndexedBranchInstruction {
+ private static LeaveExceptionHandlerInstruction[] Cache = new LeaveExceptionHandlerInstruction[2 * CacheSize];
+
+ private readonly bool _hasValue;
+
+ // The catch block yields a value if the body is non-void. This value is left on the stack.
+ public override int ConsumedStack {
+ get { return _hasValue ? 1 : 0; }
+ }
+
+ public override int ProducedStack {
+ get { return _hasValue ? 1 : 0; }
+ }
+
+ private LeaveExceptionHandlerInstruction(int labelIndex, bool hasValue)
+ : base(labelIndex) {
+ _hasValue = hasValue;
+ }
+
+ internal static LeaveExceptionHandlerInstruction Create(int labelIndex, bool hasValue) {
+ if (labelIndex < CacheSize) {
+ int index = (2 * labelIndex) | (hasValue ? 1 : 0);
+ return Cache[index] ?? (Cache[index] = new LeaveExceptionHandlerInstruction(labelIndex, hasValue));
+ }
+ return new LeaveExceptionHandlerInstruction(labelIndex, hasValue);
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ // CLR rethrows ThreadAbortException when leaving catch handler if abort is requested on the current thread.
+ Interpreter.AbortThreadIfRequested(frame, _labelIndex);
+ return GetLabel(frame).Index - frame.InstructionIndex;
+ }
+ }
+
+ /// <summary>
+ /// The last instruction of a fault exception handler.
+ /// </summary>
+ internal sealed class LeaveFaultInstruction : Instruction {
+ internal static readonly Instruction NonVoid = new LeaveFaultInstruction(true);
+ internal static readonly Instruction Void = new LeaveFaultInstruction(false);
+
+ private readonly bool _hasValue;
+
+ // The fault block has a value if the body is non-void, but the value is never used.
+ // We compile the body of a fault block as void.
+ // However, we keep the exception object that was pushed upon entering the fault block on the stack during execution of the block
+ // and pop it at the end.
+ public override int ConsumedStack {
+ get { return 1; }
+ }
+
+ // While emitting instructions a non-void try-fault expression is expected to produce a value.
+ public override int ProducedStack {
+ get { return _hasValue ? 1 : 0; }
+ }
+
+ private LeaveFaultInstruction(bool hasValue) {
+ _hasValue = hasValue;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ // TODO: ThreadAbortException ?
+
+ object exception = frame.Pop();
+ ExceptionHandler handler;
+ return frame.Interpreter.GotoHandler(frame, exception, out handler);
+ }
+ }
+
+
+ internal sealed class ThrowInstruction : Instruction {
+ internal static readonly ThrowInstruction Throw = new ThrowInstruction(true, false);
+ internal static readonly ThrowInstruction VoidThrow = new ThrowInstruction(false, false);
+ internal static readonly ThrowInstruction Rethrow = new ThrowInstruction(true, true);
+ internal static readonly ThrowInstruction VoidRethrow = new ThrowInstruction(false, true);
+
+ private readonly bool _hasResult, _rethrow;
+
+ private ThrowInstruction(bool hasResult, bool isRethrow) {
+ _hasResult = hasResult;
+ _rethrow = isRethrow;
+ }
+
+ public override int ProducedStack {
+ get { return _hasResult ? 1 : 0; }
+ }
+
+ public override int ConsumedStack {
+ get {
+ return 1;
+ }
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ var ex = (Exception)frame.Pop();
+ if (_rethrow) {
+ ExceptionHandler handler;
+ return frame.Interpreter.GotoHandler(frame, ex, out handler);
+ }
+ throw ex;
+ }
+ }
+
+ internal sealed class SwitchInstruction : Instruction {
+ private readonly Dictionary<int, int> _cases;
+
+ internal SwitchInstruction(Dictionary<int, int> cases) {
+ Assert.NotNull(cases);
+ _cases = cases;
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 0; } }
+
+ public override int Run(InterpretedFrame frame) {
+ int target;
+ return _cases.TryGetValue((int)frame.Pop(), out target) ? target : 1;
+ }
+ }
+
+ internal sealed class EnterLoopInstruction : Instruction {
+ private readonly int _instructionIndex;
+ private Dictionary<ParameterExpression, LocalVariable> _variables;
+ private Dictionary<ParameterExpression, LocalVariable> _closureVariables;
+ private LoopExpression _loop;
+ private int _loopEnd;
+ private int _compilationThreshold;
+
+ internal EnterLoopInstruction(LoopExpression loop, LocalVariables locals, int compilationThreshold, int instructionIndex) {
+ _loop = loop;
+ _variables = locals.CopyLocals();
+ _closureVariables = locals.ClosureVariables;
+ _compilationThreshold = compilationThreshold;
+ _instructionIndex = instructionIndex;
+ }
+
+ internal void FinishLoop(int loopEnd) {
+ _loopEnd = loopEnd;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ // Don't lock here, it's a frequently hit path.
+ //
+ // There could be multiple threads racing, but that is okay.
+ // Two bad things can happen:
+ // * We miss decrements (some thread sets the counter forward)
+ // * We might enter the "if" branch more than once.
+ //
+ // The first is okay, it just means we take longer to compile.
+ // The second we explicitly guard against inside of Compile().
+ //
+ // We can't miss 0. The first thread that writes -1 must have read 0 and hence start compilation.
+ if (unchecked(_compilationThreshold--) == 0) {
+#if SILVERLIGHT
+ if (PlatformAdaptationLayer.IsCompactFramework) {
+ _compilationThreshold = Int32.MaxValue;
+ return 1;
+ }
+#endif
+ if (frame.Interpreter.CompileSynchronously) {
+ Compile(frame);
+ } else {
+ // Kick off the compile on another thread so this one can keep going,
+ // Compile method backpatches the instruction when finished so we don't need to await the task.
+#if FEATURE_TASKS
+ new Task(Compile, frame).Start();
+#else
+ ThreadPool.QueueUserWorkItem(Compile, frame);
+#endif
+ }
+ }
+ return 1;
+ }
+
+ private bool Compiled {
+ get { return _loop == null; }
+ }
+
+ private void Compile(object frameObj) {
+ if (Compiled) {
+ return;
+ }
+
+ lock (this) {
+ if (Compiled) {
+ return;
+ }
+
+ PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Interpreted loop compiled");
+
+ InterpretedFrame frame = (InterpretedFrame)frameObj;
+ var compiler = new LoopCompiler(_loop, frame.Interpreter.LabelMapping, _variables, _closureVariables, _instructionIndex, _loopEnd);
+ var instructions = frame.Interpreter.Instructions.Instructions;
+
+ // replace this instruction with an optimized one:
+ Interlocked.Exchange(ref instructions[_instructionIndex], new CompiledLoopInstruction(compiler.CreateDelegate()));
+
+ // invalidate this instruction, some threads may still hold on it:
+ _loop = null;
+ _variables = null;
+ _closureVariables = null;
+ }
+ }
+ }
+
+ internal sealed class CompiledLoopInstruction : Instruction {
+ private readonly LoopFunc _compiledLoop;
+
+ public CompiledLoopInstruction(LoopFunc compiledLoop) {
+ Assert.NotNull(compiledLoop);
+ _compiledLoop = compiledLoop;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ return _compiledLoop(frame.Data, frame.Closure, frame);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DivInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DivInstruction.cs
new file mode 100644
index 00000000000..08ed47926b5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DivInstruction.cs
@@ -0,0 +1,132 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Diagnostics;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal abstract class DivInstruction : Instruction {
+ private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private DivInstruction() {
+ }
+
+ internal sealed class DivInt32 : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((Int32)l / (Int32)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivInt16 : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Int16)((Int16)l / (Int16)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivInt64 : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Int64)((Int64)l / (Int64)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivUInt16 : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt16)((UInt16)l / (UInt16)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivUInt32 : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt32)((UInt32)l / (UInt32)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivUInt64 : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (UInt64)((Int16)l / (Int16)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivSingle : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Single)((Single)l / (Single)r);
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ internal sealed class DivDouble : DivInstruction {
+ public override int Run(InterpretedFrame frame) {
+ object l = frame.Data[frame.StackIndex - 2];
+ object r = frame.Data[frame.StackIndex - 1];
+ frame.Data[frame.StackIndex - 2] = (Double)l / (Double)r;
+ frame.StackIndex--;
+ return 1;
+ }
+ }
+
+ public static Instruction Create(Type type) {
+ Debug.Assert(!type.IsEnum());
+ switch (type.GetTypeCode()) {
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new DivInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new DivInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new DivInt64());
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new DivUInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new DivUInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new DivUInt64());
+ case TypeCode.Single: return _Single ?? (_Single = new DivSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new DivDouble());
+
+ default:
+ throw Assert.Unreachable;
+ }
+ }
+
+ public override string ToString() {
+ return "Div()";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructionN.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructionN.cs
new file mode 100644
index 00000000000..70576695132
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructionN.cs
@@ -0,0 +1,76 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+
+using Microsoft.Scripting.Utils;
+using System.Security;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal sealed partial class DynamicInstructionN : Instruction {
+ private readonly CallInstruction _targetInvocationInstruction;
+ private readonly object _targetDelegate;
+ private readonly CallSite _site;
+ private readonly int _argumentCount;
+ private readonly bool _isVoid;
+
+ public DynamicInstructionN(Type delegateType, CallSite site) {
+ var methodInfo = delegateType.GetMethod("Invoke");
+ var parameters = methodInfo.GetParameters();
+
+ // <Delegate>.Invoke is ok to target by a delegate in partial trust (SecurityException is not thrown):
+ _targetInvocationInstruction = CallInstruction.Create(methodInfo, parameters);
+ _site = site;
+ _argumentCount = parameters.Length - 1;
+ _targetDelegate = site.GetType().GetInheritedFields("Target").First().GetValue(site);
+ }
+
+ public DynamicInstructionN(Type delegateType, CallSite site, bool isVoid)
+ : this(delegateType, site) {
+ _isVoid = isVoid;
+ }
+
+ public override int ProducedStack { get { return _isVoid ? 0 : 1; } }
+ public override int ConsumedStack { get { return _argumentCount; } }
+
+ public override int Run(InterpretedFrame frame) {
+ int first = frame.StackIndex - _argumentCount;
+ object[] args = new object[1 + _argumentCount];
+ args[0] = _site;
+ for (int i = 0; i < _argumentCount; i++) {
+ args[1 + i] = frame.Data[first + i];
+ }
+
+ object ret = _targetInvocationInstruction.InvokeInstance(_targetDelegate, args);
+ if (_isVoid) {
+ frame.StackIndex = first;
+ } else {
+ frame.Data[first] = ret;
+ frame.StackIndex = first + 1;
+ }
+
+ return 1;
+ }
+
+ public override string ToString() {
+ return "DynamicInstructionN(" + _site + ")";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructions.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructions.Generated.cs
new file mode 100644
index 00000000000..c98b957f6ce
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicInstructions.Generated.cs
@@ -0,0 +1,509 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+
+using System;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal partial class DynamicInstructionN {
+ internal static Type GetDynamicInstructionType(Type delegateType) {
+ Type[] argTypes = delegateType.GetGenericArguments();
+ if (argTypes.Length == 0) return null;
+ Type genericType;
+ Type[] newArgTypes = ArrayUtils.RemoveFirst(argTypes);
+ switch (newArgTypes.Length) {
+ #region Generated Dynamic Instruction Types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_types from: generate_dynamic_instructions.py
+
+ case 1: genericType = typeof(DynamicInstruction<>); break;
+ case 2: genericType = typeof(DynamicInstruction<,>); break;
+ case 3: genericType = typeof(DynamicInstruction<,,>); break;
+ case 4: genericType = typeof(DynamicInstruction<,,,>); break;
+ case 5: genericType = typeof(DynamicInstruction<,,,,>); break;
+ case 6: genericType = typeof(DynamicInstruction<,,,,,>); break;
+ case 7: genericType = typeof(DynamicInstruction<,,,,,,>); break;
+ case 8: genericType = typeof(DynamicInstruction<,,,,,,,>); break;
+ case 9: genericType = typeof(DynamicInstruction<,,,,,,,,>); break;
+ case 10: genericType = typeof(DynamicInstruction<,,,,,,,,,>); break;
+ case 11: genericType = typeof(DynamicInstruction<,,,,,,,,,,>); break;
+ case 12: genericType = typeof(DynamicInstruction<,,,,,,,,,,,>); break;
+ case 13: genericType = typeof(DynamicInstruction<,,,,,,,,,,,,>); break;
+ case 14: genericType = typeof(DynamicInstruction<,,,,,,,,,,,,,>); break;
+ case 15: genericType = typeof(DynamicInstruction<,,,,,,,,,,,,,,>); break;
+ case 16: genericType = typeof(DynamicInstruction<,,,,,,,,,,,,,,,>); break;
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ default:
+ throw Assert.Unreachable;
+ }
+
+ return genericType.MakeGenericType(newArgTypes);
+ }
+
+ internal static Instruction CreateUntypedInstruction(CallSiteBinder binder, int argCount) {
+ // DLR Ref.Emits an UpdateAndExecute delegate for sites with more than 10 parameters
+ if (argCount > 10 && PlatformAdaptationLayer.IsCompactFramework) {
+ return null;
+ }
+
+ switch (argCount) {
+ #region Generated Untyped Dynamic Instructions
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_untyped from: generate_dynamic_instructions.py
+
+ case 0: return DynamicInstruction<object>.Factory(binder);
+ case 1: return DynamicInstruction<object, object>.Factory(binder);
+ case 2: return DynamicInstruction<object, object, object>.Factory(binder);
+ case 3: return DynamicInstruction<object, object, object, object>.Factory(binder);
+ case 4: return DynamicInstruction<object, object, object, object, object>.Factory(binder);
+ case 5: return DynamicInstruction<object, object, object, object, object, object>.Factory(binder);
+ case 6: return DynamicInstruction<object, object, object, object, object, object, object>.Factory(binder);
+ case 7: return DynamicInstruction<object, object, object, object, object, object, object, object>.Factory(binder);
+ case 8: return DynamicInstruction<object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 9: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 10: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 11: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 12: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 13: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 14: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+ case 15: return DynamicInstruction<object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>.Factory(binder);
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default: return null;
+ }
+ }
+ }
+
+ #region Generated Dynamic Instructions
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_instructions from: generate_dynamic_instructions.py
+
+ internal class DynamicInstruction<TRet> : Instruction {
+ private CallSite<Func<CallSite,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<TRet>(CallSite<Func<CallSite,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 0; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 0] = _site.Target(_site);
+ frame.StackIndex -= -1;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,TRet>(CallSite<Func<CallSite,T0,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 1] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 1]);
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,TRet>(CallSite<Func<CallSite,T0,T1,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 2; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 2] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 2], (T1)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 1;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,TRet>(CallSite<Func<CallSite,T0,T1,T2,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 3; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 3] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 3], (T1)frame.Data[frame.StackIndex - 2], (T2)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 2;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 4; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 4] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 4], (T1)frame.Data[frame.StackIndex - 3], (T2)frame.Data[frame.StackIndex - 2], (T3)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 3;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 5; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 5] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 5], (T1)frame.Data[frame.StackIndex - 4], (T2)frame.Data[frame.StackIndex - 3], (T3)frame.Data[frame.StackIndex - 2], (T4)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 4;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 6; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 6] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 6], (T1)frame.Data[frame.StackIndex - 5], (T2)frame.Data[frame.StackIndex - 4], (T3)frame.Data[frame.StackIndex - 3], (T4)frame.Data[frame.StackIndex - 2], (T5)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 5;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 7; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 7] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 7], (T1)frame.Data[frame.StackIndex - 6], (T2)frame.Data[frame.StackIndex - 5], (T3)frame.Data[frame.StackIndex - 4], (T4)frame.Data[frame.StackIndex - 3], (T5)frame.Data[frame.StackIndex - 2], (T6)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 6;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 8; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 8] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 8], (T1)frame.Data[frame.StackIndex - 7], (T2)frame.Data[frame.StackIndex - 6], (T3)frame.Data[frame.StackIndex - 5], (T4)frame.Data[frame.StackIndex - 4], (T5)frame.Data[frame.StackIndex - 3], (T6)frame.Data[frame.StackIndex - 2], (T7)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 7;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 9; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 9] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 9], (T1)frame.Data[frame.StackIndex - 8], (T2)frame.Data[frame.StackIndex - 7], (T3)frame.Data[frame.StackIndex - 6], (T4)frame.Data[frame.StackIndex - 5], (T5)frame.Data[frame.StackIndex - 4], (T6)frame.Data[frame.StackIndex - 3], (T7)frame.Data[frame.StackIndex - 2], (T8)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 8;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 10; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 10] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 10], (T1)frame.Data[frame.StackIndex - 9], (T2)frame.Data[frame.StackIndex - 8], (T3)frame.Data[frame.StackIndex - 7], (T4)frame.Data[frame.StackIndex - 6], (T5)frame.Data[frame.StackIndex - 5], (T6)frame.Data[frame.StackIndex - 4], (T7)frame.Data[frame.StackIndex - 3], (T8)frame.Data[frame.StackIndex - 2], (T9)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 9;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 11; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 11] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 11], (T1)frame.Data[frame.StackIndex - 10], (T2)frame.Data[frame.StackIndex - 9], (T3)frame.Data[frame.StackIndex - 8], (T4)frame.Data[frame.StackIndex - 7], (T5)frame.Data[frame.StackIndex - 6], (T6)frame.Data[frame.StackIndex - 5], (T7)frame.Data[frame.StackIndex - 4], (T8)frame.Data[frame.StackIndex - 3], (T9)frame.Data[frame.StackIndex - 2], (T10)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 10;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 12; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 12] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 12], (T1)frame.Data[frame.StackIndex - 11], (T2)frame.Data[frame.StackIndex - 10], (T3)frame.Data[frame.StackIndex - 9], (T4)frame.Data[frame.StackIndex - 8], (T5)frame.Data[frame.StackIndex - 7], (T6)frame.Data[frame.StackIndex - 6], (T7)frame.Data[frame.StackIndex - 5], (T8)frame.Data[frame.StackIndex - 4], (T9)frame.Data[frame.StackIndex - 3], (T10)frame.Data[frame.StackIndex - 2], (T11)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 11;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 13; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 13] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 13], (T1)frame.Data[frame.StackIndex - 12], (T2)frame.Data[frame.StackIndex - 11], (T3)frame.Data[frame.StackIndex - 10], (T4)frame.Data[frame.StackIndex - 9], (T5)frame.Data[frame.StackIndex - 8], (T6)frame.Data[frame.StackIndex - 7], (T7)frame.Data[frame.StackIndex - 6], (T8)frame.Data[frame.StackIndex - 5], (T9)frame.Data[frame.StackIndex - 4], (T10)frame.Data[frame.StackIndex - 3], (T11)frame.Data[frame.StackIndex - 2], (T12)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 12;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 14; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 14] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 14], (T1)frame.Data[frame.StackIndex - 13], (T2)frame.Data[frame.StackIndex - 12], (T3)frame.Data[frame.StackIndex - 11], (T4)frame.Data[frame.StackIndex - 10], (T5)frame.Data[frame.StackIndex - 9], (T6)frame.Data[frame.StackIndex - 8], (T7)frame.Data[frame.StackIndex - 7], (T8)frame.Data[frame.StackIndex - 6], (T9)frame.Data[frame.StackIndex - 5], (T10)frame.Data[frame.StackIndex - 4], (T11)frame.Data[frame.StackIndex - 3], (T12)frame.Data[frame.StackIndex - 2], (T13)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 13;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+ internal class DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet> : Instruction {
+ private CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>> _site;
+
+ public static Instruction Factory(CallSiteBinder binder) {
+ return new DynamicInstruction<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>>.Create(binder));
+ }
+
+ private DynamicInstruction(CallSite<Func<CallSite,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>> site) {
+ _site = site;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return 15; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex - 15] = _site.Target(_site, (T0)frame.Data[frame.StackIndex - 15], (T1)frame.Data[frame.StackIndex - 14], (T2)frame.Data[frame.StackIndex - 13], (T3)frame.Data[frame.StackIndex - 12], (T4)frame.Data[frame.StackIndex - 11], (T5)frame.Data[frame.StackIndex - 10], (T6)frame.Data[frame.StackIndex - 9], (T7)frame.Data[frame.StackIndex - 8], (T8)frame.Data[frame.StackIndex - 7], (T9)frame.Data[frame.StackIndex - 6], (T10)frame.Data[frame.StackIndex - 5], (T11)frame.Data[frame.StackIndex - 4], (T12)frame.Data[frame.StackIndex - 3], (T13)frame.Data[frame.StackIndex - 2], (T14)frame.Data[frame.StackIndex - 1]);
+ frame.StackIndex -= 14;
+ return 1;
+ }
+
+ public override string ToString() {
+ return "Dynamic(" + _site.Binder.ToString() + ")";
+ }
+ }
+
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicSplatInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicSplatInstruction.cs
new file mode 100644
index 00000000000..b2426e7b414
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/DynamicSplatInstruction.cs
@@ -0,0 +1,55 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+
+using Microsoft.Scripting.Utils;
+using Microsoft.Scripting.Ast;
+using Microsoft.Scripting.Runtime;
+
+namespace Microsoft.Scripting.Interpreter {
+ /// <summary>
+ /// Implements dynamic call site with many arguments. Wraps the arguments into <see cref="ArgumentArray"/>.
+ /// </summary>
+ internal sealed partial class DynamicSplatInstruction : Instruction {
+ private readonly CallSite<Func<CallSite, ArgumentArray, object>> _site;
+ private readonly int _argumentCount;
+
+ internal DynamicSplatInstruction(int argumentCount, CallSite<Func<CallSite, ArgumentArray, object>> site) {
+ _site = site;
+ _argumentCount = argumentCount;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return _argumentCount; } }
+
+ public override int Run(InterpretedFrame frame) {
+ int first = frame.StackIndex - _argumentCount;
+ object ret = _site.Target(_site, new ArgumentArray(frame.Data, first, _argumentCount));
+ frame.Data[first] = ret;
+ frame.StackIndex = first + 1;
+
+ return 1;
+ }
+
+ public override string ToString() {
+ return "DynamicSplatInstruction(" + _site + ")";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs
new file mode 100644
index 00000000000..e4edde9bab2
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs
@@ -0,0 +1,161 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal abstract class EqualInstruction : Instruction {
+ // Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
+ private static Instruction _Reference, _Boolean, _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private EqualInstruction() {
+ }
+
+ internal sealed class EqualBoolean : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Boolean)frame.Pop()) == ((Boolean)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualSByte : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((SByte)frame.Pop()) == ((SByte)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualInt16 : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Int16)frame.Pop()) == ((Int16)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualChar : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Char)frame.Pop()) == ((Char)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualInt32 : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Int32)frame.Pop()) == ((Int32)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualInt64 : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Int64)frame.Pop()) == ((Int64)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualByte : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Byte)frame.Pop()) == ((Byte)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualUInt16 : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((UInt16)frame.Pop()) == ((UInt16)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualUInt32 : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((UInt32)frame.Pop()) == ((UInt32)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualUInt64 : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((UInt64)frame.Pop()) == ((UInt64)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualSingle : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Single)frame.Pop()) == ((Single)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualDouble : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Double)frame.Pop()) == ((Double)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class EqualReference : EqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(frame.Pop() == frame.Pop());
+ return +1;
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ public static Instruction Create(Type type) {
+ // Boxed enums can be unboxed as their underlying types:
+ switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) {
+ case TypeCode.Boolean: return _Boolean ?? (_Boolean = new EqualBoolean());
+ case TypeCode.SByte: return _SByte ?? (_SByte = new EqualSByte());
+ case TypeCode.Byte: return _Byte ?? (_Byte = new EqualByte());
+ case TypeCode.Char: return _Char ?? (_Char = new EqualChar());
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new EqualInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new EqualInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new EqualInt64());
+
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new EqualInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new EqualInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new EqualInt64());
+
+ case TypeCode.Single: return _Single ?? (_Single = new EqualSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new EqualDouble());
+
+ case TypeCode.Object:
+ if (!type.IsValueType()) {
+ return _Reference ?? (_Reference = new EqualReference());
+ }
+ // TODO: Nullable<T>
+ throw new NotImplementedException();
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+
+ public override string ToString() {
+ return "Equal()";
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/FieldOperations.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/FieldOperations.cs
new file mode 100644
index 00000000000..4bb8ec65c46
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/FieldOperations.cs
@@ -0,0 +1,94 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal sealed class LoadStaticFieldInstruction : Instruction {
+ private readonly FieldInfo _field;
+
+ public LoadStaticFieldInstruction(FieldInfo field) {
+ Debug.Assert(field.IsStatic);
+ _field = field;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(_field.GetValue(null));
+ return +1;
+ }
+ }
+
+ internal sealed class LoadFieldInstruction : Instruction {
+ private readonly FieldInfo _field;
+
+ public LoadFieldInstruction(FieldInfo field) {
+ Assert.NotNull(field);
+ _field = field;
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(_field.GetValue(frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class StoreFieldInstruction : Instruction {
+ private readonly FieldInfo _field;
+
+ public StoreFieldInstruction(FieldInfo field) {
+ Assert.NotNull(field);
+ _field = field;
+ }
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 0; } }
+
+ public override int Run(InterpretedFrame frame) {
+ object value = frame.Pop();
+ object self = frame.Pop();
+ _field.SetValue(self, value);
+ return +1;
+ }
+ }
+
+ internal sealed class StoreStaticFieldInstruction : Instruction {
+ private readonly FieldInfo _field;
+
+ public StoreStaticFieldInstruction(FieldInfo field) {
+ Assert.NotNull(field);
+ _field = field;
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 0; } }
+
+ public override int Run(InterpretedFrame frame) {
+ object value = frame.Pop();
+ _field.SetValue(null, value);
+ return +1;
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs
new file mode 100644
index 00000000000..a35f16b0e34
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs
@@ -0,0 +1,146 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal abstract class GreaterThanInstruction : Instruction {
+ private static Instruction _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private GreaterThanInstruction() {
+ }
+
+ internal sealed class GreaterThanSByte : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ SByte right = (SByte)frame.Pop();
+ frame.Push(((SByte)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanInt16 : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Int16 right = (Int16)frame.Pop();
+ frame.Push(((Int16)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanChar : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Char right = (Char)frame.Pop();
+ frame.Push(((Char)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanInt32 : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Int32 right = (Int32)frame.Pop();
+ frame.Push(((Int32)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanInt64 : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Int64 right = (Int64)frame.Pop();
+ frame.Push(((Int64)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanByte : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Byte right = (Byte)frame.Pop();
+ frame.Push(((Byte)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanUInt16 : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ UInt16 right = (UInt16)frame.Pop();
+ frame.Push(((UInt16)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanUInt32 : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ UInt32 right = (UInt32)frame.Pop();
+ frame.Push(((UInt32)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanUInt64 : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ UInt64 right = (UInt64)frame.Pop();
+ frame.Push(((UInt64)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanSingle : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Single right = (Single)frame.Pop();
+ frame.Push(((Single)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ internal sealed class GreaterThanDouble : GreaterThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Double right = (Double)frame.Pop();
+ frame.Push(((Double)frame.Pop()) > right);
+ return +1;
+ }
+ }
+
+ public static Instruction Create(Type type) {
+ Debug.Assert(!type.IsEnum());
+ switch (type.GetTypeCode()) {
+ case TypeCode.SByte: return _SByte ?? (_SByte = new GreaterThanSByte());
+ case TypeCode.Byte: return _Byte ?? (_Byte = new GreaterThanByte());
+ case TypeCode.Char: return _Char ?? (_Char = new GreaterThanChar());
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new GreaterThanInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new GreaterThanInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new GreaterThanInt64());
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new GreaterThanUInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new GreaterThanUInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new GreaterThanUInt64());
+ case TypeCode.Single: return _Single ?? (_Single = new GreaterThanSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new GreaterThanDouble());
+
+ default:
+ throw Assert.Unreachable;
+ }
+ }
+
+ public override string ToString() {
+ return "GreaterThan()";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/Instruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/Instruction.cs
new file mode 100644
index 00000000000..28267ec2a58
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/Instruction.cs
@@ -0,0 +1,73 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ public interface IInstructionProvider {
+ void AddInstructions(LightCompiler compiler);
+ }
+
+ public abstract partial class Instruction {
+ public virtual int ConsumedStack { get { return 0; } }
+ public virtual int ProducedStack { get { return 0; } }
+ public virtual int ConsumedContinuations { get { return 0; } }
+ public virtual int ProducedContinuations { get { return 0; } }
+
+ public int StackBalance {
+ get { return ProducedStack - ConsumedStack; }
+ }
+
+ public int ContinuationsBalance {
+ get { return ProducedContinuations - ConsumedContinuations; }
+ }
+
+ public abstract int Run(InterpretedFrame frame);
+
+ public virtual string InstructionName {
+ get { return GetType().Name.Replace("Instruction", ""); }
+ }
+
+ public override string ToString() {
+ return InstructionName + "()";
+ }
+
+ public virtual string ToDebugString(int instructionIndex, object cookie, Func<int, int> labelIndexer, IList<object> objects) {
+ return ToString();
+ }
+
+ public virtual object GetDebugCookie(LightCompiler compiler) {
+ return null;
+ }
+ }
+
+ internal sealed class NotInstruction : Instruction {
+ public static readonly Instruction Instance = new NotInstruction();
+
+ private NotInstruction() { }
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+ public override int Run(InterpretedFrame frame) {
+ frame.Push((bool)frame.Pop() ? ScriptingRuntimeHelpers.False : ScriptingRuntimeHelpers.True);
+ return +1;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs
new file mode 100644
index 00000000000..ca0be0924d3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs
@@ -0,0 +1,115 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_NUMERICS
+using BigInt = System.Numerics.BigInteger;
+#endif
+
+using System;
+using System.Collections.Generic;
+
+using Microsoft.Scripting.Math;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ public abstract class InstructionFactory {
+ // TODO: weak table for types in a collectible assembly?
+ private static Dictionary<Type, InstructionFactory> _factories;
+
+ internal static InstructionFactory GetFactory(Type type) {
+ if (_factories == null) {
+ _factories = new Dictionary<Type, InstructionFactory>() {
+ { typeof(object), InstructionFactory<object>.Factory },
+ { typeof(bool), InstructionFactory<bool>.Factory },
+ { typeof(byte), InstructionFactory<byte>.Factory },
+ { typeof(sbyte), InstructionFactory<sbyte>.Factory },
+ { typeof(short), InstructionFactory<short>.Factory },
+ { typeof(ushort), InstructionFactory<ushort>.Factory },
+ { typeof(int), InstructionFactory<int>.Factory },
+ { typeof(uint), InstructionFactory<uint>.Factory },
+ { typeof(long), InstructionFactory<long>.Factory },
+ { typeof(ulong), InstructionFactory<ulong>.Factory },
+ { typeof(float), InstructionFactory<float>.Factory },
+ { typeof(double), InstructionFactory<double>.Factory },
+ { typeof(char), InstructionFactory<char>.Factory },
+ { typeof(string), InstructionFactory<string>.Factory },
+#if FEATURE_NUMERICS
+ { typeof(BigInt), InstructionFactory<BigInt>.Factory },
+#endif
+ { typeof(BigInteger), InstructionFactory<BigInteger>.Factory }
+ };
+ }
+
+ lock (_factories) {
+ InstructionFactory factory;
+ if (!_factories.TryGetValue(type, out factory)) {
+ factory = (InstructionFactory)typeof(InstructionFactory<>).MakeGenericType(type).GetDeclaredField("Factory").GetValue(null);
+ _factories[type] = factory;
+ }
+ return factory;
+ }
+ }
+
+ internal protected abstract Instruction GetArrayItem();
+ internal protected abstract Instruction SetArrayItem();
+ internal protected abstract Instruction TypeIs();
+ internal protected abstract Instruction TypeAs();
+ internal protected abstract Instruction DefaultValue();
+ internal protected abstract Instruction NewArray();
+ internal protected abstract Instruction NewArrayInit(int elementCount);
+ }
+
+ public sealed class InstructionFactory<T> : InstructionFactory {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly InstructionFactory Factory = new InstructionFactory<T>();
+
+ private Instruction _getArrayItem;
+ private Instruction _setArrayItem;
+ private Instruction _typeIs;
+ private Instruction _defaultValue;
+ private Instruction _newArray;
+ private Instruction _typeAs;
+
+ private InstructionFactory() { }
+
+ internal protected override Instruction GetArrayItem() {
+ return _getArrayItem ?? (_getArrayItem = new GetArrayItemInstruction<T>());
+ }
+
+ internal protected override Instruction SetArrayItem() {
+ return _setArrayItem ?? (_setArrayItem = new SetArrayItemInstruction<T>());
+ }
+
+ internal protected override Instruction TypeIs() {
+ return _typeIs ?? (_typeIs = new TypeIsInstruction<T>());
+ }
+
+ internal protected override Instruction TypeAs() {
+ return _typeAs ?? (_typeAs = new TypeAsInstruction<T>());
+ }
+
+ internal protected override Instruction DefaultValue() {
+ return _defaultValue ?? (_defaultValue = new DefaultValueInstruction<T>());
+ }
+
+ internal protected override Instruction NewArray() {
+ return _newArray ?? (_newArray = new NewArrayInstruction<T>());
+ }
+
+ internal protected override Instruction NewArrayInit(int elementCount) {
+ return new NewArrayInitInstruction<T>(elementCount);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs
new file mode 100644
index 00000000000..c605977208d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs
@@ -0,0 +1,1001 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+// Enables instruction counting and displaying stats at process exit.
+// #define STATS
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
+ [DebuggerTypeProxy(typeof(InstructionArray.DebugView))]
+ public struct InstructionArray {
+ internal readonly int MaxStackDepth;
+ internal readonly int MaxContinuationDepth;
+ internal readonly Instruction[] Instructions;
+ internal readonly object[] Objects;
+ internal readonly RuntimeLabel[] Labels;
+
+ // list of (instruction index, cookie) sorted by instruction index:
+ internal readonly List<KeyValuePair<int, object>> DebugCookies;
+
+ internal InstructionArray(int maxStackDepth, int maxContinuationDepth, Instruction[] instructions,
+ object[] objects, RuntimeLabel[] labels, List<KeyValuePair<int, object>> debugCookies) {
+
+ MaxStackDepth = maxStackDepth;
+ MaxContinuationDepth = maxContinuationDepth;
+ Instructions = instructions;
+ DebugCookies = debugCookies;
+ Objects = objects;
+ Labels = labels;
+ }
+
+ internal int Length {
+ get { return Instructions.Length; }
+ }
+
+ #region Debug View
+
+ internal sealed class DebugView {
+ private readonly InstructionArray _array;
+
+ public DebugView(InstructionArray array) {
+ _array = array;
+
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public InstructionList.DebugView.InstructionView[]/*!*/ A0 {
+ get {
+ return InstructionList.DebugView.GetInstructionViews(
+ _array.Instructions,
+ _array.Objects,
+ (index) => _array.Labels[index].Index,
+ _array.DebugCookies
+ );
+ }
+ }
+ }
+
+ #endregion
+ }
+
+ [DebuggerTypeProxy(typeof(InstructionList.DebugView))]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ public sealed class InstructionList {
+ private readonly List<Instruction> _instructions = new List<Instruction>();
+ private List<object> _objects;
+
+ private int _currentStackDepth;
+ private int _maxStackDepth;
+ private int _currentContinuationsDepth;
+ private int _maxContinuationDepth;
+ private int _runtimeLabelCount;
+ private List<BranchLabel> _labels;
+
+ // list of (instruction index, cookie) sorted by instruction index:
+ private List<KeyValuePair<int, object>> _debugCookies = null;
+
+ #region Debug View
+
+ internal sealed class DebugView {
+ private readonly InstructionList _list;
+
+ public DebugView(InstructionList list) {
+ _list = list;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public InstructionView[]/*!*/ A0 {
+ get {
+ return GetInstructionViews(
+ _list._instructions,
+ _list._objects,
+ (index) => _list._labels[index].TargetIndex,
+ _list._debugCookies
+ );
+ }
+ }
+
+ internal static InstructionView[] GetInstructionViews(IList<Instruction> instructions, IList<object> objects,
+ Func<int, int> labelIndexer, IList<KeyValuePair<int, object>> debugCookies) {
+
+ var result = new List<InstructionView>();
+ int index = 0;
+ int stackDepth = 0;
+ int continuationsDepth = 0;
+
+ var cookieEnumerator = (debugCookies != null ? debugCookies : new KeyValuePair<int, object>[0]).GetEnumerator();
+ var hasCookie = cookieEnumerator.MoveNext();
+
+ for (int i = 0; i < instructions.Count; i++) {
+ object cookie = null;
+ while (hasCookie && cookieEnumerator.Current.Key == i) {
+ cookie = cookieEnumerator.Current.Value;
+ hasCookie = cookieEnumerator.MoveNext();
+ }
+
+ int stackDiff = instructions[i].StackBalance;
+ int contDiff = instructions[i].ContinuationsBalance;
+ string name = instructions[i].ToDebugString(i, cookie, labelIndexer, objects);
+ result.Add(new InstructionView(instructions[i], name, i, stackDepth, continuationsDepth));
+
+ index++;
+ stackDepth += stackDiff;
+ continuationsDepth += contDiff;
+ }
+ return result.ToArray();
+ }
+
+ [DebuggerDisplay("{GetValue(),nq}", Name = "{GetName(),nq}", Type = "{GetDisplayType(), nq}")]
+ internal struct InstructionView {
+ private readonly int _index;
+ private readonly int _stackDepth;
+ private readonly int _continuationsDepth;
+ private readonly string _name;
+ private readonly Instruction _instruction;
+
+ internal string GetName() {
+ return _index.ToString() +
+ (_continuationsDepth == 0 ? "" : " C(" + _continuationsDepth.ToString() + ")") +
+ (_stackDepth == 0 ? "" : " S(" + _stackDepth.ToString() + ")");
+ }
+
+ internal string GetValue() {
+ return _name;
+ }
+
+ internal string GetDisplayType() {
+ return _instruction.ContinuationsBalance.ToString() + "/" + _instruction.StackBalance.ToString();
+ }
+
+ public InstructionView(Instruction instruction, string name, int index, int stackDepth, int continuationsDepth) {
+ _instruction = instruction;
+ _name = name;
+ _index = index;
+ _stackDepth = stackDepth;
+ _continuationsDepth = continuationsDepth;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Core Emit Ops
+
+ public void Emit(Instruction instruction) {
+ _instructions.Add(instruction);
+ UpdateStackDepth(instruction);
+ }
+
+ private void UpdateStackDepth(Instruction instruction) {
+ Debug.Assert(instruction.ConsumedStack >= 0 && instruction.ProducedStack >= 0 &&
+ instruction.ConsumedContinuations >= 0 && instruction.ProducedContinuations >= 0);
+
+ _currentStackDepth -= instruction.ConsumedStack;
+ Debug.Assert(_currentStackDepth >= 0);
+ _currentStackDepth += instruction.ProducedStack;
+ if (_currentStackDepth > _maxStackDepth) {
+ _maxStackDepth = _currentStackDepth;
+ }
+
+ _currentContinuationsDepth -= instruction.ConsumedContinuations;
+ Debug.Assert(_currentContinuationsDepth >= 0);
+ _currentContinuationsDepth += instruction.ProducedContinuations;
+ if (_currentContinuationsDepth > _maxContinuationDepth) {
+ _maxContinuationDepth = _currentContinuationsDepth;
+ }
+ }
+
+ /// <summary>
+ /// Attaches a cookie to the last emitted instruction.
+ /// </summary>
+ [Conditional("DEBUG")]
+ public void SetDebugCookie(object cookie) {
+#if DEBUG
+ if (_debugCookies == null) {
+ _debugCookies = new List<KeyValuePair<int, object>>();
+ }
+
+ Debug.Assert(Count > 0);
+ _debugCookies.Add(new KeyValuePair<int, object>(Count - 1, cookie));
+#endif
+ }
+
+ public int Count {
+ get { return _instructions.Count; }
+ }
+
+ public int CurrentStackDepth {
+ get { return _currentStackDepth; }
+ }
+
+ public int CurrentContinuationsDepth {
+ get { return _currentContinuationsDepth; }
+ }
+
+ public int MaxStackDepth {
+ get { return _maxStackDepth; }
+ }
+
+ internal Instruction GetInstruction(int index) {
+ return _instructions[index];
+ }
+
+#if STATS
+ private static Dictionary<string, int> _executedInstructions = new Dictionary<string, int>();
+ private static Dictionary<string, Dictionary<object, bool>> _instances = new Dictionary<string, Dictionary<object, bool>>();
+
+ static InstructionList() {
+ AppDomain.CurrentDomain.ProcessExit += new EventHandler((_, __) => {
+ PerfTrack.DumpHistogram(_executedInstructions);
+ Console.WriteLine("-- Total executed: {0}", _executedInstructions.Values.Aggregate(0, (sum, value) => sum + value));
+ Console.WriteLine("-----");
+
+ var referenced = new Dictionary<string, int>();
+ int total = 0;
+ foreach (var entry in _instances) {
+ referenced[entry.Key] = entry.Value.Count;
+ total += entry.Value.Count;
+ }
+
+ PerfTrack.DumpHistogram(referenced);
+ Console.WriteLine("-- Total referenced: {0}", total);
+ Console.WriteLine("-----");
+ });
+ }
+#endif
+ public InstructionArray ToArray() {
+#if STATS
+ lock (_executedInstructions) {
+ _instructions.ForEach((instr) => {
+ int value = 0;
+ var name = instr.GetType().Name;
+ _executedInstructions.TryGetValue(name, out value);
+ _executedInstructions[name] = value + 1;
+
+ Dictionary<object, bool> dict;
+ if (!_instances.TryGetValue(name, out dict)) {
+ _instances[name] = dict = new Dictionary<object, bool>();
+ }
+ dict[instr] = true;
+ });
+ }
+#endif
+ return new InstructionArray(
+ _maxStackDepth,
+ _maxContinuationDepth,
+ _instructions.ToArray(),
+ (_objects != null) ? _objects.ToArray() : null,
+ BuildRuntimeLabels(),
+ _debugCookies
+ );
+ }
+
+ #endregion
+
+ #region Stack Operations
+
+ private const int PushIntMinCachedValue = -100;
+ private const int PushIntMaxCachedValue = 100;
+ private const int CachedObjectCount = 256;
+
+ private static Instruction _null;
+ private static Instruction _true;
+ private static Instruction _false;
+ private static Instruction[] _ints;
+ private static Instruction[] _loadObjectCached;
+
+ public void EmitLoad(object value) {
+ EmitLoad(value, null);
+ }
+
+ public void EmitLoad(bool value) {
+ if ((bool)value) {
+ Emit(_true ?? (_true = new LoadObjectInstruction(value)));
+ } else {
+ Emit(_false ?? (_false = new LoadObjectInstruction(value)));
+ }
+ }
+
+ public void EmitLoad(object value, Type type) {
+ if (value == null) {
+ Emit(_null ?? (_null = new LoadObjectInstruction(null)));
+ return;
+ }
+
+ if (type == null || type.IsValueType()) {
+ if (value is bool) {
+ EmitLoad((bool)value);
+ return;
+ }
+
+ if (value is int) {
+ int i = (int)value;
+ if (i >= PushIntMinCachedValue && i <= PushIntMaxCachedValue) {
+ if (_ints == null) {
+ _ints = new Instruction[PushIntMaxCachedValue - PushIntMinCachedValue + 1];
+ }
+ i -= PushIntMinCachedValue;
+ Emit(_ints[i] ?? (_ints[i] = new LoadObjectInstruction(value)));
+ return;
+ }
+ }
+ }
+
+ if (_objects == null) {
+ _objects = new List<object>();
+ if (_loadObjectCached == null) {
+ _loadObjectCached = new Instruction[CachedObjectCount];
+ }
+ }
+
+ if (_objects.Count < _loadObjectCached.Length) {
+ uint index = (uint)_objects.Count;
+ _objects.Add(value);
+ Emit(_loadObjectCached[index] ?? (_loadObjectCached[index] = new LoadCachedObjectInstruction(index)));
+ } else {
+ Emit(new LoadObjectInstruction(value));
+ }
+ }
+
+ public void EmitDup() {
+ Emit(DupInstruction.Instance);
+ }
+
+ public void EmitPop() {
+ Emit(PopInstruction.Instance);
+ }
+
+ #endregion
+
+ #region Locals
+
+ internal void SwitchToBoxed(int index, int instructionIndex) {
+ var instruction = _instructions[instructionIndex] as IBoxableInstruction;
+
+ if (instruction != null) {
+ var newInstruction = instruction.BoxIfIndexMatches(index);
+ if (newInstruction != null) {
+ _instructions[instructionIndex] = newInstruction;
+ }
+ }
+ }
+
+ private const int LocalInstrCacheSize = 64;
+
+ private static Instruction[] _loadLocal;
+ private static Instruction[] _loadLocalBoxed;
+ private static Instruction[] _loadLocalFromClosure;
+ private static Instruction[] _loadLocalFromClosureBoxed;
+ private static Instruction[] _assignLocal;
+ private static Instruction[] _storeLocal;
+ private static Instruction[] _assignLocalBoxed;
+ private static Instruction[] _storeLocalBoxed;
+ private static Instruction[] _assignLocalToClosure;
+ private static Instruction[] _initReference;
+ private static Instruction[] _initImmutableRefBox;
+ private static Instruction[] _parameterBox;
+ private static Instruction[] _parameter;
+
+ public void EmitLoadLocal(int index) {
+ if (_loadLocal == null) {
+ _loadLocal = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _loadLocal.Length) {
+ Emit(_loadLocal[index] ?? (_loadLocal[index] = new LoadLocalInstruction(index)));
+ } else {
+ Emit(new LoadLocalInstruction(index));
+ }
+ }
+
+ public void EmitLoadLocalBoxed(int index) {
+ Emit(LoadLocalBoxed(index));
+ }
+
+ internal static Instruction LoadLocalBoxed(int index) {
+ if (_loadLocalBoxed == null) {
+ _loadLocalBoxed = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _loadLocalBoxed.Length) {
+ return _loadLocalBoxed[index] ?? (_loadLocalBoxed[index] = new LoadLocalBoxedInstruction(index));
+ } else {
+ return new LoadLocalBoxedInstruction(index);
+ }
+ }
+
+ public void EmitLoadLocalFromClosure(int index) {
+ if (_loadLocalFromClosure == null) {
+ _loadLocalFromClosure = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _loadLocalFromClosure.Length) {
+ Emit(_loadLocalFromClosure[index] ?? (_loadLocalFromClosure[index] = new LoadLocalFromClosureInstruction(index)));
+ } else {
+ Emit(new LoadLocalFromClosureInstruction(index));
+ }
+ }
+
+ public void EmitLoadLocalFromClosureBoxed(int index) {
+ if (_loadLocalFromClosureBoxed == null) {
+ _loadLocalFromClosureBoxed = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _loadLocalFromClosureBoxed.Length) {
+ Emit(_loadLocalFromClosureBoxed[index] ?? (_loadLocalFromClosureBoxed[index] = new LoadLocalFromClosureBoxedInstruction(index)));
+ } else {
+ Emit(new LoadLocalFromClosureBoxedInstruction(index));
+ }
+ }
+
+ public void EmitAssignLocal(int index) {
+ if (_assignLocal == null) {
+ _assignLocal = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _assignLocal.Length) {
+ Emit(_assignLocal[index] ?? (_assignLocal[index] = new AssignLocalInstruction(index)));
+ } else {
+ Emit(new AssignLocalInstruction(index));
+ }
+ }
+
+ public void EmitStoreLocal(int index) {
+ if (_storeLocal == null) {
+ _storeLocal = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _storeLocal.Length) {
+ Emit(_storeLocal[index] ?? (_storeLocal[index] = new StoreLocalInstruction(index)));
+ } else {
+ Emit(new StoreLocalInstruction(index));
+ }
+ }
+
+ public void EmitAssignLocalBoxed(int index) {
+ Emit(AssignLocalBoxed(index));
+ }
+
+ internal static Instruction AssignLocalBoxed(int index) {
+ if (_assignLocalBoxed == null) {
+ _assignLocalBoxed = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _assignLocalBoxed.Length) {
+ return _assignLocalBoxed[index] ?? (_assignLocalBoxed[index] = new AssignLocalBoxedInstruction(index));
+ } else {
+ return new AssignLocalBoxedInstruction(index);
+ }
+ }
+
+ public void EmitStoreLocalBoxed(int index) {
+ Emit(StoreLocalBoxed(index));
+ }
+
+ internal static Instruction StoreLocalBoxed(int index) {
+ if (_storeLocalBoxed == null) {
+ _storeLocalBoxed = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _storeLocalBoxed.Length) {
+ return _storeLocalBoxed[index] ?? (_storeLocalBoxed[index] = new StoreLocalBoxedInstruction(index));
+ } else {
+ return new StoreLocalBoxedInstruction(index);
+ }
+ }
+
+ public void EmitAssignLocalToClosure(int index) {
+ if (_assignLocalToClosure == null) {
+ _assignLocalToClosure = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _assignLocalToClosure.Length) {
+ Emit(_assignLocalToClosure[index] ?? (_assignLocalToClosure[index] = new AssignLocalToClosureInstruction(index)));
+ } else {
+ Emit(new AssignLocalToClosureInstruction(index));
+ }
+ }
+
+ public void EmitStoreLocalToClosure(int index) {
+ EmitAssignLocalToClosure(index);
+ EmitPop();
+ }
+
+ public void EmitInitializeLocal(int index, Type type) {
+ object value = ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(type);
+ if (value != null) {
+ Emit(new InitializeLocalInstruction.ImmutableValue(index, value));
+ } else if (type.IsValueType()) {
+ Emit(new InitializeLocalInstruction.MutableValue(index, type));
+ } else {
+ Emit(InitReference(index));
+ }
+ }
+
+ internal void EmitInitializeParameter(int index) {
+ Emit(Parameter(index));
+ }
+
+ internal static Instruction Parameter(int index) {
+ if (_parameter == null) {
+ _parameter = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _parameter.Length) {
+ return _parameter[index] ?? (_parameter[index] = new InitializeLocalInstruction.Parameter(index));
+ }
+
+ return new InitializeLocalInstruction.Parameter(index);
+ }
+
+ internal static Instruction ParameterBox(int index) {
+ if (_parameterBox == null) {
+ _parameterBox = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _parameterBox.Length) {
+ return _parameterBox[index] ?? (_parameterBox[index] = new InitializeLocalInstruction.ParameterBox(index));
+ }
+
+ return new InitializeLocalInstruction.ParameterBox(index);
+ }
+
+ internal static Instruction InitReference(int index) {
+ if (_initReference == null) {
+ _initReference = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _initReference.Length) {
+ return _initReference[index] ?? (_initReference[index] = new InitializeLocalInstruction.Reference(index));
+ }
+
+ return new InitializeLocalInstruction.Reference(index);
+ }
+
+ internal static Instruction InitImmutableRefBox(int index) {
+ if (_initImmutableRefBox == null) {
+ _initImmutableRefBox = new Instruction[LocalInstrCacheSize];
+ }
+
+ if (index < _initImmutableRefBox.Length) {
+ return _initImmutableRefBox[index] ?? (_initImmutableRefBox[index] = new InitializeLocalInstruction.ImmutableBox(index, null));
+ }
+
+ return new InitializeLocalInstruction.ImmutableBox(index, null);
+ }
+
+ public void EmitNewRuntimeVariables(int count) {
+ Emit(new RuntimeVariablesInstruction(count));
+ }
+
+ #endregion
+
+ #region Array Operations
+
+ public void EmitGetArrayItem(Type arrayType) {
+ Type elementType = arrayType.GetElementType();
+ if (elementType.IsClass() || elementType.IsInterface()) {
+ Emit(InstructionFactory<object>.Factory.GetArrayItem());
+ } else {
+ Emit(InstructionFactory.GetFactory(elementType).GetArrayItem());
+ }
+ }
+
+ public void EmitSetArrayItem(Type arrayType) {
+ Type elementType = arrayType.GetElementType();
+ if (elementType.IsClass() || elementType.IsInterface()) {
+ Emit(InstructionFactory<object>.Factory.SetArrayItem());
+ } else {
+ Emit(InstructionFactory.GetFactory(elementType).SetArrayItem());
+ }
+ }
+
+ public void EmitNewArray(Type elementType) {
+ Emit(InstructionFactory.GetFactory(elementType).NewArray());
+ }
+
+ public void EmitNewArrayBounds(Type elementType, int rank) {
+ Emit(new NewArrayBoundsInstruction(elementType, rank));
+ }
+
+ public void EmitNewArrayInit(Type elementType, int elementCount) {
+ Emit(InstructionFactory.GetFactory(elementType).NewArrayInit(elementCount));
+ }
+
+ #endregion
+
+ #region Arithmetic Operations
+
+ public void EmitAdd(Type type, bool @checked) {
+ if (@checked) {
+ Emit(AddOvfInstruction.Create(type));
+ } else {
+ Emit(AddInstruction.Create(type));
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ public void EmitSub(Type type, bool @checked) {
+ throw new NotSupportedException();
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ public void EmitMul(Type type, bool @checked) {
+ throw new NotSupportedException();
+ }
+
+ public void EmitDiv(Type type) {
+ Emit(DivInstruction.Create(type));
+ }
+
+ #endregion
+
+ #region Comparisons
+
+ public void EmitEqual(Type type) {
+ Emit(EqualInstruction.Create(type));
+ }
+
+ public void EmitNotEqual(Type type) {
+ Emit(NotEqualInstruction.Create(type));
+ }
+
+ public void EmitLessThan(Type type) {
+ Emit(LessThanInstruction.Create(type));
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ public void EmitLessThanOrEqual(Type type) {
+ throw new NotSupportedException();
+ }
+
+ public void EmitGreaterThan(Type type) {
+ Emit(GreaterThanInstruction.Create(type));
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
+ public void EmitGreaterThanOrEqual(Type type) {
+ throw new NotSupportedException();
+ }
+
+ #endregion
+
+ #region Conversions
+
+ public void EmitNumericConvertChecked(TypeCode from, TypeCode to) {
+ Emit(new NumericConvertInstruction.Checked(from, to));
+ }
+
+ public void EmitNumericConvertUnchecked(TypeCode from, TypeCode to) {
+ Emit(new NumericConvertInstruction.Unchecked(from, to));
+ }
+
+ #endregion
+
+ #region Boolean Operators
+
+ public void EmitNot() {
+ Emit(NotInstruction.Instance);
+ }
+
+ #endregion
+
+ #region Types
+
+ public void EmitDefaultValue(Type type) {
+ Emit(InstructionFactory.GetFactory(type).DefaultValue());
+ }
+
+ public void EmitNew(ConstructorInfo constructorInfo) {
+ Emit(new NewInstruction(constructorInfo));
+ }
+
+ internal void EmitCreateDelegate(LightDelegateCreator creator) {
+ Emit(new CreateDelegateInstruction(creator));
+ }
+
+ public void EmitTypeEquals() {
+ Emit(TypeEqualsInstruction.Instance);
+ }
+
+ public void EmitTypeIs(Type type) {
+ Emit(InstructionFactory.GetFactory(type).TypeIs());
+ }
+
+ public void EmitTypeAs(Type type) {
+ Emit(InstructionFactory.GetFactory(type).TypeAs());
+ }
+
+ #endregion
+
+ #region Fields and Methods
+
+ private static readonly Dictionary<FieldInfo, Instruction> _loadFields = new Dictionary<FieldInfo, Instruction>();
+
+ public void EmitLoadField(FieldInfo field) {
+ Emit(GetLoadField(field));
+ }
+
+ private Instruction GetLoadField(FieldInfo field) {
+ lock (_loadFields) {
+ Instruction instruction;
+ if (!_loadFields.TryGetValue(field, out instruction)) {
+ if (field.IsStatic) {
+ instruction = new LoadStaticFieldInstruction(field);
+ } else {
+ instruction = new LoadFieldInstruction(field);
+ }
+ _loadFields.Add(field, instruction);
+ }
+ return instruction;
+ }
+ }
+
+ public void EmitStoreField(FieldInfo field) {
+ if (field.IsStatic) {
+ Emit(new StoreStaticFieldInstruction(field));
+ } else {
+ Emit(new StoreFieldInstruction(field));
+ }
+ }
+
+ #endregion
+
+ #region Dynamic
+
+ public void EmitDynamic(Type type, CallSiteBinder binder) {
+ Emit(CreateDynamicInstruction(type, binder));
+ }
+
+ #region Generated Dynamic InstructionList Factory
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_instructionlist_factory from: generate_dynamic_instructions.py
+
+ public void EmitDynamic<T0, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TRet>.Factory(binder));
+ }
+
+ public void EmitDynamic<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>(CallSiteBinder binder) {
+ Emit(DynamicInstruction<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TRet>.Factory(binder));
+ }
+
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ private static Dictionary<Type, Func<CallSiteBinder, Instruction>> _factories =
+ new Dictionary<Type, Func<CallSiteBinder, Instruction>>();
+
+ /// <exception cref="SecurityException">Instruction can't be created due to insufficient privileges.</exception>
+ internal static Instruction CreateDynamicInstruction(Type delegateType, CallSiteBinder binder) {
+ Func<CallSiteBinder, Instruction> factory;
+ lock (_factories) {
+ if (!_factories.TryGetValue(delegateType, out factory)) {
+ if (delegateType.GetMethod("Invoke").ReturnType == typeof(void)) {
+ // TODO: We should generally support void returning binders but the only
+ // ones that exist are delete index/member who's perf isn't that critical.
+ return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder), true);
+ }
+
+ Type instructionType = DynamicInstructionN.GetDynamicInstructionType(delegateType);
+ if (instructionType == null) {
+ return new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder));
+ }
+
+ factory = (Func<CallSiteBinder, Instruction>)instructionType.GetMethod("Factory").CreateDelegate(typeof(Func<CallSiteBinder, Instruction>));
+ _factories[delegateType] = factory;
+ }
+ }
+ return factory(binder);
+ }
+
+ #endregion
+
+ #region Control Flow
+
+ private static readonly RuntimeLabel[] EmptyRuntimeLabels = new RuntimeLabel[] { new RuntimeLabel(Interpreter.RethrowOnReturn, 0, 0) };
+
+ private RuntimeLabel[] BuildRuntimeLabels() {
+ if (_runtimeLabelCount == 0) {
+ return EmptyRuntimeLabels;
+ }
+
+ var result = new RuntimeLabel[_runtimeLabelCount + 1];
+ foreach (BranchLabel label in _labels) {
+ if (label.HasRuntimeLabel) {
+ result[label.LabelIndex] = label.ToRuntimeLabel();
+ }
+ }
+ // "return and rethrow" label:
+ result[result.Length - 1] = new RuntimeLabel(Interpreter.RethrowOnReturn, 0, 0);
+ return result;
+ }
+
+ public BranchLabel MakeLabel() {
+ if (_labels == null) {
+ _labels = new List<BranchLabel>();
+ }
+
+ var label = new BranchLabel();
+ _labels.Add(label);
+ return label;
+ }
+
+ internal void FixupBranch(int branchIndex, int offset) {
+ _instructions[branchIndex] = ((OffsetInstruction)_instructions[branchIndex]).Fixup(offset);
+ }
+
+ private int EnsureLabelIndex(BranchLabel label) {
+ if (label.HasRuntimeLabel) {
+ return label.LabelIndex;
+ }
+
+ label.LabelIndex = _runtimeLabelCount;
+ _runtimeLabelCount++;
+ return label.LabelIndex;
+ }
+
+ public int MarkRuntimeLabel() {
+ BranchLabel handlerLabel = MakeLabel();
+ MarkLabel(handlerLabel);
+ return EnsureLabelIndex(handlerLabel);
+ }
+
+ public void MarkLabel(BranchLabel label) {
+ label.Mark(this);
+ }
+
+ public void EmitGoto(BranchLabel label, bool hasResult, bool hasValue) {
+ Emit(GotoInstruction.Create(EnsureLabelIndex(label), hasResult, hasValue));
+ }
+
+ private void EmitBranch(OffsetInstruction instruction, BranchLabel label) {
+ Emit(instruction);
+ label.AddBranch(this, Count - 1);
+ }
+
+ public void EmitBranch(BranchLabel label) {
+ EmitBranch(new BranchInstruction(), label);
+ }
+
+ public void EmitBranch(BranchLabel label, bool hasResult, bool hasValue) {
+ EmitBranch(new BranchInstruction(hasResult, hasValue), label);
+ }
+
+ public void EmitCoalescingBranch(BranchLabel leftNotNull) {
+ EmitBranch(new CoalescingBranchInstruction(), leftNotNull);
+ }
+
+ public void EmitBranchTrue(BranchLabel elseLabel) {
+ EmitBranch(new BranchTrueInstruction(), elseLabel);
+ }
+
+ public void EmitBranchFalse(BranchLabel elseLabel) {
+ EmitBranch(new BranchFalseInstruction(), elseLabel);
+ }
+
+ public void EmitThrow() {
+ Emit(ThrowInstruction.Throw);
+ }
+
+ public void EmitThrowVoid() {
+ Emit(ThrowInstruction.VoidThrow);
+ }
+
+ public void EmitRethrow() {
+ Emit(ThrowInstruction.Rethrow);
+ }
+
+ public void EmitRethrowVoid() {
+ Emit(ThrowInstruction.VoidRethrow);
+ }
+
+ public void EmitEnterTryFinally(BranchLabel finallyStartLabel) {
+ Emit(EnterTryFinallyInstruction.Create(EnsureLabelIndex(finallyStartLabel)));
+ }
+
+ public void EmitEnterFinally() {
+ Emit(EnterFinallyInstruction.Instance);
+ }
+
+ public void EmitLeaveFinally() {
+ Emit(LeaveFinallyInstruction.Instance);
+ }
+
+ public void EmitLeaveFault(bool hasValue) {
+ Emit(hasValue ? LeaveFaultInstruction.NonVoid : LeaveFaultInstruction.Void);
+ }
+
+ public void EmitEnterExceptionHandlerNonVoid() {
+ Emit(EnterExceptionHandlerInstruction.NonVoid);
+ }
+
+ public void EmitEnterExceptionHandlerVoid() {
+ Emit(EnterExceptionHandlerInstruction.Void);
+ }
+
+ public void EmitLeaveExceptionHandler(bool hasValue, BranchLabel tryExpressionEndLabel) {
+ Emit(LeaveExceptionHandlerInstruction.Create(EnsureLabelIndex(tryExpressionEndLabel), hasValue));
+ }
+
+ public void EmitSwitch(Dictionary<int, int> cases) {
+ Emit(new SwitchInstruction(cases));
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LabelInfo.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LabelInfo.cs
new file mode 100644
index 00000000000..2517a85baf1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LabelInfo.cs
@@ -0,0 +1,309 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+using System.Text;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+
+ /// <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 BranchLabel label, will be mutated if Node is redefined
+ private BranchLabel _label;
+
+ // 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
+ // If there's only 1 block (the common case) it's stored here, if there's multiple blocks it's stored
+ // as a HashSet<LabelScopeInfo>
+ private object _definitions;
+
+ // Blocks that jump to this block
+ private readonly List<LabelScopeInfo> _references = new List<LabelScopeInfo>();
+
+ // 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;
+
+ internal LabelInfo(LabelTarget node) {
+ _node = node;
+ }
+
+ internal BranchLabel GetLabel(LightCompiler compiler) {
+ EnsureLabel(compiler);
+ return _label;
+ }
+
+ internal void Reference(LabelScopeInfo block) {
+ _references.Add(block);
+ if (HasDefinitions) {
+ ValidateJump(block);
+ }
+ }
+
+ 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 new InvalidOperationException(String.Format("Label target already defined: {0}", _node.Name));
+ }
+ }
+
+ AddDefinition(block);
+ block.AddLabelInfo(_node, this);
+
+ // Once defined, validate all jumps
+ if (HasDefinitions && !HasMultipleDefinitions) {
+ 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 new InvalidOperationException("Ambiguous jump");
+ }
+ // 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
+ _label = null;
+ }
+ }
+
+ private void ValidateJump(LabelScopeInfo reference) {
+ // look for a simple jump out
+ for (LabelScopeInfo j = reference; j != null; j = j.Parent) {
+ if (DefinedIn(j)) {
+ // found it, jump is valid!
+ return;
+ }
+ if (j.Kind == LabelScopeKind.Filter) {
+ break;
+ }
+ }
+
+ _acrossBlockJump = true;
+
+ if (HasMultipleDefinitions) {
+ throw new InvalidOperationException(String.Format("Ambiguous jump {0}", _node.Name));
+ }
+
+ // We didn't find an outward jump. Look for a jump across blocks
+ LabelScopeInfo def = FirstDefinition();
+ LabelScopeInfo common = CommonNode(def, reference, b => b.Parent);
+
+ // Validate that we aren't jumping across a finally
+ for (LabelScopeInfo j = reference; j != common; j = j.Parent) {
+ if (j.Kind == LabelScopeKind.Filter) {
+ throw new InvalidOperationException("Control cannot leave filter test");
+ }
+ }
+
+ // 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 new InvalidOperationException("Control cannot enter an expression");
+ } else {
+ throw new InvalidOperationException("Control cannot enter try");
+ }
+ }
+ }
+ }
+
+ internal void ValidateFinish() {
+ // Make sure that if this label was jumped to, it is also defined
+ if (_references.Count > 0 && !HasDefinitions) {
+ throw new InvalidOperationException("label target undefined");
+ }
+ }
+
+ private void EnsureLabel(LightCompiler compiler) {
+ if (_label == null) {
+ _label = compiler.Instructions.MakeLabel();
+ }
+ }
+
+ private bool DefinedIn(LabelScopeInfo scope) {
+ if (_definitions == scope) {
+ return true;
+ }
+
+ HashSet<LabelScopeInfo> definitions = _definitions as HashSet<LabelScopeInfo>;
+ if (definitions != null) {
+ return definitions.Contains(scope);
+ }
+ return false;
+ }
+
+ private bool HasDefinitions {
+ get {
+ return _definitions != null;
+ }
+ }
+
+ private LabelScopeInfo FirstDefinition() {
+ LabelScopeInfo scope = _definitions as LabelScopeInfo;
+ if (scope != null) {
+ return scope;
+ }
+ return ((HashSet<LabelScopeInfo>)_definitions).First();
+ }
+
+ private void AddDefinition(LabelScopeInfo scope) {
+ if (_definitions == null) {
+ _definitions = scope;
+ } else {
+ HashSet<LabelScopeInfo> set = _definitions as HashSet<LabelScopeInfo>;
+ if(set == null) {
+ _definitions = set = new HashSet<LabelScopeInfo>() { (LabelScopeInfo)_definitions };
+ }
+ set.Add(scope);
+ }
+ }
+
+ private bool HasMultipleDefinitions {
+ get {
+ return _definitions is HashSet<LabelScopeInfo>;
+ }
+ }
+
+ 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 HashSet<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;
+ }
+ }
+
+ public 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 HybridReferenceDictionary<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 HybridReferenceDictionary<LabelTarget, LabelInfo>();
+ }
+
+ Labels[target] = info;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs
new file mode 100644
index 00000000000..2875e8bf9cd
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs
@@ -0,0 +1,146 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ public abstract class LessThanInstruction : Instruction {
+ private static Instruction _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private LessThanInstruction() {
+ }
+
+ internal sealed class LessThanSByte : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ SByte right = (SByte)frame.Pop();
+ frame.Push(((SByte)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanInt16 : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Int16 right = (Int16)frame.Pop();
+ frame.Push(((Int16)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanChar : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Char right = (Char)frame.Pop();
+ frame.Push(((Char)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanInt32 : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Int32 right = (Int32)frame.Pop();
+ frame.Push(((Int32)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanInt64 : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Int64 right = (Int64)frame.Pop();
+ frame.Push(((Int64)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanByte : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Byte right = (Byte)frame.Pop();
+ frame.Push(((Byte)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanUInt16 : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ UInt16 right = (UInt16)frame.Pop();
+ frame.Push(((UInt16)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanUInt32 : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ UInt32 right = (UInt32)frame.Pop();
+ frame.Push(((UInt32)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanUInt64 : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ UInt64 right = (UInt64)frame.Pop();
+ frame.Push(((UInt64)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanSingle : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Single right = (Single)frame.Pop();
+ frame.Push(((Single)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ internal sealed class LessThanDouble : LessThanInstruction {
+ public override int Run(InterpretedFrame frame) {
+ Double right = (Double)frame.Pop();
+ frame.Push(((Double)frame.Pop()) < right);
+ return +1;
+ }
+ }
+
+ public static Instruction Create(Type type) {
+ Debug.Assert(!type.IsEnum());
+ switch (type.GetTypeCode()) {
+ case TypeCode.SByte: return _SByte ?? (_SByte = new LessThanSByte());
+ case TypeCode.Byte: return _Byte ?? (_Byte = new LessThanByte());
+ case TypeCode.Char: return _Char ?? (_Char = new LessThanChar());
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new LessThanInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new LessThanInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new LessThanInt64());
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new LessThanUInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new LessThanUInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new LessThanUInt64());
+ case TypeCode.Single: return _Single ?? (_Single = new LessThanSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new LessThanDouble());
+
+ default:
+ throw Assert.Unreachable;
+ }
+ }
+
+ public override string ToString() {
+ return "LessThan()";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LocalAccess.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LocalAccess.cs
new file mode 100644
index 00000000000..bc0709553d1
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LocalAccess.cs
@@ -0,0 +1,374 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using System.Collections.Generic;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal interface IBoxableInstruction {
+ Instruction BoxIfIndexMatches(int index);
+ }
+
+ internal abstract class LocalAccessInstruction : Instruction {
+ internal readonly int _index;
+
+ protected LocalAccessInstruction(int index) {
+ _index = index;
+ }
+
+ public override string ToDebugString(int instructionIndex, object cookie, Func<int, int> labelIndexer, IList<object> objects) {
+ return cookie == null ?
+ InstructionName + "(" + _index + ")" :
+ InstructionName + "(" + cookie + ": " + _index + ")";
+ }
+ }
+
+ #region Load
+
+ internal sealed class LoadLocalInstruction : LocalAccessInstruction, IBoxableInstruction {
+ internal LoadLocalInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex++] = frame.Data[_index];
+ //frame.Push(frame.Data[_index]);
+ return +1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ return (index == _index) ? InstructionList.LoadLocalBoxed(index) : null;
+ }
+ }
+
+ internal sealed class LoadLocalBoxedInstruction : LocalAccessInstruction {
+ internal LoadLocalBoxedInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var box = (StrongBox<object>)frame.Data[_index];
+ frame.Data[frame.StackIndex++] = box.Value;
+ return +1;
+ }
+ }
+
+ internal sealed class LoadLocalFromClosureInstruction : LocalAccessInstruction {
+ internal LoadLocalFromClosureInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var box = frame.Closure[_index];
+ frame.Data[frame.StackIndex++] = box.Value;
+ return +1;
+ }
+ }
+
+ internal sealed class LoadLocalFromClosureBoxedInstruction : LocalAccessInstruction {
+ internal LoadLocalFromClosureBoxedInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var box = frame.Closure[_index];
+ frame.Data[frame.StackIndex++] = box;
+ return +1;
+ }
+ }
+
+ #endregion
+
+ #region Store, Assign
+
+ internal sealed class AssignLocalInstruction : LocalAccessInstruction, IBoxableInstruction {
+ internal AssignLocalInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = frame.Peek();
+ return +1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ return (index == _index) ? InstructionList.AssignLocalBoxed(index) : null;
+ }
+ }
+
+ internal sealed class StoreLocalInstruction : LocalAccessInstruction, IBoxableInstruction {
+ internal StoreLocalInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = frame.Data[--frame.StackIndex];
+ //frame.Data[_index] = frame.Pop();
+ return +1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ return (index == _index) ? InstructionList.StoreLocalBoxed(index) : null;
+ }
+ }
+
+ internal sealed class AssignLocalBoxedInstruction : LocalAccessInstruction {
+ internal AssignLocalBoxedInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var box = (StrongBox<object>)frame.Data[_index];
+ box.Value = frame.Peek();
+ return +1;
+ }
+ }
+
+ internal sealed class StoreLocalBoxedInstruction : LocalAccessInstruction {
+ internal StoreLocalBoxedInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 0; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var box = (StrongBox<object>)frame.Data[_index];
+ box.Value = frame.Data[--frame.StackIndex];
+ return +1;
+ }
+ }
+
+ internal sealed class AssignLocalToClosureInstruction : LocalAccessInstruction {
+ internal AssignLocalToClosureInstruction(int index)
+ : base(index) {
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var box = frame.Closure[_index];
+ box.Value = frame.Peek();
+ return +1;
+ }
+ }
+
+ #endregion
+
+ #region Initialize
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors")]
+ internal abstract class InitializeLocalInstruction : LocalAccessInstruction {
+ internal InitializeLocalInstruction(int index)
+ : base(index) {
+ }
+
+ internal sealed class Reference : InitializeLocalInstruction, IBoxableInstruction {
+ internal Reference(int index)
+ : base(index) {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = null;
+ return 1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ return (index == _index) ? InstructionList.InitImmutableRefBox(index) : null;
+ }
+
+ public override string InstructionName {
+ get { return "InitRef"; }
+ }
+ }
+
+ internal sealed class ImmutableValue : InitializeLocalInstruction, IBoxableInstruction {
+ private readonly object _defaultValue;
+
+ internal ImmutableValue(int index, object defaultValue)
+ : base(index) {
+ _defaultValue = defaultValue;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = _defaultValue;
+ return 1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ return (index == _index) ? new ImmutableBox(index, _defaultValue) : null;
+ }
+
+ public override string InstructionName {
+ get { return "InitImmutableValue"; }
+ }
+ }
+
+ internal sealed class ImmutableBox : InitializeLocalInstruction {
+ // immutable value:
+ private readonly object _defaultValue;
+
+ internal ImmutableBox(int index, object defaultValue)
+ : base(index) {
+ _defaultValue = defaultValue;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = new StrongBox<object>(_defaultValue);
+ return 1;
+ }
+
+ public override string InstructionName {
+ get { return "InitImmutableBox"; }
+ }
+ }
+
+ internal sealed class ParameterBox : InitializeLocalInstruction {
+ public ParameterBox(int index)
+ : base(index) {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = new StrongBox<object>(frame.Data[_index]);
+ return 1;
+ }
+
+ }
+
+ internal sealed class Parameter : InitializeLocalInstruction, IBoxableInstruction {
+ internal Parameter(int index)
+ : base(index) {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ // nop
+ return 1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ if (index == _index) {
+ return InstructionList.ParameterBox(index);
+ }
+ return null;
+ }
+
+ public override string InstructionName {
+ get { return "InitParameter"; }
+ }
+ }
+
+ internal sealed class MutableValue : InitializeLocalInstruction, IBoxableInstruction {
+ private readonly Type _type;
+
+ internal MutableValue(int index, Type type)
+ : base(index) {
+ _type = type;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ try {
+ frame.Data[_index] = Activator.CreateInstance(_type);
+ } catch (TargetInvocationException e) {
+ ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ throw e.InnerException;
+ }
+
+ return 1;
+ }
+
+ public Instruction BoxIfIndexMatches(int index) {
+ return (index == _index) ? new MutableBox(index, _type) : null;
+ }
+
+ public override string InstructionName {
+ get { return "InitMutableValue"; }
+ }
+ }
+
+ internal sealed class MutableBox : InitializeLocalInstruction {
+ private readonly Type _type;
+
+ internal MutableBox(int index, Type type)
+ : base(index) {
+ _type = type;
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[_index] = new StrongBox<object>(Activator.CreateInstance(_type));
+ return 1;
+ }
+
+ public override string InstructionName {
+ get { return "InitMutableBox"; }
+ }
+ }
+ }
+
+ #endregion
+
+ #region RuntimeVariables
+
+ internal sealed class RuntimeVariablesInstruction : Instruction {
+ private readonly int _count;
+
+ public RuntimeVariablesInstruction(int count) {
+ _count = count;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+ public override int ConsumedStack { get { return _count; } }
+
+ public override int Run(InterpretedFrame frame) {
+ var ret = new IStrongBox[_count];
+ for (int i = ret.Length - 1; i >= 0; i--) {
+ ret[i] = (IStrongBox)frame.Pop();
+ }
+ frame.Push(RuntimeVariables.Create(ret));
+ return +1;
+ }
+
+ public override string ToString() {
+ return "GetRuntimeVariables()";
+ }
+ }
+
+ #endregion
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs
new file mode 100644
index 00000000000..f7da9f46dd3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs
@@ -0,0 +1,162 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal abstract class NotEqualInstruction : Instruction {
+ // Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
+ private static Instruction _Reference, _Boolean, _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double;
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private NotEqualInstruction() {
+ }
+
+ internal sealed class NotEqualBoolean : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Boolean)frame.Pop()) != ((Boolean)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualSByte : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((SByte)frame.Pop()) != ((SByte)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualInt16 : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Int16)frame.Pop()) != ((Int16)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualChar : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Char)frame.Pop()) != ((Char)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualInt32 : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Int32)frame.Pop()) != ((Int32)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualInt64 : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Int64)frame.Pop()) != ((Int64)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualByte : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Byte)frame.Pop()) != ((Byte)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualUInt16 : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((UInt16)frame.Pop()) != ((UInt16)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualUInt32 : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((UInt32)frame.Pop()) != ((UInt32)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualUInt64 : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((UInt64)frame.Pop()) != ((UInt64)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualSingle : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Single)frame.Pop()) != ((Single)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualDouble : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(((Double)frame.Pop()) != ((Double)frame.Pop()));
+ return +1;
+ }
+ }
+
+ internal sealed class NotEqualReference : NotEqualInstruction {
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(frame.Pop() != frame.Pop());
+ return +1;
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ public static Instruction Create(Type type) {
+ // Boxed enums can be unboxed as their underlying types:
+ switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) {
+ case TypeCode.Boolean: return _Boolean ?? (_Boolean = new NotEqualBoolean());
+ case TypeCode.SByte: return _SByte ?? (_SByte = new NotEqualSByte());
+ case TypeCode.Byte: return _Byte ?? (_Byte = new NotEqualByte());
+ case TypeCode.Char: return _Char ?? (_Char = new NotEqualChar());
+ case TypeCode.Int16: return _Int16 ?? (_Int16 = new NotEqualInt16());
+ case TypeCode.Int32: return _Int32 ?? (_Int32 = new NotEqualInt32());
+ case TypeCode.Int64: return _Int64 ?? (_Int64 = new NotEqualInt64());
+
+ case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new NotEqualInt16());
+ case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new NotEqualInt32());
+ case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new NotEqualInt64());
+
+ case TypeCode.Single: return _Single ?? (_Single = new NotEqualSingle());
+ case TypeCode.Double: return _Double ?? (_Double = new NotEqualDouble());
+
+ case TypeCode.Object:
+ if (!type.IsValueType()) {
+ return _Reference ?? (_Reference = new NotEqualReference());
+ }
+ // TODO: Nullable<T>
+ throw new NotImplementedException();
+
+ default:
+ throw new NotImplementedException();
+ }
+ }
+
+ public override string ToString() {
+ return "NotEqual()";
+ }
+ }
+}
+
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NumericConvertInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NumericConvertInstruction.cs
new file mode 100644
index 00000000000..e42515f5083
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NumericConvertInstruction.cs
@@ -0,0 +1,254 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal abstract class NumericConvertInstruction : Instruction {
+ internal readonly TypeCode _from, _to;
+
+ protected NumericConvertInstruction(TypeCode from, TypeCode to) {
+ _from = from;
+ _to = to;
+ }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override string ToString() {
+ return InstructionName + "(" + _from + "->" + _to + ")";
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
+ public sealed class Unchecked : NumericConvertInstruction {
+ public override string InstructionName { get { return "UncheckedConvert"; } }
+
+ public Unchecked(TypeCode from, TypeCode to)
+ : base(from, to) {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(Convert(frame.Pop()));
+ return +1;
+ }
+
+ private object Convert(object obj) {
+ switch (_from) {
+ case TypeCode.Byte: return ConvertInt32((Byte)obj);
+ case TypeCode.SByte: return ConvertInt32((SByte)obj);
+ case TypeCode.Int16: return ConvertInt32((Int16)obj);
+ case TypeCode.Char: return ConvertInt32((Char)obj);
+ case TypeCode.Int32: return ConvertInt32((Int32)obj);
+ case TypeCode.Int64: return ConvertInt64((Int64)obj);
+ case TypeCode.UInt16: return ConvertInt32((UInt16)obj);
+ case TypeCode.UInt32: return ConvertInt64((UInt32)obj);
+ case TypeCode.UInt64: return ConvertUInt64((UInt64)obj);
+ case TypeCode.Single: return ConvertDouble((Single)obj);
+ case TypeCode.Double: return ConvertDouble((Double)obj);
+ default: throw Assert.Unreachable;
+ }
+ }
+
+ private object ConvertInt32(int obj) {
+ unchecked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+
+ private object ConvertInt64(Int64 obj) {
+ unchecked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+
+ private object ConvertUInt64(UInt64 obj) {
+ unchecked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+
+ private object ConvertDouble(Double obj) {
+ unchecked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
+ public sealed class Checked : NumericConvertInstruction {
+ public override string InstructionName { get { return "CheckedConvert"; } }
+
+ public Checked(TypeCode from, TypeCode to)
+ : base(from, to) {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(Convert(frame.Pop()));
+ return +1;
+ }
+
+ private object Convert(object obj) {
+ switch (_from) {
+ case TypeCode.Byte: return ConvertInt32((Byte)obj);
+ case TypeCode.SByte: return ConvertInt32((SByte)obj);
+ case TypeCode.Int16: return ConvertInt32((Int16)obj);
+ case TypeCode.Char: return ConvertInt32((Char)obj);
+ case TypeCode.Int32: return ConvertInt32((Int32)obj);
+ case TypeCode.Int64: return ConvertInt64((Int64)obj);
+ case TypeCode.UInt16: return ConvertInt32((UInt16)obj);
+ case TypeCode.UInt32: return ConvertInt64((UInt32)obj);
+ case TypeCode.UInt64: return ConvertUInt64((UInt64)obj);
+ case TypeCode.Single: return ConvertDouble((Single)obj);
+ case TypeCode.Double: return ConvertDouble((Double)obj);
+ default: throw Assert.Unreachable;
+ }
+ }
+
+ private object ConvertInt32(int obj) {
+ checked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+
+ private object ConvertInt64(Int64 obj) {
+ checked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+
+ private object ConvertUInt64(UInt64 obj) {
+ checked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+
+ private object ConvertDouble(Double obj) {
+ checked {
+ switch (_to) {
+ case TypeCode.Byte: return (Byte)obj;
+ case TypeCode.SByte: return (SByte)obj;
+ case TypeCode.Int16: return (Int16)obj;
+ case TypeCode.Char: return (Char)obj;
+ case TypeCode.Int32: return (Int32)obj;
+ case TypeCode.Int64: return (Int64)obj;
+ case TypeCode.UInt16: return (UInt16)obj;
+ case TypeCode.UInt32: return (UInt32)obj;
+ case TypeCode.UInt64: return (UInt64)obj;
+ case TypeCode.Single: return (Single)obj;
+ case TypeCode.Double: return (Double)obj;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs
new file mode 100644
index 00000000000..e2c9e7d1ab7
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs
@@ -0,0 +1,117 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System.Collections.Generic;
+using System;
+using System.Diagnostics;
+using Microsoft.Scripting.Utils;
+namespace Microsoft.Scripting.Interpreter {
+ internal sealed class LoadObjectInstruction : Instruction {
+ private readonly object _value;
+
+ internal LoadObjectInstruction(object value) {
+ _value = value;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex++] = _value;
+ return +1;
+ }
+
+ public override string ToString() {
+ return "LoadObject(" + (_value ?? "null") + ")";
+ }
+ }
+
+ internal sealed class LoadCachedObjectInstruction : Instruction {
+ private readonly uint _index;
+
+ internal LoadCachedObjectInstruction(uint index) {
+ _index = index;
+ }
+
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex++] = frame.Interpreter._objects[_index];
+ return +1;
+ }
+
+ public override string ToDebugString(int instructionIndex, object cookie, Func<int, int> labelIndexer, IList<object> objects) {
+ return String.Format("LoadCached({0}: {1})", _index, objects[(int)_index]);
+ }
+
+ public override string ToString() {
+ return "LoadCached(" + _index + ")";
+ }
+ }
+
+ internal sealed class PopInstruction : Instruction {
+ internal static readonly PopInstruction Instance = new PopInstruction();
+
+ private PopInstruction() { }
+
+ public override int ConsumedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Pop();
+ return +1;
+ }
+
+ public override string ToString() {
+ return "Pop()";
+ }
+ }
+
+ // NOTE: Consider caching if used frequently
+ internal sealed class PopNInstruction : Instruction {
+ private readonly int _n;
+
+ internal PopNInstruction(int n) {
+ _n = n;
+ }
+
+ public override int ConsumedStack { get { return _n; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Pop(_n);
+ return +1;
+ }
+
+ public override string ToString() {
+ return "Pop(" + _n + ")";
+ }
+ }
+
+ internal sealed class DupInstruction : Instruction {
+ internal readonly static DupInstruction Instance = new DupInstruction();
+
+ private DupInstruction() { }
+
+ public override int ConsumedStack { get { return 0; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Data[frame.StackIndex++] = frame.Peek();
+ return +1;
+ }
+
+ public override string ToString() {
+ return "Dup()";
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs
new file mode 100644
index 00000000000..320deb5b3a6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs
@@ -0,0 +1,163 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal sealed class CreateDelegateInstruction : Instruction {
+ private readonly LightDelegateCreator _creator;
+
+ internal CreateDelegateInstruction(LightDelegateCreator delegateCreator) {
+ _creator = delegateCreator;
+ }
+
+ public override int ConsumedStack { get { return _creator.Interpreter.ClosureSize; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ StrongBox<object>[] closure;
+ if (ConsumedStack > 0) {
+ closure = new StrongBox<object>[ConsumedStack];
+ for (int i = closure.Length - 1; i >= 0; i--) {
+ closure[i] = (StrongBox<object>)frame.Pop();
+ }
+ } else {
+ closure = null;
+ }
+
+ Delegate d = _creator.CreateDelegate(closure);
+
+ frame.Push(d);
+ return +1;
+ }
+ }
+
+ internal sealed class NewInstruction : Instruction {
+ private readonly ConstructorInfo _constructor;
+ private readonly int _argCount;
+
+ public NewInstruction(ConstructorInfo constructor) {
+ _constructor = constructor;
+ _argCount = constructor.GetParameters().Length;
+
+ }
+ public override int ConsumedStack { get { return _argCount; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ object[] args = new object[_argCount];
+ for (int i = _argCount - 1; i >= 0; i--) {
+ args[i] = frame.Pop();
+ }
+
+ object ret;
+ try {
+ ret = _constructor.Invoke(args);
+ } catch (TargetInvocationException e) {
+ ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ throw e.InnerException;
+ }
+
+ frame.Push(ret);
+ return +1;
+ }
+
+ public override string ToString() {
+ return "New " + _constructor.DeclaringType.Name + "(" + _constructor + ")";
+ }
+ }
+
+ internal sealed class DefaultValueInstruction<T> : Instruction {
+ internal DefaultValueInstruction() { }
+
+ public override int ConsumedStack { get { return 0; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ frame.Push(default(T));
+ return +1;
+ }
+
+ public override string ToString() {
+ return "New " + typeof(T);
+ }
+ }
+
+ internal sealed class TypeIsInstruction<T> : Instruction {
+ internal TypeIsInstruction() { }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ // unfortunately Type.IsInstanceOfType() is 35-times slower than "is T" so we use generic code:
+ frame.Push(ScriptingRuntimeHelpers.BooleanToObject(frame.Pop() is T));
+ return +1;
+ }
+
+ public override string ToString() {
+ return "TypeIs " + typeof(T).Name;
+ }
+ }
+
+ internal sealed class TypeAsInstruction<T> : Instruction {
+ internal TypeAsInstruction() { }
+
+ public override int ConsumedStack { get { return 1; } }
+ public override int ProducedStack { get { return 1; } }
+
+ public override int Run(InterpretedFrame frame) {
+ // can't use as w/o generic constraint
+ object value = frame.Pop();
+ if (value is T) {
+ frame.Push(value);
+ } else {
+ frame.Push(null);
+ }
+ return +1;
+ }
+
+ public override string ToString() {
+ return "TypeAs " + typeof(T).Name;
+ }
+ }
+
+ internal sealed class TypeEqualsInstruction : Instruction {
+ public static readonly TypeEqualsInstruction Instance = new TypeEqualsInstruction();
+
+ public override int ConsumedStack { get { return 2; } }
+ public override int ProducedStack { get { return 1; } }
+
+ private TypeEqualsInstruction() {
+ }
+
+ public override int Run(InterpretedFrame frame) {
+ object type = frame.Pop();
+ object obj = frame.Pop();
+ frame.Push(ScriptingRuntimeHelpers.BooleanToObject(obj != null && (object)obj.GetType() == type));
+ return +1;
+ }
+
+ public override string InstructionName {
+ get { return "TypeEquals()"; }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/InterpretedFrame.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/InterpretedFrame.cs
new file mode 100644
index 00000000000..cd3a0784842
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/InterpretedFrame.cs
@@ -0,0 +1,297 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using Microsoft.Scripting.Utils;
+using Microsoft.Scripting.Runtime;
+
+namespace Microsoft.Scripting.Interpreter {
+#if CLR45
+ using InterpretedFrameThreadLocal = ThreadLocal<InterpretedFrame>;
+#else
+ using InterpretedFrameThreadLocal = Microsoft.Scripting.Utils.ThreadLocal<InterpretedFrame>;
+#endif
+
+ public sealed class InterpretedFrame {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly InterpretedFrameThreadLocal CurrentFrame = new InterpretedFrameThreadLocal();
+
+ internal readonly Interpreter Interpreter;
+ internal InterpretedFrame _parent;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ private int[] _continuations;
+ private int _continuationIndex;
+ private int _pendingContinuation;
+ private object _pendingValue;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ public readonly object[] Data;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ public readonly StrongBox<object>[] Closure;
+
+ public int StackIndex;
+ public int InstructionIndex;
+
+ // When a ThreadAbortException is raised from interpreted code this is the first frame that caught it.
+ // No handlers within this handler re-abort the current thread when left.
+ public ExceptionHandler CurrentAbortHandler;
+
+ internal InterpretedFrame(Interpreter interpreter, StrongBox<object>[] closure) {
+ Interpreter = interpreter;
+ StackIndex = interpreter.LocalCount;
+ Data = new object[StackIndex + interpreter.Instructions.MaxStackDepth];
+
+ int c = interpreter.Instructions.MaxContinuationDepth;
+ if (c > 0) {
+ _continuations = new int[c];
+ }
+
+ Closure = closure;
+ }
+
+ public DebugInfo GetDebugInfo(int instructionIndex) {
+ return DebugInfo.GetMatchingDebugInfo(Interpreter._debugInfos, instructionIndex);
+ }
+
+ public string Name {
+ get { return Interpreter._name; }
+ }
+
+ #region Data Stack Operations
+
+ public void Push(object value) {
+ Data[StackIndex++] = value;
+ }
+
+ public void Push(bool value) {
+ Data[StackIndex++] = value ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
+ }
+
+ public void Push(int value) {
+ Data[StackIndex++] = ScriptingRuntimeHelpers.Int32ToObject(value);
+ }
+
+ public object Pop() {
+ return Data[--StackIndex];
+ }
+
+ public object Pop(int n) {
+ int si = StackIndex - n;
+ StackIndex = si;
+ return Data[si];
+ }
+
+ internal void SetStackDepth(int depth) {
+ StackIndex = Interpreter.LocalCount + depth;
+ }
+
+ public object Peek() {
+ return Data[StackIndex - 1];
+ }
+
+ public void Dup() {
+ int i = StackIndex;
+ Data[i] = Data[i - 1];
+ StackIndex = i + 1;
+ }
+
+ #endregion
+
+ #region Stack Trace
+
+ public InterpretedFrame Parent {
+ get { return _parent; }
+ }
+
+ public static bool IsInterpretedFrame(MethodBase method) {
+ ContractUtils.RequiresNotNull(method, "method");
+ return method.DeclaringType == typeof(Interpreter) && method.Name == "Run";
+ }
+
+#if FEATURE_STACK_TRACE
+ /// <summary>
+ /// A single interpreted frame might be represented by multiple subsequent Interpreter.Run CLR frames.
+ /// This method filters out the duplicate CLR frames.
+ /// </summary>
+ public static IEnumerable<StackFrame> GroupStackFrames(IEnumerable<StackFrame> stackTrace) {
+ bool inInterpretedFrame = false;
+ foreach (StackFrame frame in stackTrace) {
+ if (InterpretedFrame.IsInterpretedFrame(frame.GetMethod())) {
+ if (inInterpretedFrame) {
+ continue;
+ }
+ inInterpretedFrame = true;
+ } else {
+ inInterpretedFrame = false;
+ }
+ yield return frame;
+ }
+ }
+#endif
+
+ public IEnumerable<InterpretedFrameInfo> GetStackTraceDebugInfo() {
+ var frame = this;
+ do {
+ yield return new InterpretedFrameInfo(frame.Name, frame.GetDebugInfo(frame.InstructionIndex));
+ frame = frame.Parent;
+ } while (frame != null);
+ }
+
+ internal void SaveTraceToException(Exception exception) {
+ if (exception.GetData(typeof(InterpretedFrameInfo)) == null) {
+ exception.SetData(typeof(InterpretedFrameInfo), new List<InterpretedFrameInfo>(GetStackTraceDebugInfo()).ToArray());
+ }
+ }
+
+ public static InterpretedFrameInfo[] GetExceptionStackTrace(Exception exception) {
+ return exception.GetData(typeof(InterpretedFrameInfo)) as InterpretedFrameInfo[];
+ }
+
+#if DEBUG
+ internal string[] Trace {
+ get {
+ var trace = new List<string>();
+ var frame = this;
+ do {
+ trace.Add(frame.Name);
+ frame = frame.Parent;
+ } while (frame != null);
+ return trace.ToArray();
+ }
+ }
+#endif
+
+#if CLR45
+ internal InterpretedFrameThreadLocal Enter() {
+ var currentFrame = InterpretedFrame.CurrentFrame;
+ _parent = currentFrame.Value;
+ currentFrame.Value = this;
+ return currentFrame;
+ }
+
+ internal void Leave(InterpretedFrameThreadLocal currentFrame) {
+ currentFrame.Value = _parent;
+ }
+#else
+ internal InterpretedFrameThreadLocal.StorageInfo Enter() {
+ var currentFrame = InterpretedFrame.CurrentFrame.GetStorageInfo();
+ _parent = currentFrame.Value;
+ currentFrame.Value = this;
+ return currentFrame;
+ }
+
+ internal void Leave(InterpretedFrameThreadLocal.StorageInfo currentFrame) {
+ currentFrame.Value = _parent;
+ }
+#endif
+ #endregion
+
+ #region Continuations
+
+ public void RemoveContinuation() {
+ _continuationIndex--;
+ }
+
+ public void PushContinuation(int continuation) {
+ _continuations[_continuationIndex++] = continuation;
+ }
+
+ public int YieldToCurrentContinuation() {
+ var target = Interpreter._labels[_continuations[_continuationIndex - 1]];
+ SetStackDepth(target.StackDepth);
+ return target.Index - InstructionIndex;
+ }
+
+ public int YieldToPendingContinuation() {
+ Debug.Assert(_pendingContinuation >= 0);
+
+ RuntimeLabel pendingTarget = Interpreter._labels[_pendingContinuation];
+
+ // the current continuation might have higher priority (continuationIndex is the depth of the current continuation):
+ if (pendingTarget.ContinuationStackDepth < _continuationIndex) {
+ RuntimeLabel currentTarget = Interpreter._labels[_continuations[_continuationIndex - 1]];
+ SetStackDepth(currentTarget.StackDepth);
+ return currentTarget.Index - InstructionIndex;
+ }
+
+ SetStackDepth(pendingTarget.StackDepth);
+ if (_pendingValue != Interpreter.NoValue) {
+ Data[StackIndex - 1] = _pendingValue;
+ }
+ return pendingTarget.Index - InstructionIndex;
+ }
+
+ internal void PushPendingContinuation() {
+ Push(_pendingContinuation);
+ Push(_pendingValue);
+#if DEBUG
+ _pendingContinuation = -1;
+#endif
+ }
+
+ internal void PopPendingContinuation() {
+ _pendingValue = Pop();
+ _pendingContinuation = (int)Pop();
+ }
+
+ private static MethodInfo _Goto;
+ private static MethodInfo _VoidGoto;
+
+ internal static MethodInfo GotoMethod {
+ get { return _Goto ?? (_Goto = typeof(InterpretedFrame).GetMethod("Goto")); }
+ }
+
+ internal static MethodInfo VoidGotoMethod {
+ get { return _VoidGoto ?? (_VoidGoto = typeof(InterpretedFrame).GetMethod("VoidGoto")); }
+ }
+
+ public int VoidGoto(int labelIndex) {
+ return Goto(labelIndex, Interpreter.NoValue);
+ }
+
+ public int Goto(int labelIndex, object value) {
+ // TODO: we know this at compile time (except for compiled loop):
+ RuntimeLabel target = Interpreter._labels[labelIndex];
+ if (_continuationIndex == target.ContinuationStackDepth) {
+ SetStackDepth(target.StackDepth);
+ if (value != Interpreter.NoValue) {
+ Data[StackIndex - 1] = value;
+ }
+ return target.Index - InstructionIndex;
+ }
+
+ // if we are in the middle of executing jump we forget the previous target and replace it by a new one:
+ _pendingContinuation = labelIndex;
+ _pendingValue = value;
+ return YieldToCurrentContinuation();
+ }
+
+ #endregion
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Interpreter.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Interpreter.cs
new file mode 100644
index 00000000000..81c7d5b043f
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Interpreter.cs
@@ -0,0 +1,262 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace Microsoft.Scripting.Interpreter {
+ /// <summary>
+ /// A simple forth-style stack machine for executing Expression trees
+ /// without the need to compile to IL and then invoke the JIT. This trades
+ /// off much faster compilation time for a slower execution performance.
+ /// For code that is only run a small number of times this can be a
+ /// sweet spot.
+ ///
+ /// The core loop in the interpreter is the RunInstructions method.
+ /// </summary>
+ internal sealed class Interpreter {
+ internal static readonly object NoValue = new object();
+ internal const int RethrowOnReturn = Int32.MaxValue;
+
+ // zero: sync compilation
+ // negative: default
+ internal readonly int _compilationThreshold;
+
+ private readonly int _localCount;
+ private readonly HybridReferenceDictionary<LabelTarget, BranchLabel> _labelMapping;
+ private readonly Dictionary<ParameterExpression, LocalVariable> _closureVariables;
+
+ private readonly InstructionArray _instructions;
+ internal readonly object[] _objects;
+ internal readonly RuntimeLabel[] _labels;
+
+ internal readonly string _name;
+ private readonly ExceptionHandler[] _handlers;
+ internal readonly DebugInfo[] _debugInfos;
+
+ internal Interpreter(string name, LocalVariables locals, HybridReferenceDictionary<LabelTarget, BranchLabel> labelMapping,
+ InstructionArray instructions, ExceptionHandler[] handlers, DebugInfo[] debugInfos, int compilationThreshold) {
+
+ _name = name;
+ _localCount = locals.LocalCount;
+ _closureVariables = locals.ClosureVariables;
+
+ _instructions = instructions;
+ _objects = instructions.Objects;
+ _labels = instructions.Labels;
+ _labelMapping = labelMapping;
+
+ _handlers = handlers;
+ _debugInfos = debugInfos;
+ _compilationThreshold = compilationThreshold;
+ }
+
+ internal int ClosureSize {
+ get {
+ if (_closureVariables == null) {
+ return 0;
+ }
+ return _closureVariables.Count;
+ }
+ }
+
+ internal int LocalCount {
+ get {
+ return _localCount;
+ }
+ }
+
+ internal bool CompileSynchronously {
+ get { return _compilationThreshold <= 1; }
+ }
+
+ internal InstructionArray Instructions {
+ get { return _instructions; }
+ }
+
+ internal Dictionary<ParameterExpression, LocalVariable> ClosureVariables {
+ get { return _closureVariables; }
+ }
+
+ internal HybridReferenceDictionary<LabelTarget, BranchLabel> LabelMapping {
+ get { return _labelMapping; }
+ }
+
+ /// <summary>
+ /// Runs instructions within the given frame.
+ /// </summary>
+ /// <remarks>
+ /// Interpreted stack frames are linked via Parent reference so that each CLR frame of this method corresponds
+ /// to an interpreted stack frame in the chain. It is therefore possible to combine CLR stack traces with
+ /// interpreted stack traces by aligning interpreted frames to the frames of this method.
+ /// Each group of subsequent frames of Run method corresponds to a single interpreted frame.
+ /// </remarks>
+ [SpecialName, MethodImpl(MethodImplOptions.NoInlining)]
+ public void Run(InterpretedFrame frame) {
+ while (true) {
+ try {
+ var instructions = _instructions.Instructions;
+ int index = frame.InstructionIndex;
+ while (index < instructions.Length) {
+ index += instructions[index].Run(frame);
+ frame.InstructionIndex = index;
+ }
+ return;
+ } catch (Exception exception) {
+ switch (HandleException(frame, exception)) {
+ case ExceptionHandlingResult.Rethrow: throw;
+ case ExceptionHandlingResult.Continue: continue;
+ case ExceptionHandlingResult.Return: return;
+ }
+ }
+ }
+ }
+
+ private ExceptionHandlingResult HandleException(InterpretedFrame frame, Exception exception) {
+ frame.SaveTraceToException(exception);
+ ExceptionHandler handler;
+ frame.InstructionIndex += GotoHandler(frame, exception, out handler);
+
+ if (handler == null || handler.IsFault) {
+ // run finally/fault blocks:
+ Run(frame);
+
+ // a finally block can throw an exception caught by a handler, which cancels the previous exception:
+ if (frame.InstructionIndex == RethrowOnReturn) {
+ return ExceptionHandlingResult.Rethrow;
+ }
+ return ExceptionHandlingResult.Return;
+ }
+
+#if FEATURE_THREAD
+ // stay in the current catch so that ThreadAbortException is not rethrown by CLR:
+ var abort = exception as ThreadAbortException;
+ if (abort != null) {
+ _anyAbortException = abort;
+ frame.CurrentAbortHandler = handler;
+ }
+#endif
+ while (true) {
+ try {
+ var instructions = _instructions.Instructions;
+ int index = frame.InstructionIndex;
+
+ while (index < instructions.Length) {
+ var curInstr = instructions[index];
+
+ index += curInstr.Run(frame);
+ frame.InstructionIndex = index;
+
+ if (curInstr is LeaveExceptionHandlerInstruction) {
+ // we've completed handling of this exception
+ return ExceptionHandlingResult.Continue;
+ }
+ }
+
+ if (frame.InstructionIndex == RethrowOnReturn) {
+ return ExceptionHandlingResult.Rethrow;
+ }
+
+ return ExceptionHandlingResult.Return;
+ } catch (Exception nestedException) {
+ switch (HandleException(frame, nestedException)) {
+ case ExceptionHandlingResult.Rethrow: throw;
+ case ExceptionHandlingResult.Continue: continue;
+ case ExceptionHandlingResult.Return: return ExceptionHandlingResult.Return;
+ default: throw Assert.Unreachable;
+ }
+ }
+ }
+ }
+
+ enum ExceptionHandlingResult {
+ Rethrow,
+ Continue,
+ Return
+ }
+
+#if FEATURE_THREAD
+ // To get to the current AbortReason object on Thread.CurrentThread
+ // we need to use ExceptionState property of any ThreadAbortException instance.
+ [ThreadStatic]
+ private static ThreadAbortException _anyAbortException = null;
+
+ internal static void AbortThreadIfRequested(InterpretedFrame frame, int targetLabelIndex) {
+ var abortHandler = frame.CurrentAbortHandler;
+ if (abortHandler != null && !abortHandler.IsInside(frame.Interpreter._labels[targetLabelIndex].Index)) {
+ frame.CurrentAbortHandler = null;
+
+ var currentThread = Thread.CurrentThread;
+ if ((currentThread.ThreadState & System.Threading.ThreadState.AbortRequested) != 0) {
+ Debug.Assert(_anyAbortException != null);
+
+#if FEATURE_EXCEPTION_STATE
+ // The current abort reason needs to be preserved.
+ currentThread.Abort(_anyAbortException.ExceptionState);
+#else
+ currentThread.Abort();
+#endif
+ }
+ }
+ }
+#else
+ internal static void AbortThreadIfRequested(InterpretedFrame frame, int targetLabelIndex) {
+ // nop
+ }
+#endif
+
+ internal ExceptionHandler GetBestHandler(int instructionIndex, Type exceptionType) {
+ ExceptionHandler best = null;
+ foreach (var handler in _handlers) {
+ if (handler.Matches(exceptionType, instructionIndex)) {
+ if (handler.IsBetterThan(best)) {
+ best = handler;
+ }
+ }
+ }
+ return best;
+ }
+
+ internal int ReturnAndRethrowLabelIndex {
+ get {
+ // the last label is "return and rethrow" label:
+ Debug.Assert(_labels[_labels.Length - 1].Index == RethrowOnReturn);
+ return _labels.Length - 1;
+ }
+ }
+
+ internal int GotoHandler(InterpretedFrame frame, object exception, out ExceptionHandler handler) {
+ handler = GetBestHandler(frame.InstructionIndex, exception.GetType());
+ if (handler == null) {
+ return frame.Goto(ReturnAndRethrowLabelIndex, Interpreter.NoValue);
+ } else {
+ return frame.Goto(handler.LabelIndex, exception);
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs
new file mode 100644
index 00000000000..cf88b40df59
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs
@@ -0,0 +1,1645 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+using Microsoft.Scripting.Ast;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+
+using AstUtils = Microsoft.Scripting.Ast.Utils;
+using Microsoft.Scripting.Utils;
+using Microsoft.Scripting.Runtime;
+using System.Security;
+
+namespace Microsoft.Scripting.Interpreter {
+ public sealed class ExceptionHandler {
+ public readonly Type ExceptionType;
+ public readonly int StartIndex;
+ public readonly int EndIndex;
+ public readonly int LabelIndex;
+ public readonly int HandlerStartIndex;
+
+ public bool IsFault { get { return ExceptionType == null; } }
+
+ internal ExceptionHandler(int start, int end, int labelIndex, int handlerStartIndex, Type exceptionType) {
+ StartIndex = start;
+ EndIndex = end;
+ LabelIndex = labelIndex;
+ ExceptionType = exceptionType;
+ HandlerStartIndex = handlerStartIndex;
+ }
+
+ public bool Matches(Type exceptionType, int index) {
+ if (index >= StartIndex && index < EndIndex) {
+ if (ExceptionType == null || ExceptionType.IsAssignableFrom(exceptionType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool IsBetterThan(ExceptionHandler other) {
+ if (other == null) return true;
+
+ if (StartIndex == other.StartIndex && EndIndex == other.EndIndex) {
+ return HandlerStartIndex < other.HandlerStartIndex;
+ }
+
+ if (StartIndex > other.StartIndex) {
+ Debug.Assert(EndIndex <= other.EndIndex);
+ return true;
+ } else if (EndIndex < other.EndIndex) {
+ Debug.Assert(StartIndex == other.StartIndex);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ internal bool IsInside(int index) {
+ return index >= StartIndex && index < EndIndex;
+ }
+
+ public override string ToString() {
+ return String.Format("{0} [{1}-{2}] [{3}->]",
+ (IsFault ? "fault" : "catch(" + ExceptionType.Name + ")"),
+ StartIndex, EndIndex,
+ HandlerStartIndex
+ );
+ }
+ }
+
+ [Serializable]
+ public class DebugInfo {
+ // TODO: readonly
+
+ public int StartLine, EndLine;
+ public int Index;
+ public string FileName;
+ public bool IsClear;
+ private static readonly DebugInfoComparer _debugComparer = new DebugInfoComparer();
+
+ private class DebugInfoComparer : IComparer<DebugInfo> {
+ //We allow comparison between int and DebugInfo here
+ int IComparer<DebugInfo>.Compare(DebugInfo d1, DebugInfo d2) {
+ if (d1.Index > d2.Index) return 1;
+ else if (d1.Index == d2.Index) return 0;
+ else return -1;
+ }
+ }
+
+ public static DebugInfo GetMatchingDebugInfo(DebugInfo[] debugInfos, int index) {
+ //Create a faked DebugInfo to do the search
+ DebugInfo d = new DebugInfo { Index = index };
+
+ //to find the closest debug info before the current index
+
+ int i = Array.BinarySearch<DebugInfo>(debugInfos, d, _debugComparer);
+ if (i < 0) {
+ //~i is the index for the first bigger element
+ //if there is no bigger element, ~i is the length of the array
+ i = ~i;
+ if (i == 0) {
+ return null;
+ }
+ //return the last one that is smaller
+ i = i - 1;
+ }
+
+ return debugInfos[i];
+ }
+
+ public override string ToString() {
+ if (IsClear) {
+ return String.Format("{0}: clear", Index);
+ } else {
+ return String.Format("{0}: [{1}-{2}] '{3}'", Index, StartLine, EndLine, FileName);
+ }
+ }
+ }
+
+ // TODO:
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]
+ [Serializable]
+ public struct InterpretedFrameInfo {
+ public readonly string MethodName;
+
+ // TODO:
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public readonly DebugInfo DebugInfo;
+
+ public InterpretedFrameInfo(string methodName, DebugInfo info) {
+ MethodName = methodName;
+ DebugInfo = info;
+ }
+
+ public override string ToString() {
+ return MethodName + (DebugInfo != null ? ": " + DebugInfo.ToString() : null);
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ public sealed class LightCompiler {
+ internal const int DefaultCompilationThreshold = 32;
+
+ // zero: sync compilation
+ private readonly int _compilationThreshold;
+
+ private readonly InstructionList _instructions;
+ private readonly LocalVariables _locals = new LocalVariables();
+
+ private readonly List<ExceptionHandler> _handlers = new List<ExceptionHandler>();
+
+ private readonly List<DebugInfo> _debugInfos = new List<DebugInfo>();
+ private readonly HybridReferenceDictionary<LabelTarget, LabelInfo> _treeLabels = new HybridReferenceDictionary<LabelTarget, LabelInfo>();
+ private LabelScopeInfo _labelBlock = new LabelScopeInfo(null, LabelScopeKind.Lambda);
+
+ private readonly Stack<ParameterExpression> _exceptionForRethrowStack = new Stack<ParameterExpression>();
+
+ // Set to true to force compiliation of this lambda.
+ // This disables the interpreter for this lambda. We still need to
+ // walk it, however, to resolve variables closed over from the parent
+ // lambdas (because they may be interpreted).
+ private bool _forceCompile;
+
+ private readonly LightCompiler _parent;
+
+ private static LocalDefinition[] EmptyLocals = new LocalDefinition[0];
+
+ internal LightCompiler(int compilationThreshold) {
+ _instructions = new InstructionList();
+ _compilationThreshold = compilationThreshold < 0 ? DefaultCompilationThreshold : compilationThreshold;
+ }
+
+ private LightCompiler(LightCompiler parent)
+ : this(parent._compilationThreshold) {
+ _parent = parent;
+ }
+
+ public InstructionList Instructions {
+ get { return _instructions; }
+ }
+
+ public LocalVariables Locals {
+ get { return _locals; }
+ }
+
+ internal static Expression Unbox(Expression strongBoxExpression) {
+ return Expression.Field(strongBoxExpression, typeof(StrongBox<object>).GetDeclaredField("Value"));
+ }
+
+ internal LightDelegateCreator CompileTop(LambdaExpression node) {
+ foreach (var p in node.Parameters) {
+ var local = _locals.DefineLocal(p, 0);
+ _instructions.EmitInitializeParameter(local.Index);
+ }
+
+ Compile(node.Body);
+
+ // pop the result of the last expression:
+ if (node.Body.Type != typeof(void) && node.ReturnType == typeof(void)) {
+ _instructions.EmitPop();
+ }
+
+ Debug.Assert(_instructions.CurrentStackDepth == (node.ReturnType != typeof(void) ? 1 : 0));
+
+ return new LightDelegateCreator(MakeInterpreter(node.Name), node);
+ }
+
+ internal LightDelegateCreator CompileTop(LightLambdaExpression node) {
+ foreach (var p in node.Parameters) {
+ var local = _locals.DefineLocal(p, 0);
+ _instructions.EmitInitializeParameter(local.Index);
+ }
+
+ Compile(node.Body);
+
+ // pop the result of the last expression:
+ if (node.Body.Type != typeof(void) && node.ReturnType == typeof(void)) {
+ _instructions.EmitPop();
+ }
+
+ Debug.Assert(_instructions.CurrentStackDepth == (node.ReturnType != typeof(void) ? 1 : 0));
+
+ return new LightDelegateCreator(MakeInterpreter(node.Name), node);
+ }
+
+ private Interpreter MakeInterpreter(string lambdaName) {
+ if (_forceCompile) {
+ return null;
+ }
+
+ var handlers = _handlers.ToArray();
+ var debugInfos = _debugInfos.ToArray();
+
+ return new Interpreter(lambdaName, _locals, GetBranchMapping(), _instructions.ToArray(), handlers, debugInfos, _compilationThreshold);
+ }
+
+
+ private void CompileConstantExpression(Expression expr) {
+ var node = (ConstantExpression)expr;
+ _instructions.EmitLoad(node.Value, node.Type);
+ }
+
+ private void CompileDefaultExpression(Expression expr) {
+ CompileDefaultExpression(expr.Type);
+ }
+
+ private void CompileDefaultExpression(Type type) {
+ if (type != typeof(void)) {
+ if (type.IsValueType()) {
+ object value = ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(type);
+ if (value != null) {
+ _instructions.EmitLoad(value);
+ } else {
+ _instructions.EmitDefaultValue(type);
+ }
+ } else {
+ _instructions.EmitLoad(null);
+ }
+ }
+ }
+
+ private LocalVariable EnsureAvailableForClosure(ParameterExpression expr) {
+ LocalVariable local;
+ if (_locals.TryGetLocalOrClosure(expr, out local)) {
+ if (!local.InClosure && !local.IsBoxed) {
+ _locals.Box(expr, _instructions);
+ }
+ return local;
+ } else if (_parent != null) {
+ _parent.EnsureAvailableForClosure(expr);
+ return _locals.AddClosureVariable(expr);
+ } else {
+ throw new InvalidOperationException("unbound variable: " + expr);
+ }
+ }
+
+ private void EnsureVariable(ParameterExpression variable) {
+ if (!_locals.ContainsVariable(variable)) {
+ EnsureAvailableForClosure(variable);
+ }
+ }
+
+ private LocalVariable ResolveLocal(ParameterExpression variable) {
+ LocalVariable local;
+ if (!_locals.TryGetLocalOrClosure(variable, out local)) {
+ local = EnsureAvailableForClosure(variable);
+ }
+ return local;
+ }
+
+ public void CompileGetVariable(ParameterExpression variable) {
+ LocalVariable local = ResolveLocal(variable);
+
+ if (local.InClosure) {
+ _instructions.EmitLoadLocalFromClosure(local.Index);
+ } else if (local.IsBoxed) {
+ _instructions.EmitLoadLocalBoxed(local.Index);
+ } else {
+ _instructions.EmitLoadLocal(local.Index);
+ }
+
+ _instructions.SetDebugCookie(variable.Name);
+ }
+
+ public void CompileGetBoxedVariable(ParameterExpression variable) {
+ LocalVariable local = ResolveLocal(variable);
+
+ if (local.InClosure) {
+ _instructions.EmitLoadLocalFromClosureBoxed(local.Index);
+ } else {
+ Debug.Assert(local.IsBoxed);
+ _instructions.EmitLoadLocal(local.Index);
+ }
+
+ _instructions.SetDebugCookie(variable.Name);
+ }
+
+ public void CompileSetVariable(ParameterExpression variable, bool isVoid) {
+ LocalVariable local = ResolveLocal(variable);
+
+ if (local.InClosure) {
+ if (isVoid) {
+ _instructions.EmitStoreLocalToClosure(local.Index);
+ } else {
+ _instructions.EmitAssignLocalToClosure(local.Index);
+ }
+ } else if (local.IsBoxed) {
+ if (isVoid) {
+ _instructions.EmitStoreLocalBoxed(local.Index);
+ } else {
+ _instructions.EmitAssignLocalBoxed(local.Index);
+ }
+ } else {
+ if (isVoid) {
+ _instructions.EmitStoreLocal(local.Index);
+ } else {
+ _instructions.EmitAssignLocal(local.Index);
+ }
+ }
+
+ _instructions.SetDebugCookie(variable.Name);
+ }
+
+ public void CompileParameterExpression(Expression expr) {
+ var node = (ParameterExpression)expr;
+ CompileGetVariable(node);
+ }
+
+ private void CompileBlockExpression(Expression expr, bool asVoid) {
+ var node = (BlockExpression)expr;
+ var end = CompileBlockStart(node);
+
+ var lastExpression = node.Expressions[node.Expressions.Count - 1];
+ Compile(lastExpression, asVoid);
+ CompileBlockEnd(end);
+ }
+
+ private LocalDefinition[] CompileBlockStart(BlockExpression node) {
+ var start = _instructions.Count;
+
+ LocalDefinition[] locals;
+ var variables = node.Variables;
+ if (variables.Count != 0) {
+ // TODO: basic flow analysis so we don't have to initialize all
+ // variables.
+ locals = new LocalDefinition[variables.Count];
+ int localCnt = 0;
+ foreach (var variable in variables) {
+ var local = _locals.DefineLocal(variable, start);
+ locals[localCnt++] = local;
+
+ _instructions.EmitInitializeLocal(local.Index, variable.Type);
+ _instructions.SetDebugCookie(variable.Name);
+ }
+ } else {
+ locals = EmptyLocals;
+ }
+
+ for (int i = 0; i < node.Expressions.Count - 1; i++) {
+ CompileAsVoid(node.Expressions[i]);
+ }
+ return locals;
+ }
+
+ private void CompileBlockEnd(LocalDefinition[] locals) {
+ foreach (var local in locals) {
+ _locals.UndefineLocal(local, _instructions.Count);
+ }
+ }
+
+ private void CompileIndexExpression(Expression expr) {
+ var index = (IndexExpression)expr;
+
+ // instance:
+ if (index.Object != null) {
+ Compile(index.Object);
+ }
+
+ // indexes, byref args not allowed.
+ foreach (var arg in index.Arguments) {
+ Compile(arg);
+ }
+
+ if (index.Indexer != null) {
+ EmitCall(index.Indexer.GetGetMethod(true));
+ } else if (index.Arguments.Count != 1) {
+ EmitCall(index.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance));
+ } else {
+ _instructions.EmitGetArrayItem(index.Object.Type);
+ }
+ }
+
+ private void CompileIndexAssignment(BinaryExpression node, bool asVoid) {
+ var index = (IndexExpression)node.Left;
+
+ if (!asVoid) {
+ throw new NotImplementedException();
+ }
+
+ // instance:
+ if (index.Object != null) {
+ Compile(index.Object);
+ }
+
+ // indexes, byref args not allowed.
+ foreach (var arg in index.Arguments) {
+ Compile(arg);
+ }
+
+ // value:
+ Compile(node.Right);
+
+ if (index.Indexer != null) {
+ EmitCall(index.Indexer.GetSetMethod(true));
+ } else if (index.Arguments.Count != 1) {
+ EmitCall(index.Object.Type.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance));
+ } else {
+ _instructions.EmitSetArrayItem(index.Object.Type);
+ }
+ }
+
+ private void CompileMemberAssignment(BinaryExpression node, bool asVoid) {
+ var member = (MemberExpression)node.Left;
+
+ PropertyInfo pi = member.Member as PropertyInfo;
+ if (pi != null) {
+ var method = pi.GetSetMethod(true);
+ Compile(member.Expression);
+ Compile(node.Right);
+
+ int start = _instructions.Count;
+ if (!asVoid) {
+ LocalDefinition local = _locals.DefineLocal(Expression.Parameter(node.Right.Type), start);
+ _instructions.EmitAssignLocal(local.Index);
+ EmitCall(method);
+ _instructions.EmitLoadLocal(local.Index);
+ _locals.UndefineLocal(local, _instructions.Count);
+ } else {
+ EmitCall(method);
+ }
+ return;
+ }
+
+ FieldInfo fi = member.Member as FieldInfo;
+ if (fi != null) {
+ if (member.Expression != null) {
+ Compile(member.Expression);
+ }
+ Compile(node.Right);
+
+ int start = _instructions.Count;
+ if (!asVoid) {
+ LocalDefinition local = _locals.DefineLocal(Expression.Parameter(node.Right.Type), start);
+ _instructions.EmitAssignLocal(local.Index);
+ _instructions.EmitStoreField(fi);
+ _instructions.EmitLoadLocal(local.Index);
+ _locals.UndefineLocal(local, _instructions.Count);
+ } else {
+ _instructions.EmitStoreField(fi);
+ }
+ return;
+ }
+
+ throw new NotImplementedException();
+ }
+
+ private void CompileVariableAssignment(BinaryExpression node, bool asVoid) {
+ this.Compile(node.Right);
+
+ var target = (ParameterExpression)node.Left;
+ CompileSetVariable(target, asVoid);
+ }
+
+ private void CompileAssignBinaryExpression(Expression expr, bool asVoid) {
+ var node = (BinaryExpression)expr;
+
+ switch (node.Left.NodeType) {
+ case ExpressionType.Index:
+ CompileIndexAssignment(node, asVoid);
+ break;
+
+ case ExpressionType.MemberAccess:
+ CompileMemberAssignment(node, asVoid);
+ break;
+
+ case ExpressionType.Parameter:
+ case ExpressionType.Extension:
+ CompileVariableAssignment(node, asVoid);
+ break;
+
+ default:
+ throw new InvalidOperationException("Invalid lvalue for assignment: " + node.Left.NodeType);
+ }
+ }
+
+ private void CompileBinaryExpression(Expression expr) {
+ var node = (BinaryExpression)expr;
+
+ if (node.Method != null) {
+ Compile(node.Left);
+ Compile(node.Right);
+ EmitCall(node.Method);
+ } else {
+ switch (node.NodeType) {
+ case ExpressionType.ArrayIndex:
+ Debug.Assert(node.Right.Type == typeof(int));
+ Compile(node.Left);
+ Compile(node.Right);
+ _instructions.EmitGetArrayItem(node.Left.Type);
+ return;
+
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.Divide:
+ CompileArithmetic(node.NodeType, node.Left, node.Right);
+ return;
+
+ case ExpressionType.Equal:
+ CompileEqual(node.Left, node.Right);
+ return;
+
+ case ExpressionType.NotEqual:
+ CompileNotEqual(node.Left, node.Right);
+ return;
+
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ CompileComparison(node.NodeType, node.Left, node.Right);
+ return;
+
+ default:
+ throw new NotImplementedException(node.NodeType.ToString());
+ }
+ }
+ }
+
+ private void CompileEqual(Expression left, Expression right) {
+ Debug.Assert(left.Type == right.Type || !left.Type.IsValueType() && !right.Type.IsValueType());
+ Compile(left);
+ Compile(right);
+ _instructions.EmitEqual(left.Type);
+ }
+
+ private void CompileNotEqual(Expression left, Expression right) {
+ Debug.Assert(left.Type == right.Type || !left.Type.IsValueType() && !right.Type.IsValueType());
+ Compile(left);
+ Compile(right);
+ _instructions.EmitNotEqual(left.Type);
+ }
+
+ private void CompileComparison(ExpressionType nodeType, Expression left, Expression right) {
+ Debug.Assert(left.Type == right.Type && TypeUtils.IsNumeric(left.Type));
+
+ // TODO:
+ // if (TypeUtils.IsNullableType(left.Type) && liftToNull) ...
+
+ Compile(left);
+ Compile(right);
+
+ switch (nodeType) {
+ case ExpressionType.LessThan: _instructions.EmitLessThan(left.Type); break;
+ case ExpressionType.LessThanOrEqual: _instructions.EmitLessThanOrEqual(left.Type); break;
+ case ExpressionType.GreaterThan: _instructions.EmitGreaterThan(left.Type); break;
+ case ExpressionType.GreaterThanOrEqual: _instructions.EmitGreaterThanOrEqual(left.Type); break;
+ default: throw Assert.Unreachable;
+ }
+ }
+
+ private void CompileArithmetic(ExpressionType nodeType, Expression left, Expression right) {
+ Debug.Assert(left.Type == right.Type && TypeUtils.IsArithmetic(left.Type));
+ Compile(left);
+ Compile(right);
+ switch (nodeType) {
+ case ExpressionType.Add: _instructions.EmitAdd(left.Type, false); break;
+ case ExpressionType.AddChecked: _instructions.EmitAdd(left.Type, true); break;
+ case ExpressionType.Subtract: _instructions.EmitSub(left.Type, false); break;
+ case ExpressionType.SubtractChecked: _instructions.EmitSub(left.Type, true); break;
+ case ExpressionType.Multiply: _instructions.EmitMul(left.Type, false); break;
+ case ExpressionType.MultiplyChecked: _instructions.EmitMul(left.Type, true); break;
+ case ExpressionType.Divide: _instructions.EmitDiv(left.Type); break;
+ default: throw Assert.Unreachable;
+ }
+ }
+
+ private void CompileConvertUnaryExpression(Expression expr) {
+ var node = (UnaryExpression)expr;
+ if (node.Method != null) {
+ Compile(node.Operand);
+
+ // We should be able to ignore Int32ToObject
+ if (node.Method != Runtime.ScriptingRuntimeHelpers.Int32ToObjectMethod) {
+ EmitCall(node.Method);
+ }
+ } else if (node.Type == typeof(void)) {
+ CompileAsVoid(node.Operand);
+ } else {
+ Compile(node.Operand);
+ CompileConvertToType(node.Operand.Type, node.Type, node.NodeType == ExpressionType.ConvertChecked);
+ }
+ }
+
+ private void CompileConvertToType(Type typeFrom, Type typeTo, bool isChecked) {
+ Debug.Assert(typeFrom != typeof(void) && typeTo != typeof(void));
+
+ if (TypeUtils.AreEquivalent(typeTo, typeFrom)) {
+ return;
+ }
+
+ TypeCode from = typeFrom.GetTypeCode();
+ TypeCode to = typeTo.GetTypeCode();
+ if (TypeUtils.IsNumeric(from) && TypeUtils.IsNumeric(to)) {
+ if (isChecked) {
+ _instructions.EmitNumericConvertChecked(from, to);
+ } else {
+ _instructions.EmitNumericConvertUnchecked(from, to);
+ }
+ return;
+ }
+
+ // TODO: Conversions to a super-class or implemented interfaces are no-op.
+ // A conversion to a non-implemented interface or an unrelated class, etc. should fail.
+ return;
+ }
+
+ private void CompileNotExpression(UnaryExpression node) {
+ if (node.Operand.Type == typeof(bool)) {
+ Compile(node.Operand);
+ _instructions.EmitNot();
+ } else {
+ throw new NotImplementedException();
+ }
+ }
+
+ private void CompileUnaryExpression(Expression expr) {
+ var node = (UnaryExpression)expr;
+
+ if (node.Method != null) {
+ Compile(node.Operand);
+ EmitCall(node.Method);
+ } else {
+ switch (node.NodeType) {
+ case ExpressionType.Not:
+ CompileNotExpression(node);
+ return;
+ case ExpressionType.TypeAs:
+ CompileTypeAsExpression(node);
+ return;
+ default:
+ throw new NotImplementedException(node.NodeType.ToString());
+ }
+ }
+ }
+
+ private void CompileAndAlsoBinaryExpression(Expression expr) {
+ CompileLogicalBinaryExpression(expr, true);
+ }
+
+ private void CompileOrElseBinaryExpression(Expression expr) {
+ CompileLogicalBinaryExpression(expr, false);
+ }
+
+ private void CompileLogicalBinaryExpression(Expression expr, bool andAlso) {
+ var node = (BinaryExpression)expr;
+ if (node.Method != null) {
+ throw new NotImplementedException();
+ }
+
+ Debug.Assert(node.Left.Type == node.Right.Type);
+
+ if (node.Left.Type == typeof(bool)) {
+ var elseLabel = _instructions.MakeLabel();
+ var endLabel = _instructions.MakeLabel();
+ Compile(node.Left);
+ if (andAlso) {
+ _instructions.EmitBranchFalse(elseLabel);
+ } else {
+ _instructions.EmitBranchTrue(elseLabel);
+ }
+ Compile(node.Right);
+ _instructions.EmitBranch(endLabel, false, true);
+ _instructions.MarkLabel(elseLabel);
+ _instructions.EmitLoad(!andAlso);
+ _instructions.MarkLabel(endLabel);
+ return;
+ }
+
+ Debug.Assert(node.Left.Type == typeof(bool?));
+ throw new NotImplementedException();
+ }
+
+ private void CompileConditionalExpression(Expression expr, bool asVoid) {
+ var node = (ConditionalExpression)expr;
+ Compile(node.Test);
+
+ if (node.IfTrue == AstUtils.Empty()) {
+ var endOfFalse = _instructions.MakeLabel();
+ _instructions.EmitBranchTrue(endOfFalse);
+ Compile(node.IfFalse, asVoid);
+ _instructions.MarkLabel(endOfFalse);
+ } else {
+ var endOfTrue = _instructions.MakeLabel();
+ _instructions.EmitBranchFalse(endOfTrue);
+ Compile(node.IfTrue, asVoid);
+
+ if (node.IfFalse != AstUtils.Empty()) {
+ var endOfFalse = _instructions.MakeLabel();
+ _instructions.EmitBranch(endOfFalse, false, !asVoid);
+ _instructions.MarkLabel(endOfTrue);
+ Compile(node.IfFalse, asVoid);
+ _instructions.MarkLabel(endOfFalse);
+ } else {
+ _instructions.MarkLabel(endOfTrue);
+ }
+ }
+ }
+
+ #region Loops
+
+ private void CompileLoopExpression(Expression expr) {
+ var node = (LoopExpression)expr;
+ var enterLoop = new EnterLoopInstruction(node, _locals, _compilationThreshold, _instructions.Count);
+
+ PushLabelBlock(LabelScopeKind.Statement);
+ LabelInfo breakLabel = DefineLabel(node.BreakLabel);
+ LabelInfo continueLabel = DefineLabel(node.ContinueLabel);
+
+ _instructions.MarkLabel(continueLabel.GetLabel(this));
+
+ // emit loop body:
+ _instructions.Emit(enterLoop);
+ CompileAsVoid(node.Body);
+
+ // emit loop branch:
+ _instructions.EmitBranch(continueLabel.GetLabel(this), expr.Type != typeof(void), false);
+
+ _instructions.MarkLabel(breakLabel.GetLabel(this));
+
+ PopLabelBlock(LabelScopeKind.Statement);
+
+ enterLoop.FinishLoop(_instructions.Count);
+ }
+
+ #endregion
+
+ private void CompileSwitchExpression(Expression expr) {
+ var node = (SwitchExpression)expr;
+
+ // Currently only supports int test values, with no method
+ if (node.SwitchValue.Type != typeof(int) || node.Comparison != null) {
+ throw new NotImplementedException();
+ }
+
+ // Test values must be constant
+ if (!node.Cases.All(c => c.TestValues.All(t => t is ConstantExpression))) {
+ throw new NotImplementedException();
+ }
+ LabelInfo end = DefineLabel(null);
+ bool hasValue = node.Type != typeof(void);
+
+ Compile(node.SwitchValue);
+ var caseDict = new Dictionary<int, int>();
+ int switchIndex = _instructions.Count;
+ _instructions.EmitSwitch(caseDict);
+
+ if (node.DefaultBody != null) {
+ Compile(node.DefaultBody);
+ } else {
+ Debug.Assert(!hasValue);
+ }
+ _instructions.EmitBranch(end.GetLabel(this), false, hasValue);
+
+ for (int i = 0; i < node.Cases.Count; i++) {
+ var switchCase = node.Cases[i];
+
+ int caseOffset = _instructions.Count - switchIndex;
+ foreach (ConstantExpression testValue in switchCase.TestValues) {
+ caseDict[(int)testValue.Value] = caseOffset;
+ }
+
+ Compile(switchCase.Body);
+
+ if (i < node.Cases.Count - 1) {
+ _instructions.EmitBranch(end.GetLabel(this), false, hasValue);
+ }
+ }
+
+ _instructions.MarkLabel(end.GetLabel(this));
+ }
+
+ private void CompileLabelExpression(Expression expr) {
+ var node = (LabelExpression)expr;
+
+ // 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)) {
+ CompileAsVoid(node.DefaultValue);
+ } else {
+ Compile(node.DefaultValue);
+ }
+ }
+
+ _instructions.MarkLabel(label.GetLabel(this));
+ }
+
+ private void CompileGotoExpression(Expression expr) {
+ var node = (GotoExpression)expr;
+ var labelInfo = ReferenceLabel(node.Target);
+
+ if (node.Value != null) {
+ Compile(node.Value);
+ }
+
+ _instructions.EmitGoto(labelInfo.GetLabel(this), node.Type != typeof(void), node.Value != null && node.Value.Type != typeof(void));
+ }
+
+ public BranchLabel GetBranchLabel(LabelTarget target) {
+ return ReferenceLabel(target).GetLabel(this);
+ }
+
+ public void PushLabelBlock(LabelScopeKind type) {
+ _labelBlock = new LabelScopeInfo(_labelBlock, type);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kind")]
+ public void PopLabelBlock(LabelScopeKind kind) {
+ Debug.Assert(_labelBlock != null && _labelBlock.Kind == kind);
+ _labelBlock = _labelBlock.Parent;
+ }
+
+ private LabelInfo EnsureLabel(LabelTarget node) {
+ LabelInfo result;
+ if (!_treeLabels.TryGetValue(node, out result)) {
+ _treeLabels[node] = result = new LabelInfo(node);
+ }
+ return result;
+ }
+
+ private LabelInfo ReferenceLabel(LabelTarget node) {
+ LabelInfo result = EnsureLabel(node);
+ result.Reference(_labelBlock);
+ return result;
+ }
+
+ internal LabelInfo DefineLabel(LabelTarget node) {
+ if (node == null) {
+ return new LabelInfo(null);
+ }
+ LabelInfo result = EnsureLabel(node);
+ result.Define(_labelBlock);
+ return result;
+ }
+
+ 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:
+ 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) {
+ return;
+ }
+
+ for (int i = 0, n = block.Expressions.Count; i < n; i++) {
+ Expression e = block.Expressions[i];
+
+ var label = e as LabelExpression;
+ if (label != null) {
+ DefineLabel(label.Target);
+ }
+ }
+ }
+
+ private HybridReferenceDictionary<LabelTarget, BranchLabel> GetBranchMapping() {
+ var newLabelMapping = new HybridReferenceDictionary<LabelTarget, BranchLabel>(_treeLabels.Count);
+ foreach (var kvp in _treeLabels) {
+ newLabelMapping[kvp.Key] = kvp.Value.GetLabel(this);
+ }
+ return newLabelMapping;
+ }
+
+ private void CompileThrowUnaryExpression(Expression expr, bool asVoid) {
+ var node = (UnaryExpression)expr;
+
+ if (node.Operand == null) {
+ CompileParameterExpression(_exceptionForRethrowStack.Peek());
+ if (asVoid) {
+ _instructions.EmitRethrowVoid();
+ } else {
+ _instructions.EmitRethrow();
+ }
+ } else {
+ Compile(node.Operand);
+ if (asVoid) {
+ _instructions.EmitThrowVoid();
+ } else {
+ _instructions.EmitThrow();
+ }
+ }
+
+ }
+
+ // TODO: remove (replace by true fault support)
+ private bool EndsWithRethrow(Expression expr) {
+ if (expr.NodeType == ExpressionType.Throw) {
+ var node = (UnaryExpression)expr;
+ return node.Operand == null;
+ }
+
+ BlockExpression block = expr as BlockExpression;
+ if (block != null) {
+ return EndsWithRethrow(block.Expressions[block.Expressions.Count - 1]);
+ }
+ return false;
+ }
+
+
+ // TODO: remove (replace by true fault support)
+ private void CompileAsVoidRemoveRethrow(Expression expr) {
+ int stackDepth = _instructions.CurrentStackDepth;
+
+ if (expr.NodeType == ExpressionType.Throw) {
+ Debug.Assert(((UnaryExpression)expr).Operand == null);
+ return;
+ }
+
+ var node = (BlockExpression)expr;
+ var end = CompileBlockStart(node);
+
+ CompileAsVoidRemoveRethrow(node.Expressions[node.Expressions.Count - 1]);
+
+ Debug.Assert(stackDepth == _instructions.CurrentStackDepth);
+
+ CompileBlockEnd(end);
+ }
+
+ private void CompileTryExpression(Expression expr) {
+ var node = (TryExpression)expr;
+
+ BranchLabel end = _instructions.MakeLabel();
+ BranchLabel gotoEnd = _instructions.MakeLabel();
+
+ int tryStart = _instructions.Count;
+
+ BranchLabel startOfFinally = null;
+ if (node.Finally != null) {
+ startOfFinally = _instructions.MakeLabel();
+ _instructions.EmitEnterTryFinally(startOfFinally);
+ }
+
+ PushLabelBlock(LabelScopeKind.Try);
+ Compile(node.Body);
+
+ bool hasValue = node.Body.Type != typeof(void);
+ int tryEnd = _instructions.Count;
+
+ // handlers jump here:
+ _instructions.MarkLabel(gotoEnd);
+ _instructions.EmitGoto(end, hasValue, hasValue);
+
+ // keep the result on the stack:
+ if (node.Handlers.Count > 0) {
+ // TODO: emulates faults (replace by true fault support)
+ if (node.Finally == null && node.Handlers.Count == 1) {
+ var handler = node.Handlers[0];
+ if (handler.Filter == null && handler.Test == typeof(Exception) && handler.Variable == null) {
+ if (EndsWithRethrow(handler.Body)) {
+ if (hasValue) {
+ _instructions.EmitEnterExceptionHandlerNonVoid();
+ } else {
+ _instructions.EmitEnterExceptionHandlerVoid();
+ }
+
+ // at this point the stack balance is prepared for the hidden exception variable:
+ int handlerLabel = _instructions.MarkRuntimeLabel();
+ int handlerStart = _instructions.Count;
+
+ CompileAsVoidRemoveRethrow(handler.Body);
+ _instructions.EmitLeaveFault(hasValue);
+ _instructions.MarkLabel(end);
+
+ _handlers.Add(new ExceptionHandler(tryStart, tryEnd, handlerLabel, handlerStart, null));
+ PopLabelBlock(LabelScopeKind.Try);
+ return;
+ }
+ }
+ }
+
+ foreach (var handler in node.Handlers) {
+ PushLabelBlock(LabelScopeKind.Catch);
+
+ if (handler.Filter != null) {
+ //PushLabelBlock(LabelScopeKind.Filter);
+ throw new NotImplementedException();
+ //PopLabelBlock(LabelScopeKind.Filter);
+ }
+
+ var parameter = handler.Variable ?? Expression.Parameter(handler.Test);
+
+ var local = _locals.DefineLocal(parameter, _instructions.Count);
+ _exceptionForRethrowStack.Push(parameter);
+
+ // add a stack balancing nop instruction (exception handling pushes the current exception):
+ if (hasValue) {
+ _instructions.EmitEnterExceptionHandlerNonVoid();
+ } else {
+ _instructions.EmitEnterExceptionHandlerVoid();
+ }
+
+ // at this point the stack balance is prepared for the hidden exception variable:
+ int handlerLabel = _instructions.MarkRuntimeLabel();
+ int handlerStart = _instructions.Count;
+
+ CompileSetVariable(parameter, true);
+ Compile(handler.Body);
+
+ _exceptionForRethrowStack.Pop();
+
+ // keep the value of the body on the stack:
+ Debug.Assert(hasValue == (handler.Body.Type != typeof(void)));
+ _instructions.EmitLeaveExceptionHandler(hasValue, gotoEnd);
+
+ _handlers.Add(new ExceptionHandler(tryStart, tryEnd, handlerLabel, handlerStart, handler.Test));
+
+ PopLabelBlock(LabelScopeKind.Catch);
+
+ _locals.UndefineLocal(local, _instructions.Count);
+ }
+
+ if (node.Fault != null) {
+ throw new NotImplementedException();
+ }
+ }
+
+ if (node.Finally != null) {
+ PushLabelBlock(LabelScopeKind.Finally);
+
+ _instructions.MarkLabel(startOfFinally);
+ _instructions.EmitEnterFinally();
+ CompileAsVoid(node.Finally);
+ _instructions.EmitLeaveFinally();
+
+ PopLabelBlock(LabelScopeKind.Finally);
+ }
+
+ _instructions.MarkLabel(end);
+
+ PopLabelBlock(LabelScopeKind.Try);
+ }
+
+ private void CompileDynamicExpression(Expression expr) {
+ var node = (DynamicExpression)expr;
+
+ foreach (var arg in node.Arguments) {
+ Compile(arg);
+ }
+
+ _instructions.EmitDynamic(node.DelegateType, node.Binder);
+ }
+
+ private void CompileMethodCallExpression(Expression expr) {
+ var node = (MethodCallExpression)expr;
+
+ var parameters = node.Method.GetParameters();
+
+ // TODO:
+ // Support pass by reference.
+ // Note that LoopCompiler needs to be updated too.
+
+ // force compilation for now for ref types
+ // also could be a mutable value type, Delegate.CreateDelegate and MethodInfo.Invoke both can't handle this, we
+ // need to generate code.
+ if (!CollectionUtils.TrueForAll(parameters, (p) => !p.ParameterType.IsByRef) ||
+ (!node.Method.IsStatic && node.Method.DeclaringType.IsValueType() && !node.Method.DeclaringType.IsPrimitive())) {
+ _forceCompile = true;
+ }
+
+ // CF bug workaround
+ // TODO: can we do better if the delegate targets LightLambda.Run* method?
+ if (PlatformAdaptationLayer.IsCompactFramework &&
+ node.Method.Name == "Invoke" && typeof(Delegate).IsAssignableFrom(node.Object.Type) && !node.Method.IsStatic) {
+
+ Compile(
+ AstUtils.Convert(
+ Expression.Call(
+ node.Object,
+ node.Object.Type.GetMethod("DynamicInvoke"),
+ Expression.NewArrayInit(typeof(object), node.Arguments.Map((e) => AstUtils.Convert(e, typeof(object))))
+ ),
+ node.Type
+ )
+ );
+
+ } else {
+ if (!node.Method.IsStatic) {
+ Compile(node.Object);
+ }
+
+ foreach (var arg in node.Arguments) {
+ Compile(arg);
+ }
+
+ EmitCall(node.Method, parameters);
+ }
+ }
+
+ public void EmitCall(MethodInfo method) {
+ EmitCall(method, method.GetParameters());
+ }
+
+ public void EmitCall(MethodInfo method, ParameterInfo[] parameters) {
+ Instruction instruction;
+
+ try {
+ instruction = CallInstruction.Create(method, parameters);
+ } catch (SecurityException) {
+ _forceCompile = true;
+
+ _instructions.Emit(new PopNInstruction((method.IsStatic ? 0 : 1) + parameters.Length));
+ if (method.ReturnType != typeof(void)) {
+ _instructions.EmitLoad(null);
+ }
+
+ return;
+ }
+
+ _instructions.Emit(instruction);
+ }
+
+ private void CompileNewExpression(Expression expr) {
+ var node = (NewExpression)expr;
+
+ if (node.Constructor != null) {
+ var parameters = node.Constructor.GetParameters();
+ if (!CollectionUtils.TrueForAll(parameters, (p) => !p.ParameterType.IsByRef)
+#if FEATURE_LCG
+ || node.Constructor.DeclaringType == typeof(DynamicMethod)
+#endif
+ ) {
+ _forceCompile = true;
+ }
+ }
+
+ if (node.Constructor != null) {
+ foreach (var arg in node.Arguments) {
+ this.Compile(arg);
+ }
+ _instructions.EmitNew(node.Constructor);
+ } else {
+ Debug.Assert(expr.Type.IsValueType());
+ _instructions.EmitDefaultValue(node.Type);
+ }
+ }
+
+ private void CompileMemberExpression(Expression expr) {
+ var node = (MemberExpression)expr;
+
+ var member = node.Member;
+ FieldInfo fi = member as FieldInfo;
+ if (fi != null) {
+ if (fi.IsLiteral) {
+ _instructions.EmitLoad(fi.GetRawConstantValue(), fi.FieldType);
+ } else if (fi.IsStatic) {
+ if (fi.IsInitOnly) {
+ _instructions.EmitLoad(fi.GetValue(null), fi.FieldType);
+ } else {
+ _instructions.EmitLoadField(fi);
+ }
+ } else {
+ Compile(node.Expression);
+ _instructions.EmitLoadField(fi);
+ }
+ return;
+ }
+
+ PropertyInfo pi = member as PropertyInfo;
+ if (pi != null) {
+ var method = pi.GetGetMethod(true);
+ if (node.Expression != null) {
+ Compile(node.Expression);
+ }
+ EmitCall(method);
+ return;
+ }
+
+
+ throw new System.NotImplementedException();
+ }
+
+ private void CompileNewArrayExpression(Expression expr) {
+ var node = (NewArrayExpression)expr;
+
+ foreach (var arg in node.Expressions) {
+ Compile(arg);
+ }
+
+ Type elementType = node.Type.GetElementType();
+ int rank = node.Expressions.Count;
+
+ if (node.NodeType == ExpressionType.NewArrayInit) {
+ _instructions.EmitNewArrayInit(elementType, rank);
+ } else if (node.NodeType == ExpressionType.NewArrayBounds) {
+ if (rank == 1) {
+ _instructions.EmitNewArray(elementType);
+ } else {
+ _instructions.EmitNewArrayBounds(elementType, rank);
+ }
+ } else {
+ throw new System.NotImplementedException();
+ }
+ }
+
+ private void CompileExtensionExpression(Expression expr) {
+ var instructionProvider = expr as IInstructionProvider;
+ if (instructionProvider != null) {
+ instructionProvider.AddInstructions(this);
+ return;
+ }
+
+ if (expr.CanReduce) {
+ Compile(expr.Reduce());
+ } else {
+ throw new System.NotImplementedException();
+ }
+ }
+
+
+ private void CompileDebugInfoExpression(Expression expr) {
+ var node = (DebugInfoExpression)expr;
+ int start = _instructions.Count;
+ var info = new DebugInfo()
+ {
+ Index = start,
+ FileName = node.Document.FileName,
+ StartLine = node.StartLine,
+ EndLine = node.EndLine,
+ IsClear = node.IsClear
+ };
+ _debugInfos.Add(info);
+ }
+
+ private void CompileRuntimeVariablesExpression(Expression expr) {
+ // Generates IRuntimeVariables for all requested variables
+ var node = (RuntimeVariablesExpression)expr;
+ foreach (var variable in node.Variables) {
+ EnsureAvailableForClosure(variable);
+ CompileGetBoxedVariable(variable);
+ }
+
+ _instructions.EmitNewRuntimeVariables(node.Variables.Count);
+ }
+
+
+ private void CompileLambdaExpression(Expression expr) {
+ var node = (LambdaExpression)expr;
+ var compiler = new LightCompiler(this);
+ var creator = compiler.CompileTop(node);
+
+ if (compiler._locals.ClosureVariables != null) {
+ foreach (ParameterExpression variable in compiler._locals.ClosureVariables.Keys) {
+ CompileGetBoxedVariable(variable);
+ }
+ }
+ _instructions.EmitCreateDelegate(creator);
+ }
+
+ private void CompileCoalesceBinaryExpression(Expression expr) {
+ var node = (BinaryExpression)expr;
+
+ if (TypeUtils.IsNullableType(node.Left.Type)) {
+ throw new NotImplementedException();
+ } else if (node.Conversion != null) {
+ throw new NotImplementedException();
+ } else {
+ var leftNotNull = _instructions.MakeLabel();
+ Compile(node.Left);
+ _instructions.EmitCoalescingBranch(leftNotNull);
+ _instructions.EmitPop();
+ Compile(node.Right);
+ _instructions.MarkLabel(leftNotNull);
+ }
+ }
+
+ private void CompileInvocationExpression(Expression expr) {
+ var node = (InvocationExpression)expr;
+
+ // TODO: LambdaOperand optimization (see compiler)
+ if (typeof(LambdaExpression).IsAssignableFrom(node.Expression.Type)) {
+ throw new System.NotImplementedException();
+ }
+
+ // TODO: do not create a new Call Expression
+ if (PlatformAdaptationLayer.IsCompactFramework) {
+ // Workaround for a bug in Compact Framework
+ Compile(
+ AstUtils.Convert(
+ Expression.Call(
+ node.Expression,
+ node.Expression.Type.GetMethod("DynamicInvoke"),
+ Expression.NewArrayInit(typeof(object), node.Arguments.Map((e) => AstUtils.Convert(e, typeof(object))))
+ ),
+ node.Type
+ )
+ );
+ } else {
+ CompileMethodCallExpression(Expression.Call(node.Expression, node.Expression.Type.GetMethod("Invoke"), node.Arguments));
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
+ private void CompileListInitExpression(Expression expr) {
+ throw new System.NotImplementedException();
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
+ private void CompileMemberInitExpression(Expression expr) {
+ throw new System.NotImplementedException();
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
+ private void CompileQuoteUnaryExpression(Expression expr) {
+ throw new System.NotImplementedException();
+ }
+
+ private void CompileUnboxUnaryExpression(Expression expr) {
+ var node = (UnaryExpression)expr;
+ // unboxing is a nop:
+ Compile(node.Operand);
+ }
+
+ private void CompileTypeEqualExpression(Expression expr) {
+ Debug.Assert(expr.NodeType == ExpressionType.TypeEqual);
+ var node = (TypeBinaryExpression)expr;
+
+ Compile(node.Expression);
+ _instructions.EmitLoad(node.TypeOperand);
+ _instructions.EmitTypeEquals();
+ }
+
+ private void CompileTypeAsExpression(UnaryExpression node) {
+ Compile(node.Operand);
+ _instructions.EmitTypeAs(node.Type);
+ }
+
+ private void CompileTypeIsExpression(Expression expr) {
+ Debug.Assert(expr.NodeType == ExpressionType.TypeIs);
+ var node = (TypeBinaryExpression)expr;
+
+ Compile(node.Expression);
+
+ // use TypeEqual for sealed types:
+ if (node.TypeOperand.IsSealed()) {
+ _instructions.EmitLoad(node.TypeOperand);
+ _instructions.EmitTypeEquals();
+ } else {
+ _instructions.EmitTypeIs(node.TypeOperand);
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "expr")]
+ private void CompileReducibleExpression(Expression expr) {
+ throw new System.NotImplementedException();
+ }
+
+ internal void Compile(Expression expr, bool asVoid) {
+ if (asVoid) {
+ CompileAsVoid(expr);
+ } else {
+ Compile(expr);
+ }
+ }
+
+ internal void CompileAsVoid(Expression expr) {
+ bool pushLabelBlock = TryPushLabelBlock(expr);
+ int startingStackDepth = _instructions.CurrentStackDepth;
+ switch (expr.NodeType) {
+ case ExpressionType.Assign:
+ CompileAssignBinaryExpression(expr, true);
+ break;
+
+ case ExpressionType.Block:
+ CompileBlockExpression(expr, true);
+ break;
+
+ case ExpressionType.Throw:
+ CompileThrowUnaryExpression(expr, true);
+ break;
+
+ case ExpressionType.Constant:
+ case ExpressionType.Default:
+ case ExpressionType.Parameter:
+ // no-op
+ break;
+
+ default:
+ CompileNoLabelPush(expr);
+ if (expr.Type != typeof(void)) {
+ _instructions.EmitPop();
+ }
+ break;
+ }
+ Debug.Assert(_instructions.CurrentStackDepth == startingStackDepth);
+ if (pushLabelBlock) {
+ PopLabelBlock(_labelBlock.Kind);
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ private void CompileNoLabelPush(Expression expr) {
+ int startingStackDepth = _instructions.CurrentStackDepth;
+ switch (expr.NodeType) {
+ case ExpressionType.Add: CompileBinaryExpression(expr); break;
+ case ExpressionType.AddChecked: CompileBinaryExpression(expr); break;
+ case ExpressionType.And: CompileBinaryExpression(expr); break;
+ case ExpressionType.AndAlso: CompileAndAlsoBinaryExpression(expr); break;
+ case ExpressionType.ArrayLength: CompileUnaryExpression(expr); break;
+ case ExpressionType.ArrayIndex: CompileBinaryExpression(expr); break;
+ case ExpressionType.Call: CompileMethodCallExpression(expr); break;
+ case ExpressionType.Coalesce: CompileCoalesceBinaryExpression(expr); break;
+ case ExpressionType.Conditional: CompileConditionalExpression(expr, expr.Type == typeof(void)); break;
+ case ExpressionType.Constant: CompileConstantExpression(expr); break;
+ case ExpressionType.Convert: CompileConvertUnaryExpression(expr); break;
+ case ExpressionType.ConvertChecked: CompileConvertUnaryExpression(expr); break;
+ case ExpressionType.Divide: CompileBinaryExpression(expr); break;
+ case ExpressionType.Equal: CompileBinaryExpression(expr); break;
+ case ExpressionType.ExclusiveOr: CompileBinaryExpression(expr); break;
+ case ExpressionType.GreaterThan: CompileBinaryExpression(expr); break;
+ case ExpressionType.GreaterThanOrEqual: CompileBinaryExpression(expr); break;
+ case ExpressionType.Invoke: CompileInvocationExpression(expr); break;
+ case ExpressionType.Lambda: CompileLambdaExpression(expr); break;
+ case ExpressionType.LeftShift: CompileBinaryExpression(expr); break;
+ case ExpressionType.LessThan: CompileBinaryExpression(expr); break;
+ case ExpressionType.LessThanOrEqual: CompileBinaryExpression(expr); break;
+ case ExpressionType.ListInit: CompileListInitExpression(expr); break;
+ case ExpressionType.MemberAccess: CompileMemberExpression(expr); break;
+ case ExpressionType.MemberInit: CompileMemberInitExpression(expr); break;
+ case ExpressionType.Modulo: CompileBinaryExpression(expr); break;
+ case ExpressionType.Multiply: CompileBinaryExpression(expr); break;
+ case ExpressionType.MultiplyChecked: CompileBinaryExpression(expr); break;
+ case ExpressionType.Negate: CompileUnaryExpression(expr); break;
+ case ExpressionType.UnaryPlus: CompileUnaryExpression(expr); break;
+ case ExpressionType.NegateChecked: CompileUnaryExpression(expr); break;
+ case ExpressionType.New: CompileNewExpression(expr); break;
+ case ExpressionType.NewArrayInit: CompileNewArrayExpression(expr); break;
+ case ExpressionType.NewArrayBounds: CompileNewArrayExpression(expr); break;
+ case ExpressionType.Not: CompileUnaryExpression(expr); break;
+ case ExpressionType.NotEqual: CompileBinaryExpression(expr); break;
+ case ExpressionType.Or: CompileBinaryExpression(expr); break;
+ case ExpressionType.OrElse: CompileOrElseBinaryExpression(expr); break;
+ case ExpressionType.Parameter: CompileParameterExpression(expr); break;
+ case ExpressionType.Power: CompileBinaryExpression(expr); break;
+ case ExpressionType.Quote: CompileQuoteUnaryExpression(expr); break;
+ case ExpressionType.RightShift: CompileBinaryExpression(expr); break;
+ case ExpressionType.Subtract: CompileBinaryExpression(expr); break;
+ case ExpressionType.SubtractChecked: CompileBinaryExpression(expr); break;
+ case ExpressionType.TypeAs: CompileUnaryExpression(expr); break;
+ case ExpressionType.TypeIs: CompileTypeIsExpression(expr); break;
+ case ExpressionType.Assign: CompileAssignBinaryExpression(expr, expr.Type == typeof(void)); break;
+ case ExpressionType.Block: CompileBlockExpression(expr, expr.Type == typeof(void)); break;
+ case ExpressionType.DebugInfo: CompileDebugInfoExpression(expr); break;
+ case ExpressionType.Decrement: CompileUnaryExpression(expr); break;
+ case ExpressionType.Dynamic: CompileDynamicExpression(expr); break;
+ case ExpressionType.Default: CompileDefaultExpression(expr); break;
+ case ExpressionType.Extension: CompileExtensionExpression(expr); break;
+ case ExpressionType.Goto: CompileGotoExpression(expr); break;
+ case ExpressionType.Increment: CompileUnaryExpression(expr); break;
+ case ExpressionType.Index: CompileIndexExpression(expr); break;
+ case ExpressionType.Label: CompileLabelExpression(expr); break;
+ case ExpressionType.RuntimeVariables: CompileRuntimeVariablesExpression(expr); break;
+ case ExpressionType.Loop: CompileLoopExpression(expr); break;
+ case ExpressionType.Switch: CompileSwitchExpression(expr); break;
+ case ExpressionType.Throw: CompileThrowUnaryExpression(expr, expr.Type == typeof(void)); break;
+ case ExpressionType.Try: CompileTryExpression(expr); break;
+ case ExpressionType.Unbox: CompileUnboxUnaryExpression(expr); break;
+ case ExpressionType.TypeEqual: CompileTypeEqualExpression(expr); break;
+ case ExpressionType.OnesComplement: CompileUnaryExpression(expr); break;
+ case ExpressionType.IsTrue: CompileUnaryExpression(expr); break;
+ case ExpressionType.IsFalse: CompileUnaryExpression(expr); 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:
+ CompileReducibleExpression(expr); break;
+ default: throw Assert.Unreachable;
+ };
+ Debug.Assert(_instructions.CurrentStackDepth == startingStackDepth + (expr.Type == typeof(void) ? 0 : 1));
+ }
+
+ public void Compile(Expression expr) {
+ bool pushLabelBlock = TryPushLabelBlock(expr);
+ CompileNoLabelPush(expr);
+ if (pushLabelBlock) {
+ PopLabelBlock(_labelBlock.Kind);
+ }
+ }
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightDelegateCreator.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightDelegateCreator.cs
new file mode 100644
index 00000000000..18ce7b90010
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightDelegateCreator.cs
@@ -0,0 +1,194 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+using Microsoft.Scripting.Ast;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+
+ /// <summary>
+ /// Manages creation of interpreted delegates. These delegates will get
+ /// compiled if they are executed often enough.
+ /// </summary>
+ internal sealed class LightDelegateCreator {
+ // null if we are forced to compile
+ private readonly Interpreter _interpreter;
+ private readonly Expression _lambda;
+
+ // Adaptive compilation support:
+ private Type _compiledDelegateType;
+ private Delegate _compiled;
+ private readonly object _compileLock = new object();
+
+ internal LightDelegateCreator(Interpreter interpreter, LambdaExpression lambda) {
+ Assert.NotNull(lambda);
+ _interpreter = interpreter;
+ _lambda = lambda;
+ }
+
+ internal LightDelegateCreator(Interpreter interpreter, LightLambdaExpression lambda) {
+ Assert.NotNull(lambda);
+ _interpreter = interpreter;
+ _lambda = lambda;
+ }
+
+ internal Interpreter Interpreter {
+ get { return _interpreter; }
+ }
+
+ private bool HasClosure {
+ get { return _interpreter != null && _interpreter.ClosureSize > 0; }
+ }
+
+ internal bool HasCompiled {
+ get { return _compiled != null; }
+ }
+
+ /// <summary>
+ /// true if the compiled delegate has the same type as the lambda;
+ /// false if the type was changed for interpretation.
+ /// </summary>
+ internal bool SameDelegateType {
+ get { return _compiledDelegateType == DelegateType; }
+ }
+
+ internal Delegate CreateDelegate() {
+ return CreateDelegate(null);
+ }
+
+ internal Delegate CreateDelegate(StrongBox<object>[] closure) {
+ if (_compiled != null) {
+ // If the delegate type we want is not a Func/Action, we can't
+ // use the compiled code directly. So instead just fall through
+ // and create an interpreted LightLambda, which will pick up
+ // the compiled delegate on its first run.
+ //
+ // Ideally, we would just rebind the compiled delegate using
+ // Delegate.CreateDelegate. Unfortunately, it doesn't work on
+ // dynamic methods.
+ if (SameDelegateType) {
+ return CreateCompiledDelegate(closure);
+ }
+ }
+
+ if (_interpreter == null) {
+ // We can't interpret, so force a compile
+ Compile(null);
+ Delegate compiled = CreateCompiledDelegate(closure);
+ Debug.Assert(compiled.GetType() == DelegateType);
+ return compiled;
+ }
+
+ // Otherwise, we'll create an interpreted LightLambda
+ return new LightLambda(this, closure, _interpreter._compilationThreshold).MakeDelegate(DelegateType);
+ }
+
+ private Type DelegateType {
+ get {
+ LambdaExpression le = _lambda as LambdaExpression;
+ if (le != null) {
+ return le.Type;
+ }
+
+ return ((LightLambdaExpression)_lambda).Type;
+ }
+ }
+
+ /// <summary>
+ /// Used by LightLambda to get the compiled delegate.
+ /// </summary>
+ internal Delegate CreateCompiledDelegate(StrongBox<object>[] closure) {
+ Debug.Assert(HasClosure == (closure != null));
+
+ if (HasClosure) {
+ // We need to apply the closure to get the actual delegate.
+ var applyClosure = (Func<StrongBox<object>[], Delegate>)_compiled;
+ return applyClosure(closure);
+ }
+ return _compiled;
+ }
+
+ /// <summary>
+ /// Create a compiled delegate for the LightLambda, and saves it so
+ /// future calls to Run will execute the compiled code instead of
+ /// interpreting.
+ /// </summary>
+ internal void Compile(object state) {
+ if (_compiled != null) {
+ return;
+ }
+
+ // Compilation is expensive, we only want to do it once.
+ lock (_compileLock) {
+ if (_compiled != null) {
+ return;
+ }
+
+ PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Interpreted lambda compiled");
+
+ // Interpreter needs a standard delegate type.
+ // So change the lambda's delegate type to Func<...> or
+ // Action<...> so it can be called from the LightLambda.Run
+ // methods.
+ LambdaExpression lambda = (_lambda as LambdaExpression) ?? (LambdaExpression)((LightLambdaExpression)_lambda).Reduce();
+ if (_interpreter != null) {
+ _compiledDelegateType = GetFuncOrAction(lambda);
+ lambda = Expression.Lambda(_compiledDelegateType, lambda.Body, lambda.Name, lambda.Parameters);
+ }
+
+ if (HasClosure) {
+ _compiled = LightLambdaClosureVisitor.BindLambda(lambda, _interpreter.ClosureVariables);
+ } else {
+ _compiled = lambda.Compile();
+ }
+ }
+ }
+
+ private static Type GetFuncOrAction(LambdaExpression lambda) {
+ Type delegateType;
+ bool isVoid = lambda.ReturnType == typeof(void);
+
+ if (isVoid && lambda.Parameters.Count == 2 &&
+ lambda.Parameters[0].IsByRef && lambda.Parameters[1].IsByRef) {
+ return typeof(ActionRef<,>).MakeGenericType(lambda.Parameters.Map(p => p.Type));
+ } else {
+ Type[] types = lambda.Parameters.Map(p => p.IsByRef ? p.Type.MakeByRefType() : p.Type);
+ if (isVoid) {
+ if (Expression.TryGetActionType(types, out delegateType)) {
+ return delegateType;
+ }
+ } else {
+ types = types.AddLast(lambda.ReturnType);
+ if (Expression.TryGetFuncType(types, out delegateType)) {
+ return delegateType;
+ }
+ }
+ return lambda.Type;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.Generated.cs
new file mode 100644
index 00000000000..b3b42a30463
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.Generated.cs
@@ -0,0 +1,724 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ public partial class LightLambda {
+ #region Generated LightLambda Run Methods
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_run_methods from: generate_dynamic_instructions.py
+
+ internal const int MaxParameters = 16;
+ internal TRet Run0<TRet>() {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<TRet>)_compiled)();
+ }
+
+ var frame = MakeFrame();
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid0() {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action)_compiled)();
+ return;
+ }
+
+ var frame = MakeFrame();
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun0<TRet>(LightLambda lambda) {
+ return new Func<TRet>(lambda.Run0<TRet>);
+ }
+ internal static Delegate MakeRunVoid0(LightLambda lambda) {
+ return new Action(lambda.RunVoid0);
+ }
+ internal TRet Run1<T0,TRet>(T0 arg0) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,TRet>)_compiled)(arg0);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid1<T0>(T0 arg0) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0>)_compiled)(arg0);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun1<T0,TRet>(LightLambda lambda) {
+ return new Func<T0,TRet>(lambda.Run1<T0,TRet>);
+ }
+ internal static Delegate MakeRunVoid1<T0>(LightLambda lambda) {
+ return new Action<T0>(lambda.RunVoid1<T0>);
+ }
+ internal TRet Run2<T0,T1,TRet>(T0 arg0,T1 arg1) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,TRet>)_compiled)(arg0, arg1);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid2<T0,T1>(T0 arg0,T1 arg1) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1>)_compiled)(arg0, arg1);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun2<T0,T1,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,TRet>(lambda.Run2<T0,T1,TRet>);
+ }
+ internal static Delegate MakeRunVoid2<T0,T1>(LightLambda lambda) {
+ return new Action<T0,T1>(lambda.RunVoid2<T0,T1>);
+ }
+ internal TRet Run3<T0,T1,T2,TRet>(T0 arg0,T1 arg1,T2 arg2) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,TRet>)_compiled)(arg0, arg1, arg2);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid3<T0,T1,T2>(T0 arg0,T1 arg1,T2 arg2) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2>)_compiled)(arg0, arg1, arg2);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun3<T0,T1,T2,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,TRet>(lambda.Run3<T0,T1,T2,TRet>);
+ }
+ internal static Delegate MakeRunVoid3<T0,T1,T2>(LightLambda lambda) {
+ return new Action<T0,T1,T2>(lambda.RunVoid3<T0,T1,T2>);
+ }
+ internal TRet Run4<T0,T1,T2,T3,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,TRet>)_compiled)(arg0, arg1, arg2, arg3);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid4<T0,T1,T2,T3>(T0 arg0,T1 arg1,T2 arg2,T3 arg3) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3>)_compiled)(arg0, arg1, arg2, arg3);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun4<T0,T1,T2,T3,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,TRet>(lambda.Run4<T0,T1,T2,T3,TRet>);
+ }
+ internal static Delegate MakeRunVoid4<T0,T1,T2,T3>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3>(lambda.RunVoid4<T0,T1,T2,T3>);
+ }
+ internal TRet Run5<T0,T1,T2,T3,T4,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid5<T0,T1,T2,T3,T4>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4>)_compiled)(arg0, arg1, arg2, arg3, arg4);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun5<T0,T1,T2,T3,T4,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,TRet>(lambda.Run5<T0,T1,T2,T3,T4,TRet>);
+ }
+ internal static Delegate MakeRunVoid5<T0,T1,T2,T3,T4>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4>(lambda.RunVoid5<T0,T1,T2,T3,T4>);
+ }
+ internal TRet Run6<T0,T1,T2,T3,T4,T5,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid6<T0,T1,T2,T3,T4,T5>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun6<T0,T1,T2,T3,T4,T5,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,TRet>(lambda.Run6<T0,T1,T2,T3,T4,T5,TRet>);
+ }
+ internal static Delegate MakeRunVoid6<T0,T1,T2,T3,T4,T5>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5>(lambda.RunVoid6<T0,T1,T2,T3,T4,T5>);
+ }
+ internal TRet Run7<T0,T1,T2,T3,T4,T5,T6,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid7<T0,T1,T2,T3,T4,T5,T6>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun7<T0,T1,T2,T3,T4,T5,T6,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,TRet>(lambda.Run7<T0,T1,T2,T3,T4,T5,T6,TRet>);
+ }
+ internal static Delegate MakeRunVoid7<T0,T1,T2,T3,T4,T5,T6>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6>(lambda.RunVoid7<T0,T1,T2,T3,T4,T5,T6>);
+ }
+ internal TRet Run8<T0,T1,T2,T3,T4,T5,T6,T7,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid8<T0,T1,T2,T3,T4,T5,T6,T7>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun8<T0,T1,T2,T3,T4,T5,T6,T7,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,TRet>(lambda.Run8<T0,T1,T2,T3,T4,T5,T6,T7,TRet>);
+ }
+ internal static Delegate MakeRunVoid8<T0,T1,T2,T3,T4,T5,T6,T7>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7>(lambda.RunVoid8<T0,T1,T2,T3,T4,T5,T6,T7>);
+ }
+ internal TRet Run9<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid9<T0,T1,T2,T3,T4,T5,T6,T7,T8>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun9<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>(lambda.Run9<T0,T1,T2,T3,T4,T5,T6,T7,T8,TRet>);
+ }
+ internal static Delegate MakeRunVoid9<T0,T1,T2,T3,T4,T5,T6,T7,T8>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8>(lambda.RunVoid9<T0,T1,T2,T3,T4,T5,T6,T7,T8>);
+ }
+ internal TRet Run10<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid10<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun10<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>(lambda.Run10<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,TRet>);
+ }
+ internal static Delegate MakeRunVoid10<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>(lambda.RunVoid10<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>);
+ }
+ internal TRet Run11<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9,T10 arg10) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid11<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9,T10 arg10) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun11<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>(lambda.Run11<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,TRet>);
+ }
+ internal static Delegate MakeRunVoid11<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>(lambda.RunVoid11<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>);
+ }
+ internal TRet Run12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9,T10 arg10,T11 arg11) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9,T10 arg10,T11 arg11) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>(lambda.Run12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,TRet>);
+ }
+ internal static Delegate MakeRunVoid12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>(lambda.RunVoid12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>);
+ }
+ internal TRet Run13<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9,T10 arg10,T11 arg11,T12 arg12) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ frame.Data[12] = arg12;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid13<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5,T6 arg6,T7 arg7,T8 arg8,T9 arg9,T10 arg10,T11 arg11,T12 arg12) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ frame.Data[12] = arg12;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun13<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>(lambda.Run13<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,TRet>);
+ }
+ internal static Delegate MakeRunVoid13<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>(lambda.RunVoid13<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>);
+ }
+ internal TRet Run14<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>(T0 arg0,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) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ frame.Data[12] = arg12;
+ frame.Data[13] = arg13;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid14<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>(T0 arg0,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) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ frame.Data[12] = arg12;
+ frame.Data[13] = arg13;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun14<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>(lambda.Run14<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,TRet>);
+ }
+ internal static Delegate MakeRunVoid14<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>(lambda.RunVoid14<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>);
+ }
+ internal TRet Run15<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>(T0 arg0,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) {
+ if (_compiled != null || TryGetCompiled()) {
+ return ((Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ frame.Data[12] = arg12;
+ frame.Data[13] = arg13;
+ frame.Data[14] = arg14;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ return (TRet)frame.Pop();
+ }
+
+ internal void RunVoid15<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>(T0 arg0,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) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>)_compiled)(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
+ return;
+ }
+
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ frame.Data[2] = arg2;
+ frame.Data[3] = arg3;
+ frame.Data[4] = arg4;
+ frame.Data[5] = arg5;
+ frame.Data[6] = arg6;
+ frame.Data[7] = arg7;
+ frame.Data[8] = arg8;
+ frame.Data[9] = arg9;
+ frame.Data[10] = arg10;
+ frame.Data[11] = arg11;
+ frame.Data[12] = arg12;
+ frame.Data[13] = arg13;
+ frame.Data[14] = arg14;
+ var current = frame.Enter();
+ try { _interpreter.Run(frame); } finally { frame.Leave(current); }
+ }
+
+ internal static Delegate MakeRun15<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>(LightLambda lambda) {
+ return new Func<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>(lambda.Run15<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,TRet>);
+ }
+ internal static Delegate MakeRunVoid15<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>(LightLambda lambda) {
+ return new Action<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>(lambda.RunVoid15<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>);
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.cs
new file mode 100644
index 00000000000..94982bfa24b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.cs
@@ -0,0 +1,272 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_TASKS
+using System.Threading.Tasks;
+#endif
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Reflection;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading;
+
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+
+ public sealed class LightLambdaCompileEventArgs : EventArgs {
+ public Delegate Compiled { get; private set; }
+
+ internal LightLambdaCompileEventArgs(Delegate compiled) {
+ Compiled = compiled;
+ }
+ }
+
+ public partial class LightLambda {
+ private readonly StrongBox<object>[] _closure;
+ private readonly Interpreter _interpreter;
+ private static readonly CacheDict<Type, Func<LightLambda, Delegate>> _runCache = new CacheDict<Type, Func<LightLambda, Delegate>>(100);
+
+ // Adaptive compilation support
+ private readonly LightDelegateCreator _delegateCreator;
+ private Delegate _compiled;
+ private int _compilationThreshold;
+
+ /// <summary>
+ /// Provides notification that the LightLambda has been compiled.
+ /// </summary>
+ public event EventHandler<LightLambdaCompileEventArgs> Compile;
+
+ internal LightLambda(LightDelegateCreator delegateCreator, StrongBox<object>[] closure, int compilationThreshold) {
+ _delegateCreator = delegateCreator;
+ _closure = closure;
+ _interpreter = delegateCreator.Interpreter;
+ _compilationThreshold = compilationThreshold;
+ }
+
+ private static Func<LightLambda, Delegate> GetRunDelegateCtor(Type delegateType) {
+ lock (_runCache) {
+ Func<LightLambda, Delegate> fastCtor;
+ if (_runCache.TryGetValue(delegateType, out fastCtor)) {
+ return fastCtor;
+ }
+ return MakeRunDelegateCtor(delegateType);
+ }
+ }
+
+ private static Func<LightLambda, Delegate> MakeRunDelegateCtor(Type delegateType) {
+ var method = delegateType.GetMethod("Invoke");
+ var paramInfos = method.GetParameters();
+ Type[] paramTypes;
+ string name = "Run";
+
+ if (paramInfos.Length >= MaxParameters) {
+ return null;
+ }
+
+ if (method.ReturnType == typeof(void)) {
+ name += "Void";
+ paramTypes = new Type[paramInfos.Length];
+ } else {
+ paramTypes = new Type[paramInfos.Length + 1];
+ paramTypes[paramTypes.Length - 1] = method.ReturnType;
+ }
+
+ MethodInfo runMethod;
+
+ if (method.ReturnType == typeof(void) && paramTypes.Length == 2 &&
+ paramInfos[0].ParameterType.IsByRef && paramInfos[1].ParameterType.IsByRef) {
+ runMethod = typeof(LightLambda).GetMethod("RunVoidRef2", BindingFlags.NonPublic | BindingFlags.Instance);
+ paramTypes[0] = paramInfos[0].ParameterType.GetElementType();
+ paramTypes[1] = paramInfos[1].ParameterType.GetElementType();
+ } else if (method.ReturnType == typeof(void) && paramTypes.Length == 0) {
+ runMethod = typeof(LightLambda).GetMethod("RunVoid0", BindingFlags.NonPublic | BindingFlags.Instance);
+ } else {
+ for (int i = 0; i < paramInfos.Length; i++) {
+ paramTypes[i] = paramInfos[i].ParameterType;
+ if (paramTypes[i].IsByRef) {
+ return null;
+ }
+ }
+
+ if (DelegateHelpers.MakeDelegate(paramTypes) == delegateType) {
+ name = "Make" + name + paramInfos.Length;
+
+ MethodInfo ctorMethod = typeof(LightLambda).GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(paramTypes);
+ return _runCache[delegateType] = (Func<LightLambda, Delegate>)ctorMethod.CreateDelegate(typeof(Func<LightLambda, Delegate>));
+ }
+
+ runMethod = typeof(LightLambda).GetMethod(name + paramInfos.Length, BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+
+#if FEATURE_LCG && !SILVERLIGHT && !WP75
+ try {
+ DynamicMethod dm = new DynamicMethod("FastCtor", typeof(Delegate), new[] { typeof(LightLambda) }, typeof(LightLambda), true);
+ var ilgen = dm.GetILGenerator();
+ ilgen.Emit(OpCodes.Ldarg_0);
+ ilgen.Emit(OpCodes.Ldftn, runMethod.IsGenericMethodDefinition ? runMethod.MakeGenericMethod(paramTypes) : runMethod);
+ ilgen.Emit(OpCodes.Newobj, delegateType.GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
+ ilgen.Emit(OpCodes.Ret);
+ return _runCache[delegateType] = (Func<LightLambda, Delegate>)dm.CreateDelegate(typeof(Func<LightLambda, Delegate>));
+ } catch (SecurityException) {
+ }
+#endif
+
+ // we don't have permission for restricted skip visibility dynamic methods, use the slower Delegate.CreateDelegate.
+ var targetMethod = runMethod.IsGenericMethodDefinition ? runMethod.MakeGenericMethod(paramTypes) : runMethod;
+ return _runCache[delegateType] = lambda => targetMethod.CreateDelegate(delegateType, lambda);
+ }
+
+ //TODO enable sharing of these custom delegates
+ private Delegate CreateCustomDelegate(Type delegateType) {
+ PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Synchronously compiling a custom delegate");
+
+ var method = delegateType.GetMethod("Invoke");
+ var paramInfos = method.GetParameters();
+ var parameters = new ParameterExpression[paramInfos.Length];
+ var parametersAsObject = new Expression[paramInfos.Length];
+ for (int i = 0; i < paramInfos.Length; i++) {
+ ParameterExpression parameter = Expression.Parameter(paramInfos[i].ParameterType, paramInfos[i].Name);
+ parameters[i] = parameter;
+ parametersAsObject[i] = Expression.Convert(parameter, typeof(object));
+ }
+
+ var data = Expression.NewArrayInit(typeof(object), parametersAsObject);
+ var self = AstUtils.Constant(this);
+ var runMethod = typeof(LightLambda).GetMethod("Run");
+ var body = Expression.Convert(Expression.Call(self, runMethod, data), method.ReturnType);
+ var lambda = Expression.Lambda(delegateType, body, parameters);
+ return lambda.Compile();
+ }
+
+ internal Delegate MakeDelegate(Type delegateType) {
+ Func<LightLambda, Delegate> fastCtor = GetRunDelegateCtor(delegateType);
+ if (fastCtor != null) {
+ return fastCtor(this);
+ } else {
+ return CreateCustomDelegate(delegateType);
+ }
+ }
+
+ private bool TryGetCompiled() {
+ // Use the compiled delegate if available.
+ if (_delegateCreator.HasCompiled) {
+ _compiled = _delegateCreator.CreateCompiledDelegate(_closure);
+
+ // Send it to anyone who's interested.
+ var compileEvent = Compile;
+ if (compileEvent != null && _delegateCreator.SameDelegateType) {
+ compileEvent(this, new LightLambdaCompileEventArgs(_compiled));
+ }
+
+ return true;
+ }
+
+ // Don't lock here, it's a frequently hit path.
+ //
+ // There could be multiple threads racing, but that is okay.
+ // Two bad things can happen:
+ // * We miss decrements (some thread sets the counter forward)
+ // * We might enter the "if" branch more than once.
+ //
+ // The first is okay, it just means we take longer to compile.
+ // The second we explicitly guard against inside of Compile().
+ //
+ // We can't miss 0. The first thread that writes -1 must have read 0 and hence start compilation.
+ if (unchecked(_compilationThreshold--) == 0) {
+#if SILVERLIGHT
+ if (PlatformAdaptationLayer.IsCompactFramework) {
+ _compilationThreshold = Int32.MaxValue;
+ return false;
+ }
+#endif
+ if (_interpreter.CompileSynchronously) {
+ _delegateCreator.Compile(null);
+ return TryGetCompiled();
+ } else {
+ // Kick off the compile on another thread so this one can keep going
+#if FEATURE_TASKS
+ new Task(_delegateCreator.Compile, null).Start();
+#else
+ ThreadPool.QueueUserWorkItem(_delegateCreator.Compile, null);
+#endif
+ }
+ }
+
+ return false;
+ }
+
+ private InterpretedFrame MakeFrame() {
+ return new InterpretedFrame(_interpreter, _closure);
+ }
+
+ internal void RunVoidRef2<T0, T1>(ref T0 arg0, ref T1 arg1) {
+ if (_compiled != null || TryGetCompiled()) {
+ ((ActionRef<T0, T1>)_compiled)(ref arg0, ref arg1);
+ return;
+ }
+
+ // copy in and copy out for today...
+ var frame = MakeFrame();
+ frame.Data[0] = arg0;
+ frame.Data[1] = arg1;
+ var currentFrame = frame.Enter();
+ try {
+ _interpreter.Run(frame);
+ } finally {
+ frame.Leave(currentFrame);
+ arg0 = (T0)frame.Data[0];
+ arg1 = (T1)frame.Data[1];
+ }
+ }
+
+
+ public object Run(params object[] arguments) {
+ if (_compiled != null || TryGetCompiled()) {
+ try {
+ return _compiled.DynamicInvoke(arguments);
+ } catch (TargetInvocationException e) {
+ throw ExceptionHelpers.UpdateForRethrow(e.InnerException);
+ }
+ }
+
+ var frame = MakeFrame();
+ for (int i = 0; i < arguments.Length; i++) {
+ frame.Data[i] = arguments[i];
+ }
+ var currentFrame = frame.Enter();
+ try {
+ _interpreter.Run(frame);
+ } finally {
+ frame.Leave(currentFrame);
+ }
+ return frame.Pop();
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambdaClosureVisitor.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambdaClosureVisitor.cs
new file mode 100644
index 00000000000..e779e414855
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambdaClosureVisitor.cs
@@ -0,0 +1,260 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Utils;
+using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+
+ /// <summary>
+ /// Visits a LambdaExpression, replacing the constants with direct accesses
+ /// to their StrongBox fields. This is very similar to what
+ /// ExpressionQuoter does for LambdaCompiler.
+ ///
+ /// Also inserts debug information tracking similar to what the interpreter
+ /// would do.
+ /// </summary>
+ internal sealed class LightLambdaClosureVisitor : ExpressionVisitor {
+ /// <summary>
+ /// Local variable mapping.
+ /// </summary>
+ private readonly Dictionary<ParameterExpression, LocalVariable> _closureVars;
+
+ /// <summary>
+ /// The variable that holds onto the StrongBox{object}[] closure from
+ /// the interpreter
+ /// </summary>
+ private readonly ParameterExpression _closureArray;
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ private readonly Stack<HashSet<ParameterExpression>> _shadowedVars = new Stack<HashSet<ParameterExpression>>();
+
+ private LightLambdaClosureVisitor(Dictionary<ParameterExpression, LocalVariable> closureVariables, ParameterExpression closureArray) {
+ Assert.NotNull(closureVariables, closureArray);
+ _closureArray = closureArray;
+ _closureVars = closureVariables;
+ }
+
+ /// <summary>
+ /// Walks the lambda and produces a higher order function, which can be
+ /// used to bind the lambda to a closure array from the interpreter.
+ /// </summary>
+ /// <param name="lambda">The lambda to bind.</param>
+ /// <param name="closureVariables">Variables which are being accessed defined in the outer scope.</param>
+ /// <returns>A delegate that can be called to produce a delegate bound to the passed in closure array.</returns>
+ internal static Func<StrongBox<object>[], Delegate> BindLambda(LambdaExpression lambda, Dictionary<ParameterExpression, LocalVariable> closureVariables) {
+ // 1. Create rewriter
+ var closure = Expression.Parameter(typeof(StrongBox<object>[]), "closure");
+ var visitor = new LightLambdaClosureVisitor(closureVariables, closure);
+
+ // 2. Visit the lambda
+ lambda = (LambdaExpression)visitor.Visit(lambda);
+
+ // 3. Create a higher-order function which fills in the parameters
+ var result = Expression.Lambda<Func<StrongBox<object>[], Delegate>>(lambda, closure);
+
+ // 4. Compile it
+ return result.Compile();
+ }
+
+ #region closures
+
+ protected override Expression VisitLambda<T>(Expression<T> node) {
+ _shadowedVars.Push(new HashSet<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 override Expression VisitBlock(BlockExpression node) {
+ if (node.Variables.Count > 0) {
+ _shadowedVars.Push(new HashSet<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 HashSet<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 override Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
+ int count = node.Variables.Count;
+ var boxes = new List<Expression>();
+ var vars = new List<ParameterExpression>();
+ var indexes = new int[count];
+ for (int i = 0; i < count; i++) {
+ Expression box = GetClosureItem(node.Variables[i], false);
+ 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 boxesArray = Expression.NewArrayInit(typeof(IStrongBox), boxes);
+
+ // All of them were rewritten. Just return the array, wrapped in a
+ // read-only collection.
+ if (vars.Count == 0) {
+ return Expression.Invoke(
+ Expression.Constant((Func<IStrongBox[], IRuntimeVariables>)RuntimeVariables.Create),
+ boxesArray
+ );
+ }
+
+ // Otherwise, we need to return an object that merges them
+ Func<IRuntimeVariables, IRuntimeVariables, int[], IRuntimeVariables> helper = MergedRuntimeVariables.Create;
+ return Expression.Invoke(AstUtils.Constant(helper), Expression.RuntimeVariables(vars), boxesArray, AstUtils.Constant(indexes));
+ }
+
+ protected override Expression VisitParameter(ParameterExpression node) {
+ Expression closureItem = GetClosureItem(node, true);
+ if (closureItem == null) {
+ return node;
+ }
+ // Convert can go away if we switch to strongly typed StrongBox
+ return Ast.Utils.Convert(closureItem, node.Type);
+ }
+
+ protected override Expression VisitBinary(BinaryExpression node) {
+ if (node.NodeType == ExpressionType.Assign &&
+ node.Left.NodeType == ExpressionType.Parameter) {
+
+ var variable = (ParameterExpression)node.Left;
+ Expression closureItem = GetClosureItem(variable, true);
+ if (closureItem != null) {
+ // We need to convert to object to store the value in the box.
+ return Expression.Block(
+ new[] { variable },
+ Expression.Assign(variable, Visit(node.Right)),
+ Expression.Assign(closureItem, Ast.Utils.Convert(variable, typeof(object))),
+ variable
+ );
+ }
+ }
+ return base.VisitBinary(node);
+ }
+
+ private Expression GetClosureItem(ParameterExpression variable, bool unbox) {
+ // Skip variables that are shadowed by a nested scope/lambda
+ foreach (HashSet<ParameterExpression> hidden in _shadowedVars) {
+ if (hidden.Contains(variable)) {
+ return null;
+ }
+ }
+
+ LocalVariable loc;
+ if (!_closureVars.TryGetValue(variable, out loc)) {
+ throw new InvalidOperationException("unbound variable: " + variable.Name);
+ }
+
+ var result = loc.LoadFromArray(null, _closureArray);
+ return (unbox) ? LightCompiler.Unbox(result) : result;
+ }
+
+ protected override Expression VisitExtension(Expression node) {
+ // Reduce extensions now so we can find embedded variables
+ return Visit(node.ReduceExtensions());
+ }
+
+
+ #region MergedRuntimeVariables
+
+ /// <summary>
+ /// Provides a list of variables, supporing read/write of the values
+ /// </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;
+
+ private MergedRuntimeVariables(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) {
+ _first = first;
+ _second = second;
+ _indexes = indexes;
+ }
+
+ internal static IRuntimeVariables Create(IRuntimeVariables first, IRuntimeVariables second, int[] indexes) {
+ return new MergedRuntimeVariables(first, second, indexes);
+ }
+
+ int IRuntimeVariables.Count {
+ get { return _indexes.Length; }
+ }
+
+ object IRuntimeVariables.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;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LocalVariables.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LocalVariables.cs
new file mode 100644
index 00000000000..d848a643002
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LocalVariables.cs
@@ -0,0 +1,266 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ public sealed class LocalVariable {
+ private const int IsBoxedFlag = 1;
+ private const int InClosureFlag = 2;
+
+ public readonly int Index;
+ private int _flags;
+
+ public bool IsBoxed {
+ get { return (_flags & IsBoxedFlag) != 0; }
+ set {
+ if (value) {
+ _flags |= IsBoxedFlag;
+ } else {
+ _flags &= ~IsBoxedFlag;
+ }
+ }
+ }
+
+ public bool InClosure {
+ get { return (_flags & InClosureFlag) != 0; }
+ }
+
+ public bool InClosureOrBoxed {
+ get { return InClosure | IsBoxed; }
+ }
+
+ internal LocalVariable(int index, bool closure, bool boxed) {
+ Index = index;
+ _flags = (closure ? InClosureFlag : 0) | (boxed ? IsBoxedFlag : 0);
+ }
+
+ internal Expression LoadFromArray(Expression frameData, Expression closure) {
+ Expression result = Expression.ArrayAccess(InClosure ? closure : frameData, Expression.Constant(Index));
+ return IsBoxed ? Expression.Convert(result, typeof(StrongBox<object>)) : result;
+ }
+
+ public override string ToString() {
+ return String.Format("{0}: {1} {2}", Index, IsBoxed ? "boxed" : null, InClosure ? "in closure" : null);
+ }
+ }
+
+ public struct LocalDefinition {
+ private readonly int _index;
+ private readonly ParameterExpression _parameter;
+
+ internal LocalDefinition(int localIndex, ParameterExpression parameter) {
+ _index = localIndex;
+ _parameter = parameter;
+ }
+
+ public int Index {
+ get {
+ return _index;
+ }
+ }
+
+ public ParameterExpression Parameter {
+ get {
+ return _parameter;
+ }
+ }
+
+ public override bool Equals(object obj) {
+ if (obj is LocalDefinition) {
+ LocalDefinition other = (LocalDefinition)obj;
+ return other.Index == Index && other.Parameter == Parameter;
+ }
+
+ return false;
+ }
+
+ public override int GetHashCode() {
+ if (_parameter == null) {
+ return 0;
+ }
+ return _parameter.GetHashCode() ^ _index.GetHashCode();
+ }
+
+ public static bool operator ==(LocalDefinition self, LocalDefinition other) {
+ return self.Index == other.Index && self.Parameter == other.Parameter;
+ }
+
+ public static bool operator !=(LocalDefinition self, LocalDefinition other) {
+ return self.Index != other.Index || self.Parameter != other.Parameter;
+ }
+ }
+
+ public sealed class LocalVariables {
+ private readonly HybridReferenceDictionary<ParameterExpression, VariableScope> _variables = new HybridReferenceDictionary<ParameterExpression, VariableScope>();
+ private Dictionary<ParameterExpression, LocalVariable> _closureVariables;
+
+ private int _localCount, _maxLocalCount;
+
+ internal LocalVariables() {
+ }
+
+ public LocalDefinition DefineLocal(ParameterExpression variable, int start) {
+ ContractUtils.RequiresNotNull(variable, "variable");
+ ContractUtils.Requires(start >= 0, "start", "start must be positive");
+
+ LocalVariable result = new LocalVariable(_localCount++, false, false);
+ _maxLocalCount = System.Math.Max(_localCount, _maxLocalCount);
+
+ VariableScope existing, newScope;
+ if (_variables.TryGetValue(variable, out existing)) {
+ newScope = new VariableScope(result, start, existing);
+ if (existing.ChildScopes == null) {
+ existing.ChildScopes = new List<VariableScope>();
+ }
+ existing.ChildScopes.Add(newScope);
+ } else {
+ newScope = new VariableScope(result, start, null);
+ }
+
+ _variables[variable] = newScope;
+ return new LocalDefinition(result.Index, variable);
+ }
+
+ public void UndefineLocal(LocalDefinition definition, int end) {
+ var scope = _variables[definition.Parameter];
+ scope.Stop = end;
+ if (scope.Parent != null) {
+ _variables[definition.Parameter] = scope.Parent;
+ } else {
+ _variables.Remove(definition.Parameter);
+ }
+
+ _localCount--;
+ }
+
+ internal void Box(ParameterExpression variable, InstructionList instructions) {
+ var scope = _variables[variable];
+
+ LocalVariable local = scope.Variable;
+ Debug.Assert(!local.IsBoxed && !local.InClosure);
+ _variables[variable].Variable.IsBoxed = true;
+
+ int curChild = 0;
+ for (int i = scope.Start; i < scope.Stop && i < instructions.Count; i++) {
+ if (scope.ChildScopes != null && scope.ChildScopes[curChild].Start == i) {
+ // skip boxing in the child scope
+ var child = scope.ChildScopes[curChild];
+ i = child.Stop;
+
+ curChild++;
+ continue;
+ }
+
+ instructions.SwitchToBoxed(local.Index, i);
+ }
+ }
+
+ public int LocalCount {
+ get { return _maxLocalCount; }
+ }
+
+ public int GetOrDefineLocal(ParameterExpression var) {
+ int index = GetLocalIndex(var);
+ if (index == -1) {
+ return DefineLocal(var, 0).Index;
+ }
+ return index;
+ }
+
+ public int GetLocalIndex(ParameterExpression var) {
+ VariableScope loc;
+ return _variables.TryGetValue(var, out loc) ? loc.Variable.Index : -1;
+ }
+
+ public bool TryGetLocalOrClosure(ParameterExpression var, out LocalVariable local) {
+ VariableScope scope;
+ if (_variables.TryGetValue(var, out scope)) {
+ local = scope.Variable;
+ return true;
+ }
+ if (_closureVariables != null && _closureVariables.TryGetValue(var, out local)) {
+ return true;
+ }
+
+ local = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a copy of the local variables which are defined in the current scope.
+ /// </summary>
+ /// <returns></returns>
+ internal Dictionary<ParameterExpression, LocalVariable> CopyLocals() {
+ var res = new Dictionary<ParameterExpression, LocalVariable>(_variables.Count);
+ foreach (var keyValue in _variables) {
+ res[keyValue.Key] = keyValue.Value.Variable;
+ }
+ return res;
+ }
+
+ /// <summary>
+ /// Checks to see if the given variable is defined within the current local scope.
+ /// </summary>
+ internal bool ContainsVariable(ParameterExpression variable) {
+ return _variables.ContainsKey(variable);
+ }
+
+ /// <summary>
+ /// Gets the variables which are defined in an outer scope and available within the current scope.
+ /// </summary>
+ internal Dictionary<ParameterExpression, LocalVariable> ClosureVariables {
+ get {
+ return _closureVariables;
+ }
+ }
+
+ internal LocalVariable AddClosureVariable(ParameterExpression variable) {
+ if (_closureVariables == null) {
+ _closureVariables = new Dictionary<ParameterExpression, LocalVariable>();
+ }
+ LocalVariable result = new LocalVariable(_closureVariables.Count, true, false);
+ _closureVariables.Add(variable, result);
+ return result;
+ }
+
+ /// <summary>
+ /// Tracks where a variable is defined and what range of instructions it's used in
+ /// </summary>
+ private sealed class VariableScope {
+ public readonly int Start;
+ public int Stop = Int32.MaxValue;
+ public readonly LocalVariable Variable;
+ public readonly VariableScope Parent;
+ public List<VariableScope> ChildScopes;
+
+ public VariableScope(LocalVariable variable, int start, VariableScope parent) {
+ Variable = variable;
+ Start = start;
+ Parent = parent;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LoopCompiler.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LoopCompiler.cs
new file mode 100644
index 00000000000..acc416ea5e5
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LoopCompiler.cs
@@ -0,0 +1,323 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Ast;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Interpreter {
+ using AstUtils = Microsoft.Scripting.Ast.Utils;
+ using LoopFunc = Func<object[], StrongBox<object>[], InterpretedFrame, int>;
+ using System.Collections.ObjectModel;
+
+ internal sealed class LoopCompiler : ExpressionVisitor {
+ private struct LoopVariable {
+ public ExpressionAccess Access;
+
+ // a variable that holds on the strong box for closure variables:
+ public ParameterExpression BoxStorage;
+
+ public LoopVariable(ExpressionAccess access, ParameterExpression box) {
+ Access = access;
+ BoxStorage = box;
+ }
+
+ public override string ToString() {
+ return Access.ToString() + " " + BoxStorage;
+ }
+ }
+
+ private readonly ParameterExpression _frameDataVar;
+ private readonly ParameterExpression _frameClosureVar;
+ private readonly ParameterExpression _frameVar;
+ private readonly LabelTarget _returnLabel;
+ // locals and closure variables defined outside the loop
+ private readonly Dictionary<ParameterExpression, LocalVariable> _outerVariables, _closureVariables;
+ private readonly LoopExpression _loop;
+ private ReadOnlyCollectionBuilder<ParameterExpression> _temps;
+ // tracks variables that flow in and flow out for initialization and
+ private readonly Dictionary<ParameterExpression, LoopVariable> _loopVariables;
+ // variables which are defined and used within the loop
+ private HashSet<ParameterExpression> _loopLocals;
+
+ private readonly HybridReferenceDictionary<LabelTarget, BranchLabel> _labelMapping;
+ private readonly int _loopStartInstructionIndex;
+ private readonly int _loopEndInstructionIndex;
+
+ internal LoopCompiler(LoopExpression loop, HybridReferenceDictionary<LabelTarget, BranchLabel> labelMapping, Dictionary<ParameterExpression, LocalVariable> locals,
+ Dictionary<ParameterExpression, LocalVariable> closureVariables, int loopStartInstructionIndex, int loopEndInstructionIndex) {
+ _loop = loop;
+ _outerVariables = locals;
+ _closureVariables = closureVariables;
+ _frameDataVar = Expression.Parameter(typeof(object[]));
+ _frameClosureVar = Expression.Parameter(typeof(StrongBox<object>[]));
+ _frameVar = Expression.Parameter(typeof(InterpretedFrame));
+ _loopVariables = new Dictionary<ParameterExpression, LoopVariable>();
+ _returnLabel = Expression.Label(typeof(int));
+ _labelMapping = labelMapping;
+ _loopStartInstructionIndex = loopStartInstructionIndex;
+ _loopEndInstructionIndex = loopEndInstructionIndex;
+ }
+
+ internal LoopFunc CreateDelegate() {
+ var loop = (LoopExpression)Visit(_loop);
+ var body = new ReadOnlyCollectionBuilder<Expression>();
+ var finallyClause = new ReadOnlyCollectionBuilder<Expression>();
+
+ foreach (var variable in _loopVariables) {
+ LocalVariable local;
+ if (!_outerVariables.TryGetValue(variable.Key, out local)) {
+ local = _closureVariables[variable.Key];
+ }
+ Expression elemRef = local.LoadFromArray(_frameDataVar, _frameClosureVar);
+
+ if (local.InClosureOrBoxed) {
+ var box = variable.Value.BoxStorage;
+ Debug.Assert(box != null);
+ body.Add(Expression.Assign(box, elemRef));
+ AddTemp(box);
+ } else {
+ // Always initialize the variable even if it is only written to.
+ // If a write-only variable is actually not assigned during execution of the loop we will still write some value back.
+ // This value must be the original value, which we assign at entry.
+ body.Add(Expression.Assign(variable.Key, AstUtils.Convert(elemRef, variable.Key.Type)));
+
+ if ((variable.Value.Access & ExpressionAccess.Write) != 0) {
+ finallyClause.Add(Expression.Assign(elemRef, AstUtils.Box(variable.Key)));
+ }
+
+ AddTemp(variable.Key);
+ }
+ }
+
+ if (finallyClause.Count > 0) {
+ body.Add(Expression.TryFinally(loop, Expression.Block(finallyClause)));
+ } else {
+ body.Add(loop);
+ }
+
+ body.Add(Expression.Label(_returnLabel, Expression.Constant(_loopEndInstructionIndex - _loopStartInstructionIndex)));
+
+ var lambda = Expression.Lambda<LoopFunc>(
+ _temps != null ? Expression.Block(_temps.ToReadOnlyCollection(), body) : Expression.Block(body),
+ new[] { _frameDataVar, _frameClosureVar, _frameVar }
+ );
+ return lambda.Compile();
+ }
+
+ protected override Expression VisitExtension(Expression node) {
+ // Reduce extensions before we visit them so that we operate on a plain DLR tree,
+ // where we know relationships among the nodes (which nodes represent write context etc.).
+ if (node.CanReduce) {
+ return Visit(node.Reduce());
+ }
+
+ return base.VisitExtension(node);
+ }
+
+ #region Gotos
+
+ protected override Expression VisitGoto(GotoExpression node) {
+ BranchLabel label;
+
+ var target = node.Target;
+ var value = Visit(node.Value);
+
+ // TODO: Is it possible for an inner reducible node of the loop to rely on nodes produced by reducing outer reducible nodes?
+
+ // Unknown label => must be within the loop:
+ if (!_labelMapping.TryGetValue(target, out label)) {
+ return node.Update(target, value);
+ }
+
+ // Known label within the loop:
+ if (label.TargetIndex >= _loopStartInstructionIndex && label.TargetIndex < _loopEndInstructionIndex) {
+ return node.Update(target, value);
+ }
+
+ return Expression.Return(_returnLabel,
+ (value != null) ?
+ Expression.Call(_frameVar, InterpretedFrame.GotoMethod, Expression.Constant(label.LabelIndex), AstUtils.Box(value)) :
+ Expression.Call(_frameVar, InterpretedFrame.VoidGotoMethod, Expression.Constant(label.LabelIndex)),
+ node.Type
+ );
+ }
+
+ #endregion
+
+ #region Local Variables
+
+ // Gather all outer variables accessed in the loop.
+ // Determines which ones are read from and written to.
+ // We will consider a variable as "read" if it is read anywhere in the loop even though
+ // the first operation might actually always be "write". We could do better if we had CFG.
+
+ protected override Expression VisitBlock(BlockExpression node) {
+ var variables = ((BlockExpression)node).Variables;
+ var prevLocals = EnterVariableScope(variables);
+
+ var res = base.VisitBlock(node);
+
+ ExitVariableScope(prevLocals);
+ return res;
+ }
+
+ private HashSet<ParameterExpression> EnterVariableScope(ICollection<ParameterExpression> variables) {
+ if (_loopLocals == null) {
+ _loopLocals = new HashSet<ParameterExpression>(variables);
+ return null;
+ }
+
+ var prevLocals = new HashSet<ParameterExpression>(_loopLocals);
+ _loopLocals.UnionWith(variables);
+ return prevLocals;
+ }
+
+ protected override CatchBlock VisitCatchBlock(CatchBlock node) {
+ if (node.Variable != null) {
+ var prevLocals = EnterVariableScope(new[] { node.Variable });
+ var res = base.VisitCatchBlock(node);
+ ExitVariableScope(prevLocals);
+ return res;
+ } else {
+ return base.VisitCatchBlock(node);
+ }
+ }
+
+ protected override Expression VisitLambda<T>(Expression<T> node) {
+ var prevLocals = EnterVariableScope(node.Parameters);
+ try {
+ return base.VisitLambda<T>(node);
+ } finally {
+ ExitVariableScope(prevLocals);
+ }
+ }
+
+ private void ExitVariableScope(HashSet<ParameterExpression> prevLocals) {
+ _loopLocals = prevLocals;
+ }
+
+ protected override Expression VisitBinary(BinaryExpression node) {
+ // reduce compound assignments:
+ if (node.CanReduce) {
+ return Visit(node.Reduce());
+ }
+ Debug.Assert(!node.NodeType.IsReadWriteAssignment());
+
+ var param = node.Left as ParameterExpression;
+ if (param != null && node.NodeType == ExpressionType.Assign) {
+ var left = VisitVariable(param, ExpressionAccess.Write);
+ var right = Visit(node.Right);
+
+ // left parameter is a boxed variable:
+ if (left.Type != param.Type) {
+ Debug.Assert(left.Type == typeof(object));
+
+ Expression rightVar;
+ if (right.NodeType != ExpressionType.Parameter) {
+ // { left.Value = (object)(rightVar = right), rightVar }
+ rightVar = AddTemp(Expression.Parameter(right.Type));
+ right = Expression.Assign(rightVar, right);
+ } else {
+ // { left.Value = (object)right, right }
+ rightVar = right;
+ }
+
+ return Expression.Block(
+ node.Update(left, Expression.Convert(right, left.Type)),
+ rightVar
+ );
+ } else {
+ return node.Update(left, right);
+ }
+
+ } else {
+ return base.VisitBinary(node);
+ }
+ }
+
+ protected override Expression VisitUnary(UnaryExpression node) {
+ // reduce inplace increment/decrement:
+ if (node.CanReduce) {
+ return Visit(node.Reduce());
+ }
+ Debug.Assert(!node.NodeType.IsReadWriteAssignment());
+ return base.VisitUnary(node);
+ }
+
+ // TODO: if we supported ref/out parameter we would need to override
+ // MethodCallExpression, VisitDynamic and VisitNew
+
+ protected override Expression VisitParameter(ParameterExpression node) {
+ return VisitVariable(node, ExpressionAccess.Read);
+ }
+
+ private Expression VisitVariable(ParameterExpression node, ExpressionAccess access) {
+ ParameterExpression box;
+ LoopVariable existing;
+ LocalVariable loc;
+
+ if (_loopLocals.Contains(node)) {
+ // local to the loop - not propagated in or out
+ return node;
+ } else if (_loopVariables.TryGetValue(node, out existing)) {
+ // existing outer variable that we are already tracking
+ box = existing.BoxStorage;
+ _loopVariables[node] = new LoopVariable(existing.Access | access, box);
+ } else if (_outerVariables.TryGetValue(node, out loc) ||
+ (_closureVariables != null && _closureVariables.TryGetValue(node, out loc))) {
+ // not tracking this variable yet, but defined in outer scope and seen for the 1st time
+ box = loc.InClosureOrBoxed ? Expression.Parameter(typeof(StrongBox<object>), node.Name) : null;
+ _loopVariables[node] = new LoopVariable(access, box);
+ } else {
+ // node is a variable defined in a nested lambda -> skip
+ return node;
+ }
+
+ if (box != null) {
+ if ((access & ExpressionAccess.Write) != 0) {
+ // compound assignments were reduced:
+ Debug.Assert((access & ExpressionAccess.Read) == 0);
+
+ // box.Value = (object)rhs
+ return LightCompiler.Unbox(box);
+ } else {
+ // (T)box.Value
+ return Expression.Convert(LightCompiler.Unbox(box), node.Type);
+ }
+ }
+
+ return node;
+ }
+
+ private ParameterExpression AddTemp(ParameterExpression variable) {
+ if (_temps == null) {
+ _temps = new ReadOnlyCollectionBuilder<ParameterExpression>();
+ }
+
+ _temps.Add(variable);
+ return variable;
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/RuntimeVariables.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/RuntimeVariables.cs
new file mode 100644
index 00000000000..e8b8e98520c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/RuntimeVariables.cs
@@ -0,0 +1,46 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Microsoft.Scripting.Interpreter {
+ internal sealed class RuntimeVariables : IRuntimeVariables {
+ private readonly IStrongBox[] _boxes;
+
+ private 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;
+ }
+ }
+
+ internal static IRuntimeVariables Create(IStrongBox[] boxes) {
+ return new RuntimeVariables(boxes);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/BigIntegerV4.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/BigIntegerV4.cs
new file mode 100644
index 00000000000..303eb7521b6
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/BigIntegerV4.cs
@@ -0,0 +1,614 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+#if FEATURE_NUMERICS
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Text;
+using Microsoft.Scripting.Utils;
+using BigInt = System.Numerics.BigInteger;
+
+namespace Microsoft.Scripting.Math {
+ /// <summary>
+ /// arbitrary precision integers
+ /// </summary>
+ [Serializable]
+ public sealed class BigInteger : IFormattable, IComparable, IEquatable<BigInteger> {
+ internal readonly BigInt Value;
+
+ [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly BigInteger Zero = new BigInteger((BigInt)0);
+ [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly BigInteger One = new BigInteger((BigInt)1);
+
+ public BigInteger(BigInt value) {
+ Value = value;
+ }
+
+ [CLSCompliant(false)]
+ public static BigInteger Create(ulong v) {
+ return new BigInteger(new BigInt(v));
+ }
+
+ [CLSCompliant(false)]
+ public static BigInteger Create(uint v) {
+ return new BigInteger(new BigInt(v));
+ }
+
+ public static BigInteger Create(long v) {
+ return new BigInteger(new BigInt(v));
+ }
+
+ public static BigInteger Create(int v) {
+ return new BigInteger(new BigInt(v));
+ }
+
+ public static BigInteger Create(decimal v) {
+ return new BigInteger(new BigInt(v));
+ }
+
+ public static BigInteger Create(byte[] v) {
+ return new BigInteger(v);
+ }
+
+ public static BigInteger Create(double v) {
+ return new BigInteger(new BigInt(v));
+ }
+
+ public static implicit operator BigInteger(byte i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator BigInteger(sbyte i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ public static implicit operator BigInteger(short i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator BigInteger(ushort i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator BigInteger(uint i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ public static implicit operator BigInteger(int i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator BigInteger(ulong i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ public static implicit operator BigInteger(long i) {
+ return new BigInteger((BigInt)i);
+ }
+
+ public static implicit operator BigInteger(decimal self) {
+ return new BigInteger((BigInt)self);
+ }
+
+ public static explicit operator BigInteger(double self) {
+ return new BigInteger((BigInt)self);
+ }
+
+ public static explicit operator BigInteger(float self) {
+ return new BigInteger((BigInt)self);
+ }
+
+ public static explicit operator double(BigInteger self) {
+ return (double)self.Value;
+ }
+
+ public static explicit operator float(BigInteger self) {
+ return (float)self.Value;
+ }
+
+ public static explicit operator decimal(BigInteger self) {
+ return (decimal)self.Value;
+ }
+
+ public static explicit operator byte(BigInteger self) {
+ return (byte)self.Value;
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator sbyte(BigInteger self) {
+ return (sbyte)self.Value;
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator UInt16(BigInteger self) {
+ return (UInt16)self.Value;
+ }
+
+ public static explicit operator Int16(BigInteger self) {
+ return (Int16)self.Value;
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator UInt32(BigInteger self) {
+ return (UInt32)self.Value;
+ }
+
+ public static explicit operator Int32(BigInteger self) {
+ return (Int32)self.Value;
+ }
+
+ public static explicit operator Int64(BigInteger self) {
+ return (Int64)self.Value;
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator UInt64(BigInteger self) {
+ return (UInt64)self.Value;
+ }
+
+ public static implicit operator BigInteger(BigInt value) {
+ return new BigInteger(value);
+ }
+
+ public static implicit operator BigInt(BigInteger value) {
+ return value.Value;
+ }
+
+ public BigInteger(BigInteger copy) {
+ if (object.ReferenceEquals(copy, null)) {
+ throw new ArgumentNullException("copy");
+ }
+ Value = copy.Value;
+ }
+
+ public BigInteger(byte[] data) {
+ ContractUtils.RequiresNotNull(data, "data");
+
+ Value = new BigInt(data);
+ }
+
+ public BigInteger(int sign, byte[] data) {
+ ContractUtils.RequiresNotNull(data, "data");
+ ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
+
+ Value = new BigInt(data);
+ if (sign < 0) {
+ Value = -Value;
+ }
+ }
+
+ [CLSCompliant(false)]
+ public BigInteger(int sign, uint[] data) {
+ ContractUtils.RequiresNotNull(data, "data");
+ ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
+ int length = GetLength(data);
+ ContractUtils.Requires(length == 0 || sign != 0, "sign");
+ if (length == 0) {
+ Value = 0;
+ return;
+ }
+
+ bool highest = (data[length - 1] & 0x80000000) != 0;
+ byte[] bytes = new byte[length * 4 + (highest ? 1 : 0)];
+ int j = 0;
+ for (int i = 0; i < length; i++) {
+ ulong w = data[i];
+ bytes[j++] = (byte)(w & 0xff);
+ bytes[j++] = (byte)((w >> 8) & 0xff);
+ bytes[j++] = (byte)((w >> 16) & 0xff);
+ bytes[j++] = (byte)((w >> 24) & 0xff);
+ }
+
+ Value = new BigInt(bytes);
+ if (sign < 0) {
+ Value = -Value;
+ }
+ }
+
+ [CLSCompliant(false)]
+ public uint[] GetWords() {
+ return Value.GetWords();
+ }
+
+ public int GetBitCount() {
+ return Value.GetBitCount();
+ }
+
+ public int GetWordCount() {
+ return Value.GetWordCount();
+ }
+
+ public int GetByteCount() {
+ return Value.GetByteCount();
+ }
+
+ /// <summary>
+ /// Return the sign of this BigInteger: -1, 0, or 1.
+ /// </summary>
+ public int Sign {
+ get {
+ return Value.Sign;
+ }
+ }
+
+ public bool AsInt64(out long ret) {
+ if (Value >= Int64.MinValue && Value <= Int64.MaxValue) {
+ ret = (long)Value;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ [CLSCompliant(false)]
+ public bool AsUInt32(out uint ret) {
+ if (Value >= UInt32.MinValue && Value <= UInt32.MaxValue) {
+ ret = (UInt32)Value;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ [CLSCompliant(false)]
+ public bool AsUInt64(out ulong ret) {
+ if (Value >= UInt64.MinValue && Value <= UInt64.MaxValue) {
+ ret = (UInt64)Value;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ public bool AsInt32(out int ret) {
+ if (Value >= Int32.MinValue && Value <= Int32.MaxValue) {
+ ret = (Int32)Value;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ [CLSCompliant(false)]
+ public uint ToUInt32() {
+ return (uint)Value;
+ }
+
+ public int ToInt32() {
+ return (int)Value;
+ }
+
+ public decimal ToDecimal() {
+ return (decimal)Value;
+ }
+
+ [CLSCompliant(false)]
+ public ulong ToUInt64() {
+ return (ulong)Value;
+ }
+
+ public long ToInt64() {
+ return (long)Value;
+ }
+
+ private static int GetLength(uint[] data) {
+ int ret = data.Length - 1;
+ while (ret >= 0 && data[ret] == 0) ret--;
+ return ret + 1;
+ }
+
+ public static int Compare(BigInteger x, BigInteger y) {
+ return BigInt.Compare(x.Value, y.Value);
+ }
+
+ public static bool operator ==(BigInteger x, int y) {
+ return x.Value == y;
+ }
+
+ public static bool operator !=(BigInteger x, int y) {
+ return x.Value != y;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
+ public static bool operator ==(BigInteger x, double y) {
+ if (object.ReferenceEquals(x, null)) {
+ throw new ArgumentNullException("x");
+ }
+
+ // we can hold all double values, but not all double values
+ // can hold BigInteger values, and we may lose precision. Convert
+ // the double to a big int, then compare.
+
+ if ((y % 1) != 0) return false; // not a whole number, can't be equal
+
+ return x.Value == (BigInt)y;
+ }
+
+ public static bool operator ==(double x, BigInteger y) {
+ return y == x;
+ }
+
+ public static bool operator !=(BigInteger x, double y) {
+ return !(x == y);
+ }
+
+ public static bool operator !=(double x, BigInteger y) {
+ return !(x == y);
+ }
+
+
+ public static bool operator ==(BigInteger x, BigInteger y) {
+ return Compare(x, y) == 0;
+ }
+
+ public static bool operator !=(BigInteger x, BigInteger y) {
+ return Compare(x, y) != 0;
+ }
+ public static bool operator <(BigInteger x, BigInteger y) {
+ return Compare(x, y) < 0;
+ }
+ public static bool operator <=(BigInteger x, BigInteger y) {
+ return Compare(x, y) <= 0;
+ }
+ public static bool operator >(BigInteger x, BigInteger y) {
+ return Compare(x, y) > 0;
+ }
+ public static bool operator >=(BigInteger x, BigInteger y) {
+ return Compare(x, y) >= 0;
+ }
+
+ public static BigInteger Add(BigInteger x, BigInteger y) {
+ return x + y;
+ }
+
+ public static BigInteger operator +(BigInteger x, BigInteger y) {
+ return new BigInteger(x.Value + y.Value);
+ }
+
+ public static BigInteger Subtract(BigInteger x, BigInteger y) {
+ return x - y;
+ }
+
+ public static BigInteger operator -(BigInteger x, BigInteger y) {
+ return new BigInteger(x.Value - y.Value);
+ }
+
+ public static BigInteger Multiply(BigInteger x, BigInteger y) {
+ return x * y;
+ }
+
+ public static BigInteger operator *(BigInteger x, BigInteger y) {
+ return new BigInteger(x.Value * y.Value);
+ }
+
+ public static BigInteger Divide(BigInteger x, BigInteger y) {
+ return x / y;
+ }
+
+ public static BigInteger operator /(BigInteger x, BigInteger y) {
+ BigInteger dummy;
+ return DivRem(x, y, out dummy);
+ }
+
+ public static BigInteger Mod(BigInteger x, BigInteger y) {
+ return x % y;
+ }
+
+ public static BigInteger operator %(BigInteger x, BigInteger y) {
+ BigInteger ret;
+ DivRem(x, y, out ret);
+ return ret;
+ }
+
+ public static BigInteger DivRem(BigInteger x, BigInteger y, out BigInteger remainder) {
+ BigInt rem;
+ BigInt result = BigInt.DivRem(x.Value, y.Value, out rem);
+ remainder = new BigInteger(rem);
+ return new BigInteger(result);
+ }
+
+ public static BigInteger BitwiseAnd(BigInteger x, BigInteger y) {
+ return x & y;
+ }
+
+ public static BigInteger operator &(BigInteger x, BigInteger y) {
+ return new BigInteger(x.Value & y.Value);
+ }
+
+ public static BigInteger BitwiseOr(BigInteger x, BigInteger y) {
+ return x | y;
+ }
+
+ public static BigInteger operator |(BigInteger x, BigInteger y) {
+ return new BigInteger(x.Value | y.Value);
+ }
+
+ public static BigInteger Xor(BigInteger x, BigInteger y) {
+ return x ^ y;
+ }
+
+ public static BigInteger operator ^(BigInteger x, BigInteger y) {
+ return new BigInteger(x.Value ^ y.Value);
+ }
+
+ public static BigInteger LeftShift(BigInteger x, int shift) {
+ return x << shift;
+ }
+
+ public static BigInteger operator <<(BigInteger x, int shift) {
+ return new BigInteger(x.Value << shift);
+ }
+
+ public static BigInteger RightShift(BigInteger x, int shift) {
+ return x >> shift;
+ }
+
+ public static BigInteger operator >>(BigInteger x, int shift) {
+ return new BigInteger(x.Value >> shift);
+ }
+
+ public static BigInteger Negate(BigInteger x) {
+ return -x;
+ }
+
+ public static BigInteger operator -(BigInteger x) {
+ return new BigInteger(-x.Value);
+ }
+
+ public BigInteger OnesComplement() {
+ return ~this;
+ }
+
+ public static BigInteger operator ~(BigInteger x) {
+ return new BigInteger(~x.Value);
+ }
+
+ public BigInteger Abs() {
+ return new BigInteger(BigInt.Abs(Value));
+ }
+
+ public BigInteger Power(int exp) {
+ return new BigInteger(BigInt.Pow(Value, exp));
+ }
+
+ public BigInteger ModPow(int power, BigInteger mod) {
+ return new BigInteger(BigInt.ModPow(Value, power, mod.Value));
+ }
+
+ public BigInteger ModPow(BigInteger power, BigInteger mod) {
+ return new BigInteger(BigInt.ModPow(Value, power.Value, mod.Value));
+ }
+
+ public BigInteger Square() {
+ return this * this;
+ }
+
+#if !SILVERLIGHT
+ public static BigInteger Parse(string str) {
+ return new BigInteger(BigInt.Parse(str));
+ }
+#endif
+
+ public override string ToString() {
+ return ToString(10);
+ }
+
+ public string ToString(int @base) {
+ return MathUtils.BigIntegerToString(GetWords(), Sign, @base, false);
+ }
+
+ public string ToString(string format) {
+ return Value.ToString(format);
+ }
+
+ public override int GetHashCode() {
+ return Value.GetHashCode();
+ }
+
+ public override bool Equals(object obj) {
+ return Equals(obj as BigInteger);
+ }
+
+ public bool Equals(BigInteger other) {
+ if (object.ReferenceEquals(other, null)) return false;
+ return this == other;
+ }
+
+ public bool IsNegative() {
+ return Value.Sign < 0;
+ }
+
+ public bool IsZero() {
+ return Value.Sign == 0;
+ }
+
+ public bool IsPositive() {
+ return Value.Sign > 0;
+ }
+
+ public bool IsEven {
+ get { return Value.IsEven; }
+ }
+
+ public bool IsPowerOfTwo {
+ get {
+ return Value.IsPowerOfTwo;
+ }
+ }
+
+ public double Log(Double newBase) {
+ return BigInt.Log(Value, newBase);
+ }
+
+ /// <summary>
+ /// Calculates the natural logarithm of the BigInteger.
+ /// </summary>
+ public double Log() {
+ return BigInt.Log(Value);
+ }
+
+ /// <summary>
+ /// Calculates log base 10 of a BigInteger.
+ /// </summary>
+ public double Log10() {
+ return BigInt.Log10(Value);
+ }
+
+#region IComparable Members
+
+ public int CompareTo(object obj) {
+ if (obj == null) {
+ return 1;
+ }
+ BigInteger o = obj as BigInteger;
+ if (object.ReferenceEquals(o, null)) {
+ throw new ArgumentException("expected integer");
+ }
+ return Compare(this, o);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Return the value of this BigInteger as a little-endian twos-complement
+ /// byte array, using the fewest number of bytes possible. If the value is zero,
+ /// return an array of one byte whose element is 0x00.
+ /// </summary>
+ public byte[] ToByteArray() {
+ return Value.ToByteArray();
+ }
+
+ public string ToString(IFormatProvider provider) {
+ return Value.ToString(provider);
+ }
+
+#region IFormattable Members
+
+ string IFormattable.ToString(string format, IFormatProvider formatProvider) {
+ return Value.ToString(format, formatProvider);
+ }
+
+ #endregion
+ }
+}
+#endif
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/Complex64.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/Complex64.cs
new file mode 100644
index 00000000000..bb6da752e40
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Math/Complex64.cs
@@ -0,0 +1,276 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using Microsoft.Scripting.Utils;
+
+#if FEATURE_NUMERICS
+using BigInt = System.Numerics.BigInteger;
+#endif
+
+namespace Microsoft.Scripting.Math {
+ /// <summary>
+ /// Implementation of the complex number data type.
+ /// </summary>
+ [Serializable]
+ public struct Complex64 {
+ public static readonly Complex64 Zero = new Complex64(0.0, 0.0);
+ public static readonly Complex64 One = new Complex64(1.0, 0.0);
+ public static readonly Complex64 ImaginaryOne = new Complex64(0.0, 1.0);
+
+ private readonly double real, imag;
+
+ public static Complex64 MakeImaginary(double imag) {
+ return new Complex64(0.0, imag);
+ }
+
+ public static Complex64 MakeReal(double real) {
+ return new Complex64(real, 0.0);
+ }
+
+ public static Complex64 Make(double real, double imag) {
+ return new Complex64(real, imag);
+ }
+
+ public Complex64(double real)
+ : this(real, 0.0) {
+ }
+
+ public Complex64(double real, double imag) {
+ this.real = real;
+ this.imag = imag;
+ }
+
+ public bool IsZero {
+ get {
+ return real == 0.0 && imag == 0.0;
+ }
+ }
+
+ public double Real {
+ get {
+ return real;
+ }
+ }
+
+ public double Imag {
+ get {
+ return imag;
+ }
+ }
+
+ public Complex64 Conjugate() {
+ return new Complex64(real, -imag);
+ }
+
+
+ public override string ToString() {
+ if (real == 0.0) return imag.ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat) + "j";
+ else if (imag < 0.0) return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}{1}j)", real, imag);
+ else return string.Format(System.Globalization.CultureInfo.InvariantCulture.NumberFormat, "({0}+{1}j)", real, imag);
+ }
+
+ public static implicit operator Complex64(bool b) {
+ return b ? One : Zero;
+ }
+
+ public static implicit operator Complex64(int i) {
+ return MakeReal(i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Complex64(uint i) {
+ return MakeReal(i);
+ }
+
+ public static implicit operator Complex64(short i) {
+ return MakeReal(i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Complex64(ushort i) {
+ return MakeReal(i);
+ }
+
+ public static implicit operator Complex64(long l) {
+ return MakeReal(l);
+ }
+ [CLSCompliant(false)]
+ public static implicit operator Complex64(ulong i) {
+ return MakeReal(i);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Complex64(sbyte i) {
+ return MakeReal(i);
+ }
+
+ public static implicit operator Complex64(byte i) {
+ return MakeReal(i);
+ }
+
+ public static implicit operator Complex64(float f) {
+ return MakeReal(f);
+ }
+
+ public static implicit operator Complex64(double d) {
+ return MakeReal(d);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
+ public static implicit operator Complex64(BigInteger i) {
+ ContractUtils.RequiresNotNull(i, "i");
+
+ // throws an overflow exception if we can't handle the value.
+ return MakeReal((double)i);
+ }
+
+#if FEATURE_NUMERICS
+ public static implicit operator Complex64(BigInt i) {
+ // throws an overflow exception if we can't handle the value.
+ return MakeReal((double)i);
+ }
+#endif
+
+ public static bool operator ==(Complex64 x, Complex64 y) {
+ return x.real == y.real && x.imag == y.imag;
+ }
+
+ public static bool operator !=(Complex64 x, Complex64 y) {
+ return x.real != y.real || x.imag != y.imag;
+ }
+
+ public static Complex64 Add(Complex64 x, Complex64 y) {
+ return x + y;
+ }
+
+ public static Complex64 operator +(Complex64 x, Complex64 y) {
+ return new Complex64(x.real + y.real, x.imag + y.imag);
+ }
+
+ public static Complex64 Subtract(Complex64 x, Complex64 y) {
+ return x - y;
+ }
+
+ public static Complex64 operator -(Complex64 x, Complex64 y) {
+ return new Complex64(x.real - y.real, x.imag - y.imag);
+ }
+
+ public static Complex64 Multiply(Complex64 x, Complex64 y) {
+ return x * y;
+ }
+
+ public static Complex64 operator *(Complex64 x, Complex64 y) {
+ return new Complex64(x.real * y.real - x.imag * y.imag, x.real * y.imag + x.imag * y.real);
+ }
+
+ public static Complex64 Divide(Complex64 x, Complex64 y) {
+ return x / y;
+ }
+
+ public static Complex64 operator /(Complex64 a, Complex64 b) {
+ if (b.IsZero) {
+ throw new DivideByZeroException("complex division by zero");
+ }
+
+ double real, imag, den, r;
+
+ if (System.Math.Abs(b.real) >= System.Math.Abs(b.imag)) {
+ r = b.imag / b.real;
+ den = b.real + r * b.imag;
+ real = (a.real + a.imag * r) / den;
+ imag = (a.imag - a.real * r) / den;
+ } else {
+ r = b.real / b.imag;
+ den = b.imag + r * b.real;
+ real = (a.real * r + a.imag) / den;
+ imag = (a.imag * r - a.real) / den;
+ }
+
+ return new Complex64(real, imag);
+ }
+
+ public static Complex64 Negate(Complex64 x) {
+ return -x;
+ }
+
+ public static Complex64 operator -(Complex64 x) {
+ return new Complex64(-x.real, -x.imag);
+ }
+
+ public static Complex64 Plus(Complex64 x) {
+ return +x;
+ }
+
+ public static Complex64 operator +(Complex64 x) {
+ return x;
+ }
+
+ [Obsolete("Deprecated - consider using MS.Scripting.Utils.MathUtils.Hypot")]
+ public static double Hypot(double x, double y) {
+ return MathUtils.Hypot(x, y);
+ }
+
+ public double Abs() {
+ return MathUtils.Hypot(real, imag);
+ }
+
+ public Complex64 Power(Complex64 y) {
+ double c = y.real;
+ double d = y.imag;
+ int power = (int)c;
+
+ if (power == c && power >= 0 && d == .0) {
+ Complex64 result = One;
+ if (power == 0) return result;
+ Complex64 factor = this;
+ while (power != 0) {
+ if ((power & 1) != 0) {
+ result = result * factor;
+ }
+ factor = factor * factor;
+ power >>= 1;
+ }
+ return result;
+ } else if (IsZero) {
+ return y.IsZero ? One : Zero;
+ } else {
+ double a = real;
+ double b = imag;
+ double powers = a * a + b * b;
+ double arg = System.Math.Atan2(b, a);
+ double mul = System.Math.Pow(powers, c / 2) * System.Math.Exp(-d * arg);
+ double common = c * arg + .5 * d * System.Math.Log(powers);
+ return new Complex64(mul * System.Math.Cos(common), mul * System.Math.Sin(common));
+ }
+ }
+
+ public override int GetHashCode() {
+ // The Object.GetHashCode function needs to be consistent with the Object.Equals function.
+ // Languages that build on top of this may have a more flexible equality function and
+ // so may not be able to use this hash function directly.
+ // For example, Python allows that c=Complex64(1.5, 0), f = 1.5f, c==f.
+ // so then the hash(f) == hash(c). Since the python (and other languages) can define an arbitrary
+ // hash(float) function, the language may need to define a matching hash(complex) function for
+ // the cases where the float and complex numbers overlap.
+ return (int)real + (int)imag * 1000003;
+ }
+
+ public override bool Equals(object obj) {
+ if (!(obj is Complex64)) return false;
+ return this == ((Complex64)obj);
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs
new file mode 100644
index 00000000000..3b0cc25069a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/MultiRuntimeAwareAttribute.cs
@@ -0,0 +1,34 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Diagnostics;
+
+namespace Microsoft.Scripting {
+ /// <summary>
+ /// marks a field, class, or struct as being safe to have statics which can be accessed
+ /// from multiple runtimes.
+ ///
+ /// Static fields which are not read-only or marked with this attribute will be flagged
+ /// by a test which looks for state being shared between runtimes. Before applying this
+ /// attribute you should ensure that it is safe to share the state. This is typically
+ /// state which is lazy initialized or state which is caching values which are identical
+ /// in all runtimes and are immutable.
+ /// </summary>
+ [Conditional("DEBUG")]
+ [AttributeUsage(AttributeTargets.Field)]
+ public sealed class MultiRuntimeAwareAttribute : Attribute {
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs
new file mode 100644
index 00000000000..622e41d0927
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/PerfTrack.cs
@@ -0,0 +1,185 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.Scripting.Utils;
+using System.Dynamic;
+using System.IO;
+
+namespace Microsoft.Scripting {
+ /// <summary>
+ /// This class is useful for quickly collecting performance counts for expensive
+ /// operations. Usually this means operations involving either reflection or
+ /// code gen. Long-term we need to see if this can be plugged better into the
+ /// standard performance counter architecture.
+ /// </summary>
+ public static class PerfTrack {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1717:OnlyFlagsEnumsShouldHavePluralNames")] // TODO: fix
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] // TODO: fix
+ public enum Categories {
+ /// <summary>
+ /// temporary categories for quick investigation, use a custom key if you
+ /// need to track multiple items, and if you want to keep it then create
+ /// a new Categories entry and rename all your temporary entries.
+ /// </summary>
+ Temporary,
+ ReflectedTypes,
+ Exceptions, // exceptions thrown
+ Properties, // properties got or set
+ Fields, // fields got or set
+ Methods, // methods called through MethodBase.Invoke()...
+ Compiler, // Methods compiled via the ReflectOptimizer
+ DelegateCreate, // we've created a new method for delegates
+ DictInvoke, // Dictionary accesses
+ OperatorInvoke, // Invoking an operator against a type
+ OverAllocate, // a spot where we have an un-ideal algorithm that needs to allocate more than necessary
+ Rules, // related to rules / actions.
+ RuleEvaluation, // a rule was evaluated
+ Binding, // a rule was bound
+ BindingSlow,
+ BindingFast,
+ BindingTarget, // a rule was bound against a target of a specific type
+ Count
+ }
+
+ [MultiRuntimeAware]
+ private static int totalEvents;
+ private static readonly Dictionary<Categories, Dictionary<string, int>> _events = MakeEventsDictionary();
+ private static readonly Dictionary<Categories, int> summaryStats = new Dictionary<Categories, int>();
+
+ private static Dictionary<Categories, Dictionary<string, int>> MakeEventsDictionary() {
+ Dictionary<Categories, Dictionary<string, int>> result = new Dictionary<Categories, Dictionary<string, int>>();
+
+ // We do not use Enum.GetValues here since it is not available in SILVERLIGHT
+ for (int i = 0; i <= (int)Categories.Count; i++) {
+ result[(Categories)i] = new Dictionary<string, int>();
+ }
+
+ return result;
+ }
+
+#if FEATURE_BASIC_CONSOLE
+ public static void DumpHistogram<TKey>(IDictionary<TKey, int> histogram) {
+ DumpHistogram(histogram, Console.Out);
+ }
+
+ public static void DumpStats() {
+ DumpStats(Console.Out);
+ }
+#endif
+
+ public static void DumpHistogram<TKey>(IDictionary<TKey, int> histogram, TextWriter output) {
+ var keys = ArrayUtils.MakeArray(histogram.Keys);
+ var values = ArrayUtils.MakeArray(histogram.Values);
+
+#if !WIN8 // TODO:
+ Array.Sort(values, keys);
+#endif
+ for (int i = 0; i < keys.Length; i++) {
+ output.WriteLine("{0} {1}", keys[i], values[i]);
+ }
+ }
+
+ public static void AddHistograms<TKey>(IDictionary<TKey, int> result, IDictionary<TKey, int> addend) {
+ foreach (var entry in addend) {
+ int value;
+ result[entry.Key] = entry.Value + (result.TryGetValue(entry.Key, out value) ? value : 0);
+ }
+ }
+
+ public static void IncrementEntry<TKey>(IDictionary<TKey, int> histogram, TKey key) {
+ int value;
+ histogram.TryGetValue(key, out value);
+ histogram[key] = value + 1;
+ }
+
+ public static void DumpStats(TextWriter output) {
+ if (totalEvents == 0) return;
+
+ // numbers from AMD Opteron 244 1.8 Ghz, 2.00GB of ram,
+ // running on IronPython 1.0 Beta 4 against Whidbey RTM.
+ const double CALL_TIME = 0.0000051442355;
+ const double THROW_TIME = 0.000025365656;
+ const double FIELD_TIME = 0.0000018080093;
+
+ output.WriteLine();
+ output.WriteLine("---- Performance Details ----");
+ output.WriteLine();
+
+ foreach (KeyValuePair<Categories, Dictionary<string, int>> kvpCategories in _events) {
+ if (kvpCategories.Value.Count > 0) {
+ output.WriteLine("Category : " + kvpCategories.Key);
+ DumpHistogram(kvpCategories.Value, output);
+ output.WriteLine();
+ }
+ }
+
+ output.WriteLine();
+ output.WriteLine("---- Performance Summary ----");
+ output.WriteLine();
+ double knownTimes = 0;
+ foreach (KeyValuePair<Categories, int> kvp in summaryStats) {
+ switch (kvp.Key) {
+ case Categories.Exceptions:
+ output.WriteLine("Total Exception ({0}) = {1} (throwtime = ~{2} secs)", kvp.Key, kvp.Value, kvp.Value * THROW_TIME);
+ knownTimes += kvp.Value * THROW_TIME;
+ break;
+ case Categories.Fields:
+ output.WriteLine("Total field = {0} (time = ~{1} secs)", kvp.Value, kvp.Value * FIELD_TIME);
+ knownTimes += kvp.Value * FIELD_TIME;
+ break;
+ case Categories.Methods:
+ output.WriteLine("Total calls = {0} (calltime = ~{1} secs)", kvp.Value, kvp.Value * CALL_TIME);
+ knownTimes += kvp.Value * CALL_TIME;
+ break;
+ //case Categories.Properties:
+ default:
+ output.WriteLine("Total {1} = {0}", kvp.Value, kvp.Key);
+ break;
+ }
+ }
+
+ output.WriteLine();
+ output.WriteLine("Total Known Times: {0}", knownTimes);
+ }
+
+ [Conditional("DEBUG")]
+ public static void NoteEvent(Categories category, object key) {
+ if (!DebugOptions.TrackPerformance) return;
+
+ Dictionary<string, int> categoryEvents = _events[category];
+ totalEvents++;
+ lock (categoryEvents) {
+ string name = key.ToString();
+ Exception ex = key as Exception;
+ if (ex != null) name = ex.GetType().ToString();
+ int v;
+ if (!categoryEvents.TryGetValue(name, out v)) categoryEvents[name] = 1;
+ else categoryEvents[name] = v + 1;
+
+ if (!summaryStats.TryGetValue(category, out v)) summaryStats[category] = 1;
+ else summaryStats[category] = v + 1;
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ArgumentArray.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ArgumentArray.cs
new file mode 100644
index 00000000000..b6484afc31d
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ArgumentArray.cs
@@ -0,0 +1,76 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, please send an email to
+ * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
+ * by the terms of the Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Dynamic;
+using System.Reflection;
+using Microsoft.Scripting.Utils;
+
+namespace Microsoft.Scripting.Runtime {
+ using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+ /// <summary>
+ /// Wraps all arguments passed to a dynamic site with more arguments than can be accepted by a Func/Action delegate.
+ /// The binder generating a rule for such a site should unwrap the arguments first and then perform a binding to them.
+ /// </summary>
+ public sealed class ArgumentArray {
+ private readonly object[] _arguments;
+
+ // the index of the first item _arguments that represents an argument:
+ private readonly int _first;
+
+ // the number of items in _arguments that represent the arguments:
+ private readonly int _count;
+
+ internal ArgumentArray(object[] arguments, int first, int count) {
+ _arguments = arguments;
+ _first = first;
+ _count = count;
+ }
+
+ public int Count {
+ get { return _count; }
+ }
+
+ public object GetArgument(int index) {
+ ContractUtils.RequiresArrayIndex(_arguments, index, "index");
+ return _arguments[_first + index];
+ }
+
+ public DynamicMetaObject GetMetaObject(Expression parameter, int index) {
+ return DynamicMetaObject.Create(
+ GetArgument(index),
+ Expression.Call(
+ _GetArgMethod,
+ AstUtils.Convert(parameter, typeof(ArgumentArray)),
+ AstUtils.Constant(index)
+ )
+ );
+ }
+
+ [CLSCompliant(false)]
+ public static object GetArg(ArgumentArray array, int index) {
+ return array._arguments[array._first + index];
+ }
+
+ private static readonly MethodInfo _GetArgMethod = new Func<ArgumentArray, int, object>(GetArg).GetMethodInfo();
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/DynamicNull.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/DynamicNull.cs
new file mode 100644
index 00000000000..378bea4d090
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/DynamicNull.cs
@@ -0,0 +1,27 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+namespace Microsoft.Scripting.Runtime {
+ /// <summary>
+ /// Represents the type of a null value.
+ /// </summary>
+ public sealed class DynamicNull {
+ /// <summary>
+ /// Private constructor is never called since 'null' is the only valid instance.
+ /// </summary>
+ private DynamicNull() { }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ExceptionHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ExceptionHelpers.cs
new file mode 100644
index 00000000000..43350e7611e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ExceptionHelpers.cs
@@ -0,0 +1,79 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Threading;
+using Microsoft.Scripting.Actions;
+using Microsoft.Scripting.Generation;
+
+namespace Microsoft.Scripting.Runtime {
+ public static class ExceptionHelpers {
+#if FEATURE_STACK_TRACE
+ private const string prevStackTraces = "PreviousStackTraces";
+
+ /// <summary>
+ /// Updates an exception before it's getting re-thrown so
+ /// we can present a reasonable stack trace to the user.
+ /// </summary>
+ public static Exception UpdateForRethrow(Exception rethrow) {
+#if !SILVERLIGHT
+ List<StackTrace> prev;
+
+ // we don't have any dynamic stack trace data, capture the data we can
+ // from the raw exception object.
+ StackTrace st = new StackTrace(rethrow, true);
+
+ if (!TryGetAssociatedStackTraces(rethrow, out prev)) {
+ prev = new List<StackTrace>();
+ AssociateStackTraces(rethrow, prev);
+ }
+
+ prev.Add(st);
+
+#endif
+ return rethrow;
+ }
+
+ /// <summary>
+ /// Returns all the stack traces associates with an exception
+ /// </summary>
+ public static IList<StackTrace> GetExceptionStackTraces(Exception rethrow) {
+ List<StackTrace> result;
+ return TryGetAssociatedStackTraces(rethrow, out result) ? result : null;
+ }
+
+ private static void AssociateStackTraces(Exception e, List<StackTrace> traces) {
+ e.Data[prevStackTraces] = traces;
+ }
+
+ private static bool TryGetAssociatedStackTraces(Exception e, out List<StackTrace> traces) {
+ traces = e.Data[prevStackTraces] as List<StackTrace>;
+ return traces != null;
+ }
+#else
+ public static Exception UpdateForRethrow(Exception rethrow) {
+ return rethrow;
+ }
+#endif
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ScriptingRuntimeHelpers.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ScriptingRuntimeHelpers.cs
new file mode 100644
index 00000000000..f7fc8b33eda
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Runtime/ScriptingRuntimeHelpers.cs
@@ -0,0 +1,261 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.Scripting.Actions;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Utils;
+using Microsoft.Scripting.Interpreter;
+
+namespace Microsoft.Scripting.Runtime {
+ /// <summary>
+ /// These are some generally useful helper methods. Currently the only methods are those to
+ /// cached boxed representations of commonly used primitive types so that they can be shared.
+ /// This is useful to most dynamic languages that use object as a universal type.
+ ///
+ /// The methods in RuntimeHelepers are caleld by the generated code. From here the methods may
+ /// dispatch to other parts of the runtime to get bulk of the work done, but the entry points
+ /// should be here.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
+ public static partial class ScriptingRuntimeHelpers {
+ private const int MIN_CACHE = -100;
+ private const int MAX_CACHE = 1000;
+ private static readonly object[] cache = MakeCache();
+
+ /// <summary>
+ /// A singleton boxed boolean true.
+ /// </summary>
+ public static readonly object True = true;
+
+ /// <summary>
+ ///A singleton boxed boolean false.
+ /// </summary>
+ public static readonly object False = false;
+
+ internal static readonly MethodInfo BooleanToObjectMethod = typeof(ScriptingRuntimeHelpers).GetMethod("BooleanToObject");
+ internal static readonly MethodInfo Int32ToObjectMethod = typeof(ScriptingRuntimeHelpers).GetMethod("Int32ToObject");
+
+ private static object[] MakeCache() {
+ object[] result = new object[MAX_CACHE - MIN_CACHE];
+
+ for (int i = 0; i < result.Length; i++) {
+ result[i] = (object)(i + MIN_CACHE);
+ }
+
+ return result;
+ }
+
+#if DEBUG
+ public static void NoteException(Exception e) {
+ PerfTrack.NoteEvent(PerfTrack.Categories.Exceptions, "LightEH Missed: " + e.GetType());
+ }
+#endif
+
+ /// <summary>
+ /// Gets a singleton boxed value for the given integer if possible, otherwise boxes the integer.
+ /// </summary>
+ /// <param name="value">The value to box.</param>
+ /// <returns>The boxed value.</returns>
+ public static object Int32ToObject(Int32 value) {
+ // caches improves pystone by ~5-10% on MS .Net 1.1, this is a very integer intense app
+ // TODO: investigate if this still helps perf. There's evidence that it's harmful on
+ // .NET 3.5 and 4.0
+ if (value < MAX_CACHE && value >= MIN_CACHE) {
+ return cache[value - MIN_CACHE];
+ }
+ return (object)value;
+ }
+
+ private static readonly string[] chars = MakeSingleCharStrings();
+
+ private static string[] MakeSingleCharStrings() {
+ string[] result = new string[255];
+
+ for (char ch = (char)0; ch < result.Length; ch++) {
+ result[ch] = new string(ch, 1);
+ }
+
+ return result;
+ }
+
+ public static object BooleanToObject(bool value) {
+ return value ? True : False;
+ }
+
+ public static string CharToString(char ch) {
+ if (ch < 255) return chars[ch];
+ return new string(ch, 1);
+ }
+
+ internal static object GetPrimitiveDefaultValue(Type type) {
+ switch (type.GetTypeCode()) {
+ case TypeCode.Boolean: return ScriptingRuntimeHelpers.False;
+ case TypeCode.SByte: return default(SByte);
+ case TypeCode.Byte: return default(Byte);
+ case TypeCode.Char: return default(Char);
+ case TypeCode.Int16: return default(Int16);
+ case TypeCode.Int32: return ScriptingRuntimeHelpers.Int32ToObject(0);
+ case TypeCode.Int64: return default(Int64);
+ case TypeCode.UInt16: return default(UInt16);
+ case TypeCode.UInt32: return default(UInt32);
+ case TypeCode.UInt64: return default(UInt64);
+ case TypeCode.Single: return default(Single);
+ case TypeCode.Double: return default(Double);
+#if FEATURE_DBNULL
+ case TypeCode.DBNull: return default(DBNull);
+#endif
+ case TypeCode.DateTime: return default(DateTime);
+ case TypeCode.Decimal: return default(Decimal);
+ default: return null;
+ }
+ }
+
+ public static ArgumentTypeException SimpleTypeError(string message) {
+ return new ArgumentTypeException(message);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // TODO: fix
+ public static Exception CannotConvertError(Type toType, object value) {
+ return SimpleTypeError(String.Format("Cannot convert {0}({1}) to {2}", CompilerHelpers.GetType(value).Name, value, toType.Name));
+ }
+
+ public static Exception SimpleAttributeError(string message) {
+ //TODO: localize
+ return new MissingMemberException(message);
+ }
+
+ public static object ReadOnlyAssignError(bool field, string fieldName) {
+ if (field) {
+ throw Error.FieldReadonly(fieldName);
+ } else {
+ throw Error.PropertyReadonly(fieldName);
+ }
+ }
+
+ /// <summary>
+ /// Helper method to create an instance. Work around for Silverlight where Activator.CreateInstance
+ /// is SecuritySafeCritical.
+ ///
+ /// TODO: Why can't we just emit the right thing for default(T)?
+ /// It's always null for reference types and it's well defined for value types
+ /// </summary>
+ public static T CreateInstance<T>() {
+ return default(T);
+ }
+
+ // TODO: can't we just emit a new array?
+ public static T[] CreateArray<T>(int args) {
+ return new T[args];
+ }
+
+ /// <summary>
+ /// EventInfo.EventHandlerType getter is marked SecuritySafeCritical in CoreCLR
+ /// This method is to get to the property without using Reflection
+ /// </summary>
+ /// <param name="eventInfo"></param>
+ /// <returns></returns>
+ public static Type GetEventHandlerType(EventInfo eventInfo) {
+ ContractUtils.RequiresNotNull(eventInfo, "eventInfo");
+ return eventInfo.EventHandlerType;
+ }
+
+ public static IList<string> GetStringMembers(IList<object> members) {
+ List<string> res = new List<string>();
+ foreach (object o in members) {
+ string str = o as string;
+ if (str != null) {
+ res.Add(str);
+ }
+ }
+ return res;
+ }
+#if !MONO_INTERPRETER
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // TODO: fix
+ public static void SetEvent(EventTracker eventTracker, object value) {
+ EventTracker et = value as EventTracker;
+ if (et != null) {
+ if (et != eventTracker) {
+ throw Error.UnexpectedEvent(eventTracker.DeclaringType.Name,
+ eventTracker.Name,
+ et.DeclaringType.Name,
+ et.Name);
+ }
+ return;
+ }
+
+ BoundMemberTracker bmt = value as BoundMemberTracker;
+ if (bmt == null) {
+ throw Error.ExpectedBoundEvent(CompilerHelpers.GetType(value).Name);
+ }
+ if (bmt.BoundTo.MemberType != TrackerTypes.Event) throw Error.ExpectedBoundEvent(bmt.BoundTo.MemberType.ToString());
+
+ if (bmt.BoundTo != eventTracker) throw Error.UnexpectedEvent(
+ eventTracker.DeclaringType.Name,
+ eventTracker.Name,
+ bmt.BoundTo.DeclaringType.Name,
+ bmt.BoundTo.Name);
+ }
+#endif
+ // TODO: just emit this in the generated code
+ public static bool CheckDictionaryMembers(IDictionary dict, string[] names) {
+ if (dict.Count != names.Length) return false;
+
+ foreach (string name in names) {
+ if (!dict.Contains(name)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // TODO: just emit this in the generated code
+ [Obsolete("use MakeIncorrectBoxTypeError instead")]
+ public static T IncorrectBoxType<T>(object received) {
+ throw Error.UnexpectedType("StrongBox<" + typeof(T).Name + ">", CompilerHelpers.GetType(received).Name);
+ }
+
+ public static Exception MakeIncorrectBoxTypeError(Type type, object received) {
+ return Error.UnexpectedType("StrongBox<" + type.Name + ">", CompilerHelpers.GetType(received).Name);
+ }
+
+ /// <summary>
+ /// Provides the test to see if an interpreted call site should switch over to being compiled.
+ /// </summary>
+ public static bool InterpretedCallSiteTest(bool restrictionResult, object bindingInfo) {
+ if (restrictionResult) {
+ CachedBindingInfo bindInfo = (CachedBindingInfo)bindingInfo;
+ if (bindInfo.CompilationThreshold >= 0) {
+ // still interpreting...
+ bindInfo.CompilationThreshold--;
+ return true;
+ }
+#if SILVERLIGHT
+ if (PlatformAdaptationLayer.IsCompactFramework) {
+ bindInfo.CompilationThreshold = Int32.MaxValue;
+ return true;
+ }
+#endif
+ return bindInfo.CheckCompiled();
+ }
+ return false;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ArrayUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ArrayUtils.cs
new file mode 100644
index 00000000000..4262c15b0de
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ArrayUtils.cs
@@ -0,0 +1,354 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace Microsoft.Scripting.Utils {
+ public static class ArrayUtils {
+ internal sealed class FunctorComparer<T> : IComparer<T> {
+ private readonly Comparison<T> _comparison;
+
+ public FunctorComparer(Comparison<T> comparison) {
+ Assert.NotNull(comparison);
+ _comparison = comparison;
+ }
+
+ public int Compare(T x, T y) {
+ return _comparison(x, y);
+ }
+ }
+
+ // Emitted:
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ public static readonly string[] EmptyStrings = new string[0];
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+ public static readonly object[] EmptyObjects = new object[0];
+
+ public static IComparer<T> ToComparer<T>(Comparison<T> comparison) {
+ return new FunctorComparer<T>(comparison);
+ }
+
+ public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] input, Func<TInput, TOutput> conv) {
+ ContractUtils.RequiresNotNull(input, "input");
+ ContractUtils.RequiresNotNull(conv, "conv");
+
+ TOutput[] res = new TOutput[input.Length];
+ for (int i = 0; i < input.Length; i++) {
+ res[i] = conv(input[i]);
+ }
+
+ return res;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional", MessageId = "1#")] // TODO: fix
+ public static void PrintTable(StringBuilder output, string[,] table) {
+ ContractUtils.RequiresNotNull(output, "output");
+ ContractUtils.RequiresNotNull(table, "table");
+
+ int max_width = 0;
+ for (int i = 0; i < table.GetLength(0); i++) {
+ if (table[i, 0].Length > max_width) {
+ max_width = table[i, 0].Length;
+ }
+ }
+
+ for (int i = 0; i < table.GetLength(0); i++) {
+ output.Append(" ");
+ output.Append(table[i, 0]);
+
+ for (int j = table[i, 0].Length; j < max_width + 1; j++) {
+ output.Append(' ');
+ }
+
+ output.AppendLine(table[i, 1]);
+ }
+ }
+
+ public static T[] Copy<T>(T[] array) {
+ return (array.Length > 0) ? (T[])array.Clone() : array;
+ }
+
+ /// <summary>
+ /// Converts a generic ICollection of T into an array of T.
+ ///
+ /// If the collection is already an array of T the original collection is returned.
+ /// </summary>
+ public static T[] ToArray<T>(ICollection<T> list) {
+ return (list as T[]) ?? MakeArray(list);
+ }
+
+ /// <summary>
+ /// Converts a generic ICollection of T into an array of R using a given conversion.
+ ///
+ /// If the collection is already an array of R the original collection is returned.
+ /// </summary>
+ public static TResult[] ToArray<TElement, TResult>(ICollection<TElement> list, Func<TElement, TResult> convertor) {
+ TResult[] res = list as TResult[];
+ if (res == null) {
+ res = new TResult[list.Count];
+ int i = 0;
+ foreach (TElement obj in list) {
+ res[i++] = convertor(obj);
+ }
+ }
+ return res;
+ }
+
+ public static T[] MakeArray<T>(ICollection<T> list) {
+ if (list.Count == 0) {
+ return new T[0];
+ }
+
+ T[] res = new T[list.Count];
+ list.CopyTo(res, 0);
+ return res;
+ }
+
+ public static T[] MakeArray<T>(ICollection<T> elements, int reservedSlotsBefore, int reservedSlotsAfter) {
+ if (reservedSlotsAfter < 0) throw new ArgumentOutOfRangeException("reservedSlotsAfter");
+ if (reservedSlotsBefore < 0) throw new ArgumentOutOfRangeException("reservedSlotsBefore");
+
+ if (elements == null) {
+ return new T[reservedSlotsBefore + reservedSlotsAfter];
+ }
+
+ T[] result = new T[reservedSlotsBefore + elements.Count + reservedSlotsAfter];
+ elements.CopyTo(result, reservedSlotsBefore);
+ return result;
+ }
+
+ public static T[] RotateRight<T>(T[] array, int count) {
+ ContractUtils.RequiresNotNull(array, "array");
+ if ((count < 0) || (count > array.Length)) throw new ArgumentOutOfRangeException("count");
+
+ T[] result = new T[array.Length];
+ // The head of the array is shifted, and the tail will be rotated to the head of the resulting array
+ int sizeOfShiftedArray = array.Length - count;
+ Array.Copy(array, 0, result, count, sizeOfShiftedArray);
+ Array.Copy(array, sizeOfShiftedArray, result, 0, count);
+ return result;
+ }
+
+ public static T[] ShiftRight<T>(T[] array, int count) {
+ ContractUtils.RequiresNotNull(array, "array");
+ if (count < 0) throw new ArgumentOutOfRangeException("count");
+
+ T[] result = new T[array.Length + count];
+ System.Array.Copy(array, 0, result, count, array.Length);
+ return result;
+ }
+
+ public static T[] ShiftLeft<T>(T[] array, int count) {
+ ContractUtils.RequiresNotNull(array, "array");
+ if (count < 0) throw new ArgumentOutOfRangeException("count");
+
+ T[] result = new T[array.Length - count];
+ System.Array.Copy(array, count, result, 0, result.Length);
+ return result;
+ }
+
+ public static T[] Insert<T>(T item, IList<T> list) {
+ T[] res = new T[list.Count + 1];
+ res[0] = item;
+ list.CopyTo(res, 1);
+ return res;
+ }
+
+ public static T[] Insert<T>(T item1, T item2, IList<T> list) {
+ T[] res = new T[list.Count + 2];
+ res[0] = item1;
+ res[1] = item2;
+ list.CopyTo(res, 2);
+ return res;
+ }
+
+ public static T[] Insert<T>(T item, T[] array) {
+ T[] result = ShiftRight(array, 1);
+ result[0] = item;
+ return result;
+ }
+
+ public static T[] Insert<T>(T item1, T item2, T[] array) {
+ T[] result = ShiftRight(array, 2);
+ result[0] = item1;
+ result[1] = item2;
+ return result;
+ }
+
+ public static T[] Append<T>(T[] array, T item) {
+ System.Array.Resize<T>(ref array, (array == null) ? 1 : array.Length + 1);
+ array[array.Length - 1] = item;
+ return array;
+ }
+
+ public static T[] AppendRange<T>(T[] array, IList<T> items) {
+ return AppendRange<T>(array, items, 0);
+ }
+
+ public static T[] AppendRange<T>(T[] array, IList<T> items, int additionalItemCount) {
+ if (additionalItemCount < 0) {
+ throw new ArgumentOutOfRangeException("additionalItemCount");
+ }
+
+ int j = (array == null) ? 0 : array.Length;
+ System.Array.Resize<T>(ref array, j + items.Count + additionalItemCount);
+
+ for (int i = 0; i < items.Count; i++, j++) {
+ array[j] = items[i];
+ }
+
+ return array;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional")] // TODO: fix
+ public static T[,] Concatenate<T>(T[,] array1, T[,] array2) {
+ int columnsCount = array1.GetLength(1);
+ Debug.Assert(array2.GetLength(1) == columnsCount);
+
+ int row1Count = array1.GetLength(0);
+ int row2Count = array2.GetLength(0);
+ int totalRowsCount = row1Count + row2Count;
+ T[,] result = new T[totalRowsCount, columnsCount];
+
+ for (int i = 0; i < row1Count; i++) {
+ for (int j = 0; j < columnsCount; j++) {
+ result[i, j] = array1[i, j];
+ }
+ }
+
+ for (int i = 0; i < row2Count; i++) {
+ for (int j = 0; j < columnsCount; j++) {
+ result[(i + row1Count), j] = array2[i, j];
+ }
+ }
+
+ return result;
+ }
+
+ public static void SwapLastTwo<T>(T[] array) {
+ Debug.Assert(array != null && array.Length >= 2);
+
+ T temp = array[array.Length - 1];
+ array[array.Length - 1] = array[array.Length - 2];
+ array[array.Length - 2] = temp;
+ }
+
+ public static T[] RemoveFirst<T>(IList<T> list) {
+ return ShiftLeft(MakeArray(list), 1);
+ }
+
+ public static T[] RemoveFirst<T>(T[] array) {
+ return ShiftLeft(array, 1);
+ }
+
+ public static T[] RemoveLast<T>(T[] array) {
+ ContractUtils.RequiresNotNull(array, "array");
+
+ System.Array.Resize(ref array, array.Length - 1);
+ return array;
+ }
+
+ public static T[] RemoveAt<T>(IList<T> list, int indexToRemove) {
+ return RemoveAt(MakeArray(list), indexToRemove);
+ }
+
+ public static T[] RemoveAt<T>(T[] array, int indexToRemove) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.Requires(indexToRemove >= 0 && indexToRemove < array.Length, "index");
+
+ T[] result = new T[array.Length - 1];
+ if (indexToRemove > 0) {
+ Array.Copy(array, 0, result, 0, indexToRemove);
+ }
+ int remaining = array.Length - indexToRemove - 1;
+ if (remaining > 0) {
+ Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
+ }
+ return result;
+ }
+
+ public static T[] InsertAt<T>(IList<T> list, int index, params T[] items) {
+ return InsertAt(MakeArray(list), index, items);
+ }
+
+ public static T[] InsertAt<T>(T[] array, int index, params T[] items) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.RequiresNotNull(items, "items");
+ ContractUtils.Requires(index >= 0 && index <= array.Length, "index");
+
+ if (items.Length == 0) {
+ return Copy(array);
+ }
+
+ T[] result = new T[array.Length + items.Length];
+ if (index > 0) {
+ Array.Copy(array, 0, result, 0, index);
+ }
+ Array.Copy(items, 0, result, index, items.Length);
+
+ int remaining = array.Length - index;
+ if (remaining > 0) {
+ Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
+ }
+ return result;
+ }
+
+ public static bool ValueEquals<T>(this T[] array, T[] other) {
+ if (other.Length != array.Length) {
+ return false;
+ }
+
+ for (int i = 0; i < array.Length; i++) {
+ if (!Object.Equals(array[i], other[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static int GetValueHashCode<T>(this T[] array) {
+ return GetValueHashCode<T>(array, 0, array.Length);
+ }
+
+ public static int GetValueHashCode<T>(this T[] array, int start, int count) {
+ ContractUtils.RequiresNotNull(array, "array");
+ ContractUtils.RequiresArrayRange(array.Length, start, count, "start", "count");
+
+ if (count == 0) {
+ return 0;
+ }
+
+ int result = array[start].GetHashCode();
+ for (int i = 1; i < count; i++) {
+ result = ((result << 5) | (result >> 27)) ^ array[start + i].GetHashCode();
+ }
+
+ return result;
+ }
+
+ public static T[] Reverse<T>(this T[] array) {
+ T[] res = new T[array.Length];
+ for (int i = 0; i < array.Length; i++) {
+ res[array.Length - i - 1] = array[i];
+ }
+ return res;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/Assert.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/Assert.cs
new file mode 100644
index 00000000000..adae9ddd77a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/Assert.cs
@@ -0,0 +1,78 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#define DEBUG
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Microsoft.Scripting.Utils {
+
+ public static class Assert {
+
+ public static Exception Unreachable {
+ get {
+ Debug.Assert(false, "Unreachable");
+ return new InvalidOperationException("Code supposed to be unreachable");
+ }
+ }
+
+ [Conditional("DEBUG")]
+ public static void NotNull(object var) {
+ Debug.Assert(var != null);
+ }
+
+ [Conditional("DEBUG")]
+ public static void NotNull(object var1, object var2) {
+ Debug.Assert(var1 != null && var2 != null);
+ }
+
+ [Conditional("DEBUG")]
+ public 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")]
+ public static void NotNull(object var1, object var2, object var3, object var4) {
+ Debug.Assert(var1 != null && var2 != null && var3 != null && var4 != null);
+ }
+
+ [Conditional("DEBUG")]
+ public static void NotEmpty(string str) {
+ Debug.Assert(!String.IsNullOrEmpty(str));
+ }
+
+ [Conditional("DEBUG")]
+ public static void NotEmpty<T>(ICollection<T> array) {
+ Debug.Assert(array != null && array.Count > 0);
+ }
+
+ [Conditional("DEBUG")]
+ public 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")]
+ public static void IsTrue(Func<bool> predicate) {
+ ContractUtils.RequiresNotNull(predicate, "predicate");
+ Debug.Assert(predicate());
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CacheDict.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CacheDict.cs
new file mode 100644
index 00000000000..57724cc447a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CacheDict.cs
@@ -0,0 +1,114 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace Microsoft.Scripting.Utils {
+ /// <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>
+ public 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>
+ public 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>
+ public 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>
+ public 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>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
+ public 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.Dynamic/Utils/CollectionExtensions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionExtensions.cs
new file mode 100644
index 00000000000..7eaf4000160
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionExtensions.cs
@@ -0,0 +1,156 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+
+namespace Microsoft.Scripting.Utils {
+ 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 roCollection = enumerable as ReadOnlyCollection<T>;
+ if (roCollection != null) {
+ return roCollection;
+ }
+
+ var collection = enumerable as ICollection<T>;
+ if (collection != null) {
+ int count = collection.Count;
+ if (count == 0) {
+ return EmptyReadOnlyCollection<T>.Instance;
+ }
+
+ T[] array = new T[count];
+ collection.CopyTo(array, 0);
+ return new ReadOnlyCollection<T>(array);
+ }
+
+ // ToArray trims the excess space and speeds up access
+ return new ReadOnlyCollection<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;
+ }
+
+ // 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 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[] RemoveAt<T>(this T[] array, int indexToRemove) {
+ Debug.Assert(array != null);
+ Debug.Assert(indexToRemove >= 0 && indexToRemove < array.Length);
+
+ T[] result = new T[array.Length - 1];
+ if (indexToRemove > 0) {
+ Array.Copy(array, 0, result, 0, indexToRemove);
+ }
+ int remaining = array.Length - indexToRemove - 1;
+ if (remaining > 0) {
+ Array.Copy(array, array.Length - remaining, result, result.Length - remaining, remaining);
+ }
+ return result;
+ }
+
+ internal static T[] RotateRight<T>(this T[] array, int count) {
+ Debug.Assert(count >= 0 && count <= array.Length);
+
+ T[] result = new T[array.Length];
+ // The head of the array is shifted, and the tail will be rotated to the head of the resulting array
+ int sizeOfShiftedArray = array.Length - count;
+ Array.Copy(array, 0, result, count, sizeOfShiftedArray);
+ Array.Copy(array, sizeOfShiftedArray, result, 0, count);
+ return result;
+ }
+ }
+
+
+ internal static class EmptyReadOnlyCollection<T> {
+ internal static ReadOnlyCollection<T> Instance = new ReadOnlyCollection<T>(new T[0]);
+ }
+ // TODO: Should we use this everywhere for empty arrays?
+ // my thought is, probably more hassle than its worth
+ internal static class EmptyArray<T> {
+ internal static T[] Instance = new T[0];
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionUtils.cs
new file mode 100644
index 00000000000..dec3b4e5992
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/CollectionUtils.cs
@@ -0,0 +1,322 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Microsoft.Scripting.Utils {
+ /// <summary>
+ /// Allows wrapping of proxy types (like COM RCWs) to expose their IEnumerable functionality
+ /// which is supported after casting to IEnumerable, even though Reflection will not indicate
+ /// IEnumerable as a supported interface
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1010:CollectionsShouldImplementGenericInterface")] // TODO
+ public class EnumerableWrapper : IEnumerable {
+ private IEnumerable _wrappedObject;
+ public EnumerableWrapper(IEnumerable o) {
+ _wrappedObject = o;
+ }
+
+ public IEnumerator GetEnumerator() {
+ return _wrappedObject.GetEnumerator();
+ }
+ }
+
+ public static class CollectionUtils {
+#if !FEATURE_VARIANCE
+ public static IEnumerable<T> Cast<S, T>(this IEnumerable<S> sequence) where S : T {
+ foreach (var item in sequence) {
+ yield return (T)item;
+ }
+ }
+#else
+ public static IEnumerable<T> Cast<S, T>(this IEnumerable<S> sequence) where S : T {
+ return (IEnumerable<T>)sequence;
+ }
+#endif
+
+ public static IEnumerable<TSuper> ToCovariant<T, TSuper>(IEnumerable<T> enumerable)
+ where T : TSuper {
+#if FEATURE_VARIANCE
+ return (IEnumerable<TSuper>)enumerable;
+#else
+ return new CovariantConvertor<T, TSuper>(enumerable);
+#endif
+ }
+
+ public static void AddRange<T>(ICollection<T> collection, IEnumerable<T> items) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresNotNull(items, "items");
+
+ List<T> list = collection as List<T>;
+ if (list != null) {
+ list.AddRange(items);
+ } else {
+ foreach (T item in items) {
+ collection.Add(item);
+ }
+ }
+ }
+
+ public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) {
+ foreach (var item in items) {
+ list.Add(item);
+ }
+ }
+
+ public static IEnumerable<T> ToEnumerable<T>(IEnumerable enumerable) {
+ foreach (T item in enumerable) {
+ yield return item;
+ }
+ }
+
+ public static IEnumerator<TSuper> ToCovariant<T, TSuper>(IEnumerator<T> enumerator)
+ where T : TSuper {
+
+ ContractUtils.RequiresNotNull(enumerator, "enumerator");
+
+ while (enumerator.MoveNext()) {
+ yield return enumerator.Current;
+ }
+ }
+
+ private class CovariantConvertor<T, TSuper> : IEnumerable<TSuper> where T : TSuper {
+ private IEnumerable<T> _enumerable;
+
+ public CovariantConvertor(IEnumerable<T> enumerable) {
+ ContractUtils.RequiresNotNull(enumerable, "enumerable");
+ _enumerable = enumerable;
+ }
+
+ public IEnumerator<TSuper> GetEnumerator() {
+ return CollectionUtils.ToCovariant<T, TSuper>(_enumerable.GetEnumerator());
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+ }
+
+ public static IDictionaryEnumerator ToDictionaryEnumerator(IEnumerator<KeyValuePair<object, object>> enumerator) {
+ return new DictionaryEnumerator(enumerator);
+ }
+
+ private sealed class DictionaryEnumerator : IDictionaryEnumerator {
+ private readonly IEnumerator<KeyValuePair<object, object>> _enumerator;
+
+ public DictionaryEnumerator(IEnumerator<KeyValuePair<object, object>> enumerator) {
+ _enumerator = enumerator;
+ }
+
+ public DictionaryEntry Entry {
+ get { return new DictionaryEntry(_enumerator.Current.Key, _enumerator.Current.Value); }
+ }
+
+ public object Key {
+ get { return _enumerator.Current.Key; }
+ }
+
+ public object Value {
+ get { return _enumerator.Current.Value; }
+ }
+
+ public object Current {
+ get { return Entry; }
+ }
+
+ public bool MoveNext() {
+ return _enumerator.MoveNext();
+ }
+
+ public void Reset() {
+ _enumerator.Reset();
+ }
+ }
+
+ public static List<T> MakeList<T>(T item) {
+ List<T> result = new List<T>();
+ result.Add(item);
+ return result;
+ }
+
+ public static int CountOf<T>(IList<T> list, T item) where T : IEquatable<T> {
+ if (list == null) return 0;
+
+ int result = 0;
+ for (int i = 0; i < list.Count; i++) {
+ if (list[i].Equals(item)) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ public static int Max(this IEnumerable<int> values) {
+ ContractUtils.RequiresNotNull(values, "values");
+
+ int result = Int32.MinValue;
+ foreach (var value in values) {
+ if (value > result) {
+ result = value;
+ }
+ }
+ return result;
+ }
+
+ public static bool TrueForAll<T>(IEnumerable<T> collection, Predicate<T> predicate) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresNotNull(predicate, "predicate");
+
+ foreach (T item in collection) {
+ if (!predicate(item)) return false;
+ }
+
+ return true;
+ }
+
+ public static IList<TRet> ConvertAll<T, TRet>(IList<T> collection, Func<T, TRet> predicate) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresNotNull(predicate, "predicate");
+
+ List<TRet> res = new List<TRet>(collection.Count);
+ foreach (T item in collection) {
+ res.Add(predicate(item));
+ }
+
+ return res;
+ }
+
+ public static List<T> GetRange<T>(IList<T> list, int index, int count) {
+ ContractUtils.RequiresNotNull(list, "list");
+ ContractUtils.RequiresArrayRange(list, index, count, "index", "count");
+
+ List<T> result = new List<T>(count);
+ int stop = index + count;
+ for (int i = index; i < stop; i++) {
+ result.Add(list[i]);
+ }
+ return result;
+ }
+
+ public static void InsertRange<T>(IList<T> collection, int index, IEnumerable<T> items) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresNotNull(items, "items");
+ ContractUtils.RequiresArrayInsertIndex(collection, index, "index");
+
+ List<T> list = collection as List<T>;
+ if (list != null) {
+ list.InsertRange(index, items);
+ } else {
+ int i = index;
+ foreach (T obj in items) {
+ collection.Insert(i++, obj);
+ }
+ }
+ }
+
+ public static void RemoveRange<T>(IList<T> collection, int index, int count) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresArrayRange(collection, index, count, "index", "count");
+
+ List<T> list = collection as List<T>;
+ if (list != null) {
+ list.RemoveRange(index, count);
+ } else {
+ for (int i = index + count - 1; i >= index; i--) {
+ collection.RemoveAt(i);
+ }
+ }
+ }
+
+ public static int FindIndex<T>(this IList<T> collection, Predicate<T> predicate) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresNotNull(predicate, "predicate");
+
+ for (int i = 0; i < collection.Count; i++) {
+ if (predicate(collection[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static IList<T> ToSortedList<T>(this ICollection<T> collection, Comparison<T> comparison) {
+ ContractUtils.RequiresNotNull(collection, "collection");
+ ContractUtils.RequiresNotNull(comparison, "comparison");
+
+ var array = new T[collection.Count];
+ collection.CopyTo(array, 0);
+ Array.Sort(array, comparison);
+ return array;
+ }
+
+ public static T[] ToReverseArray<T>(this IList<T> list) {
+ ContractUtils.RequiresNotNull(list, "list");
+ T[] result = new T[list.Count];
+ for (int i = 0; i < result.Length; i++) {
+ result[i] = list[result.Length - 1 - i];
+ }
+ return result;
+ }
+
+
+#if SILVERLIGHT || WIN8 || WP75
+ // HashSet.CreateSetComparer not available on Silverlight
+ public static IEqualityComparer<HashSet<T>> CreateSetComparer<T>() {
+ return new HashSetEqualityComparer<T>();
+ }
+
+ class HashSetEqualityComparer<T> : IEqualityComparer<HashSet<T>> {
+ private IEqualityComparer<T> _comparer;
+
+ public HashSetEqualityComparer() {
+ _comparer = EqualityComparer<T>.Default;
+ }
+
+ public bool Equals(HashSet<T> x, HashSet<T> y) {
+ if (x == y) {
+ return true;
+ } else if (x == null || y == null || x.Count != y.Count) {
+ return false;
+ }
+
+ foreach (T value in x) {
+ if (!y.Contains(value)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int GetHashCode(HashSet<T> obj) {
+ int res = 6551;
+ if (obj != null) {
+ foreach (T t in obj) {
+ res = res ^ _comparer.GetHashCode(t);
+ }
+ }
+
+ return res;
+ }
+ }
+#else
+ public static IEqualityComparer<HashSet<T>> CreateSetComparer<T>() {
+ return HashSet<T>.CreateSetComparer();
+ }
+#endif
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ContractUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ContractUtils.cs
new file mode 100644
index 00000000000..53a9ea256fd
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ContractUtils.cs
@@ -0,0 +1,233 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Microsoft.Scripting.Utils {
+ public static class ContractUtils {
+ [Conditional("DEBUG")]
+ public static void Assert(bool precondition) {
+ Debug.Assert(precondition);
+ }
+
+ public static void Requires(bool precondition) {
+ if (!precondition) {
+ throw new ArgumentException(Strings.MethodPreconditionViolated);
+ }
+ }
+
+ public static void Requires(bool precondition, string paramName) {
+ Utils.Assert.NotEmpty(paramName);
+
+ if (!precondition) {
+ throw new ArgumentException(Strings.InvalidArgumentValue, paramName);
+ }
+ }
+
+ public static void Requires(bool precondition, string paramName, string message) {
+ Utils.Assert.NotEmpty(paramName);
+
+ if (!precondition) {
+ throw new ArgumentException(message, paramName);
+ }
+ }
+
+ public static void RequiresNotNull(object value, string paramName) {
+ Utils.Assert.NotEmpty(paramName);
+
+ if (value == null) {
+ throw new ArgumentNullException(paramName);
+ }
+ }
+
+ public static void RequiresNotEmpty(string str, string paramName) {
+ RequiresNotNull(str, paramName);
+ if (str.Length == 0) {
+ throw new ArgumentException(Strings.NonEmptyStringRequired, paramName);
+ }
+ }
+
+ public 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 specified index to point inside the array.
+ /// </summary>
+ /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
+ public static void RequiresArrayIndex<T>(IList<T> array, int index, string indexName) {
+ RequiresArrayIndex(array.Count, index, indexName);
+ }
+
+ /// <summary>
+ /// Requires the specified index to point inside the array.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
+ public static void RequiresArrayIndex(int arraySize, int index, string indexName) {
+ Utils.Assert.NotEmpty(indexName);
+ Debug.Assert(arraySize >= 0);
+
+ if (index < 0 || index >= arraySize) throw new ArgumentOutOfRangeException(indexName);
+ }
+
+ /// <summary>
+ /// Requires the specified index to point inside the array or at the end
+ /// </summary>
+ /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
+ public static void RequiresArrayInsertIndex<T>(IList<T> array, int index, string indexName) {
+ RequiresArrayInsertIndex(array.Count, index, indexName);
+ }
+
+ /// <summary>
+ /// Requires the specified index to point inside the array or at the end
+ /// </summary>
+ /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
+ public static void RequiresArrayInsertIndex(int arraySize, int index, string indexName) {
+ Utils.Assert.NotEmpty(indexName);
+ Debug.Assert(arraySize >= 0);
+
+ if (index < 0 || index > arraySize) throw new ArgumentOutOfRangeException(indexName);
+ }
+
+ /// <summary>
+ /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
+ public static void RequiresArrayRange<T>(IList<T> array, int offset, int count, string offsetName, string countName) {
+ Utils.Assert.NotNull(array);
+ RequiresArrayRange(array.Count, offset, count, offsetName, countName);
+ }
+
+ /// <summary>
+ /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
+ public static void RequiresArrayRange(int arraySize, int offset, int count, string offsetName, string countName) {
+ Utils.Assert.NotEmpty(offsetName);
+ Utils.Assert.NotEmpty(countName);
+ Debug.Assert(arraySize >= 0);
+
+ if (count < 0) throw new ArgumentOutOfRangeException(countName);
+ if (offset < 0 || arraySize - offset < count) throw new ArgumentOutOfRangeException(offsetName);
+ }
+
+
+ /// <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>
+ public static void RequiresListRange(IList array, int offset, int count, string offsetName, string countName) {
+ Utils.Assert.NotEmpty(offsetName);
+ Utils.Assert.NotEmpty(countName);
+ Utils.Assert.NotNull(array);
+
+ if (count < 0) throw new ArgumentOutOfRangeException(countName);
+ if (offset < 0 || array.Count - offset < count) throw new ArgumentOutOfRangeException(offsetName);
+ }
+
+ /// <summary>
+ /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
+ /// </summary>
+ /// <exception cref="ArgumentNullException">String is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
+ public static void RequiresArrayRange(string str, int offset, int count, string offsetName, string countName) {
+ Utils.Assert.NotEmpty(offsetName);
+ Utils.Assert.NotEmpty(countName);
+ Utils.Assert.NotNull(str);
+
+ if (count < 0) throw new ArgumentOutOfRangeException(countName);
+ if (offset < 0 || str.Length - offset < count) throw new ArgumentOutOfRangeException(offsetName);
+ }
+
+ /// <summary>
+ /// Requires the array and all its items to be non-null.
+ /// </summary>
+ public static void RequiresNotNullItems<T>(IList<T> array, string arrayName) {
+ Utils.Assert.NotNull(arrayName);
+ RequiresNotNull(array, arrayName);
+
+ for (int i = 0; i < array.Count; i++) {
+ if (array[i] == null) {
+ throw ExceptionUtils.MakeArgumentItemNullException(i, arrayName);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Requires the enumerable collection and all its items to be non-null.
+ /// </summary>
+ public static void RequiresNotNullItems<T>(IEnumerable<T> collection, string collectionName) {
+ Utils.Assert.NotNull(collectionName);
+ RequiresNotNull(collection, collectionName);
+
+ int i = 0;
+ foreach (var item in collection) {
+ if (item == null) {
+ throw ExceptionUtils.MakeArgumentItemNullException(i, collectionName);
+ }
+ i++;
+ }
+ }
+
+ [Conditional("FALSE")]
+ public static void Invariant(bool condition) {
+ Debug.Assert(condition);
+ }
+
+ [Conditional("FALSE")]
+ public static void Invariant(bool condition, string message) {
+ Debug.Assert(condition, message);
+ }
+
+ [Conditional("FALSE")]
+ public static void Ensures(bool condition) {
+ // nop
+ }
+
+ [Conditional("FALSE")]
+ public static void Ensures(bool condition, string message) {
+ // nop
+ }
+
+ public static T Result<T>() {
+ return default(T);
+ }
+
+ public static T Parameter<T>(out T value) {
+ value = default(T);
+ return value;
+ }
+
+ public static T Old<T>(T value) {
+ return value;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/DynamicUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/DynamicUtils.cs
new file mode 100644
index 00000000000..3c8e955c587
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/DynamicUtils.cs
@@ -0,0 +1,297 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_TASKS
+using System.Threading.Tasks;
+#endif
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Dynamic;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Interpreter;
+using Microsoft.Scripting.Runtime;
+
+#if !FEATURE_DYNAMIC_EXPRESSION_VISITOR
+#if FEATURE_CORE_DLR
+namespace System.Linq.Expressions {
+#else
+namespace Microsoft.Scripting.Ast {
+#endif
+ public abstract class DynamicExpressionVisitor : ExpressionVisitor {
+ }
+}
+#endif
+
+namespace Microsoft.Scripting.Utils {
+ using AstUtils = Microsoft.Scripting.Ast.Utils;
+
+ public static class DynamicUtils {
+ /// <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>
+ public 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];
+ res[i] = mo != null ? mo.Expression : null;
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Creates an instance of <see cref="DynamicMetaObject"/> for a runtime value and the expression that represents it during the binding process.
+ /// </summary>
+ /// <param name="argValue">The runtime value to be represented by the <see cref="DynamicMetaObject"/>.</param>
+ /// <param name="parameterExpression">An expression to represent this <see cref="DynamicMetaObject"/> during the binding process.</param>
+ /// <returns>The new instance of <see cref="DynamicMetaObject"/>.</returns>
+ public static DynamicMetaObject ObjectToMetaObject(object argValue, Expression parameterExpression) {
+ IDynamicMetaObjectProvider ido = argValue as IDynamicMetaObjectProvider;
+ if (ido != null) {
+ return ido.GetMetaObject(parameterExpression);
+ } else {
+ return new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty, argValue);
+ }
+ }
+
+ /// <summary>
+ /// Produces an interpreted binding using the given binder which falls over to a compiled
+ /// binding after hitCount tries.
+ ///
+ /// This method should be called whenever an interpreted binding is required. Sometimes it will
+ /// return a compiled binding if a previous binding was produced and it's hit count was exhausted.
+ /// In this case the binder will not be called back for a new binding - the previous one will
+ /// be used.
+ /// </summary>
+ /// <typeparam name="T">The delegate type being used for the call site</typeparam>
+ /// <param name="binder">The binder used for the call site</param>
+ /// <param name="compilationThreshold">The number of calls before the binder should switch to a compiled mode.</param>
+ /// <param name="args">The arguments that are passed for the binding (as received in a BindDelegate call)</param>
+ /// <returns>A delegate which represents the interpreted binding.</returns>
+ public static T/*!*/ LightBind<T>(this DynamicMetaObjectBinder/*!*/ binder, object[]/*!*/ args, int compilationThreshold) where T : class {
+ ContractUtils.RequiresNotNull(binder, "binder");
+ ContractUtils.RequiresNotNull(args, "args");
+
+ return GenericInterpretedBinder<T>.Instance.Bind(binder, compilationThreshold < 0 ? LightCompiler.DefaultCompilationThreshold : compilationThreshold, args);
+ }
+
+ private class GenericInterpretedBinder<T> where T : class {
+ public static GenericInterpretedBinder<T>/*!*/ Instance = new GenericInterpretedBinder<T>();
+ private readonly ReadOnlyCollection<ParameterExpression>/*!*/ _parameters;
+ private readonly Expression/*!*/ _updateExpression;
+
+ private GenericInterpretedBinder() {
+ var invokeMethod = typeof(T).GetMethod("Invoke");
+ var methodParams = invokeMethod.GetParameters();
+
+ ReadOnlyCollectionBuilder<ParameterExpression> prms = new ReadOnlyCollectionBuilder<ParameterExpression>(methodParams.Length);
+ ReadOnlyCollectionBuilder<Expression> invokePrms = new ReadOnlyCollectionBuilder<Expression>(methodParams.Length);
+ for (int i = 0; i < methodParams.Length; i++) {
+ var param = Expression.Parameter(methodParams[i].ParameterType);
+ if (i == 0) {
+ invokePrms.Add(Expression.Convert(param, typeof(CallSite<T>)));
+ } else {
+ invokePrms.Add(param);
+ }
+ prms.Add(param);
+ }
+
+ _parameters = prms.ToReadOnlyCollection();
+
+ _updateExpression = Expression.Block(
+ Expression.Label(CallSiteBinder.UpdateLabel),
+ Expression.Invoke(
+ Expression.Property(
+ invokePrms[0],
+ typeof(CallSite<T>).GetDeclaredProperty("Update")
+ ),
+ invokePrms.ToReadOnlyCollection()
+ )
+ );
+ }
+
+ public T/*!*/ Bind(DynamicMetaObjectBinder/*!*/ binder, int compilationThreshold, object[] args) {
+ if (CachedBindingInfo<T>.LastInterpretedFailure != null && CachedBindingInfo<T>.LastInterpretedFailure.Binder == binder) {
+ // we failed the rule because we have a compiled target available, return the compiled target
+ Debug.Assert(CachedBindingInfo<T>.LastInterpretedFailure.CompiledTarget != null);
+ var res = CachedBindingInfo<T>.LastInterpretedFailure.CompiledTarget;
+ CachedBindingInfo<T>.LastInterpretedFailure = null;
+ return res;
+ }
+
+ // we haven't produced a rule yet....
+ var bindingInfo = new CachedBindingInfo<T>(binder, compilationThreshold);
+
+ var targetMO = DynamicMetaObject.Create(args[0], _parameters[1]); // 1 is skipping CallSite
+ DynamicMetaObject[] argsMO = new DynamicMetaObject[args.Length - 1];
+ for (int i = 0; i < argsMO.Length; i++) {
+ argsMO[i] = DynamicMetaObject.Create(args[i + 1], _parameters[i + 2]);
+ }
+ var binding = binder.Bind(targetMO, argsMO);
+
+ return CreateDelegate(binding, bindingInfo);
+ }
+
+ private T/*!*/ CreateDelegate(DynamicMetaObject/*!*/ binding, CachedBindingInfo<T>/*!*/ bindingInfo) {
+ return Compile(binding, bindingInfo).LightCompile(Int32.MaxValue);
+ }
+
+ private Expression<T>/*!*/ Compile(DynamicMetaObject/*!*/ obj, CachedBindingInfo<T>/*!*/ bindingInfo) {
+ var restrictions = obj.Restrictions.ToExpression();
+
+ var body = Expression.Condition(
+ new InterpretedRuleHitCheckExpression(restrictions, bindingInfo),
+ AstUtils.Convert(obj.Expression, _updateExpression.Type),
+ _updateExpression
+ );
+
+ var res = Expression.Lambda<T>(
+ body,
+ "CallSite.Target",
+ true, // always compile the rules with tail call optimization
+ _parameters
+ );
+
+ bindingInfo.Target = res;
+ return res;
+ }
+
+ /// <summary>
+ /// Expression which reduces to the normal test but under the interpreter adds a count down
+ /// check which enables compiling when the count down is reached.
+ /// </summary>
+ class InterpretedRuleHitCheckExpression : Expression, IInstructionProvider {
+ private readonly Expression/*!*/ _test;
+ private readonly CachedBindingInfo/*!*/ _bindingInfo;
+
+ private static readonly MethodInfo InterpretedCallSiteTest = typeof(ScriptingRuntimeHelpers).GetMethod("InterpretedCallSiteTest");
+ public InterpretedRuleHitCheckExpression(Expression/*!*/ test, CachedBindingInfo/*!*/ bindingInfo) {
+ Assert.NotNull(test, bindingInfo);
+
+ _test = test;
+ _bindingInfo = bindingInfo;
+ }
+
+ public override Expression Reduce() {
+ return _test;
+ }
+
+ protected override Expression VisitChildren(ExpressionVisitor visitor) {
+ var test = visitor.Visit(_test);
+ if (test != _test) {
+ return new InterpretedRuleHitCheckExpression(test, _bindingInfo);
+ }
+ return this;
+ }
+
+ public override bool CanReduce {
+ get { return true; }
+ }
+
+ public override ExpressionType NodeType {
+ get { return ExpressionType.Extension; }
+ }
+
+ public override Type Type {
+ get { return typeof(bool); }
+ }
+
+ #region IInstructionProvider Members
+
+ public void AddInstructions(LightCompiler compiler) {
+ compiler.Compile(_test);
+ compiler.Instructions.EmitLoad(_bindingInfo);
+ compiler.EmitCall(InterpretedCallSiteTest);
+ }
+
+ #endregion
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Base class for storing information about the binding that a specific rule is applicable for.
+ ///
+ /// We have a derived generic class but this class enables us to refer to it w/o having the
+ /// generic type information around.
+ ///
+ /// This class tracks both the count down to when we should compile. When we compile we
+ /// take the Expression[T] that was used before and compile it. While this is happening
+ /// we continue to allow the interpreted code to run. When the compilation is complete we
+ /// store a thread static which tells us what binding failed and the current rule is no
+ /// longer functional. Finally the language binder will call us again and we'll retrieve
+ /// and return the compiled overload.
+ /// </summary>
+ abstract class CachedBindingInfo {
+ public readonly DynamicMetaObjectBinder/*!*/ Binder;
+ public int CompilationThreshold;
+
+ public CachedBindingInfo(DynamicMetaObjectBinder binder, int compilationThreshold) {
+ Binder = binder;
+ CompilationThreshold = compilationThreshold;
+ }
+
+ public abstract bool CheckCompiled();
+ }
+
+ class CachedBindingInfo<T> : CachedBindingInfo where T : class {
+ public T CompiledTarget;
+ public Expression<T> Target;
+
+ [ThreadStatic]
+ public static CachedBindingInfo<T> LastInterpretedFailure;
+
+ public CachedBindingInfo(DynamicMetaObjectBinder binder, int compilationThreshold)
+ : base(binder, compilationThreshold) {
+ }
+
+ public override bool CheckCompiled() {
+ if (Target != null) {
+ // start compiling the target if no one else has
+ var lambda = Interlocked.Exchange(ref Target, null);
+ if (lambda != null) {
+#if FEATURE_TASKS
+ new Task(() => { CompiledTarget = lambda.Compile(); }).Start();
+#else
+ ThreadPool.QueueUserWorkItem(x => { CompiledTarget = lambda.Compile(); });
+#endif
+ }
+ }
+
+ if (CompiledTarget != null) {
+ LastInterpretedFailure = this;
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionFactory.Generated.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionFactory.Generated.cs
new file mode 100644
index 00000000000..1214351549a
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionFactory.Generated.cs
@@ -0,0 +1,1050 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+
+namespace Microsoft.Scripting {
+
+ 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 Microsoft.Scripting Exception Factory
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_expr_factory_scripting from: generate_exception_factory.py
+
+ /// <summary>
+ /// Strongly-typed and parameterized string factory.
+ /// </summary>
+
+ internal static partial class Strings {
+ /// <summary>
+ /// A string like "Cannot access member {1} declared on type {0} because the type contains generic parameters."
+ /// </summary>
+ internal static string InvalidOperation_ContainsGenericParameters(object p0, object p1) {
+ return FormatString("Cannot access member {1} declared on type {0} because the type contains generic parameters.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Type '{0}' is missing or cannot be loaded."
+ /// </summary>
+ internal static string MissingType(object p0) {
+ return FormatString("Type '{0}' is missing or cannot be loaded.", p0);
+ }
+
+ /// <summary>
+ /// A string like "static property "{0}" of "{1}" can only be read through a type, not an instance"
+ /// </summary>
+ internal static string StaticAccessFromInstanceError(object p0, object p1) {
+ return FormatString("static property \"{0}\" of \"{1}\" can only be read through a type, not an instance", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "static property "{0}" of "{1}" can only be assigned to through a type, not an instance"
+ /// </summary>
+ internal static string StaticAssignmentFromInstanceError(object p0, object p1) {
+ return FormatString("static property \"{0}\" of \"{1}\" can only be assigned to through a type, not an instance", p0, p1);
+ }
+
+ /// <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 string required"
+ /// </summary>
+ internal static string NonEmptyStringRequired {
+ get {
+ return "Non-empty string required";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Non-empty collection required"
+ /// </summary>
+ internal static string NonEmptyCollectionRequired {
+ get {
+ return "Non-empty collection required";
+ }
+ }
+
+ /// <summary>
+ /// A string like "must by an Exception instance"
+ /// </summary>
+ internal static string MustBeExceptionInstance {
+ get {
+ return "must by an Exception instance";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type of test must be bool"
+ /// </summary>
+ internal static string TypeOfTestMustBeBool {
+ get {
+ return "Type of test must be bool";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type of the expression must be bool"
+ /// </summary>
+ internal static string TypeOfExpressionMustBeBool {
+ get {
+ return "Type of the expression must be bool";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Empty string is not a valid path."
+ /// </summary>
+ internal static string EmptyStringIsInvalidPath {
+ get {
+ return "Empty string is not a valid path.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid delegate type (Invoke method not found)."
+ /// </summary>
+ internal static string InvalidDelegate {
+ get {
+ return "Invalid delegate type (Invoke method not found).";
+ }
+ }
+
+ /// <summary>
+ /// A string like "expected only static property"
+ /// </summary>
+ internal static string ExpectedStaticProperty {
+ get {
+ return "expected only static property";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Property doesn't exist on the provided type"
+ /// </summary>
+ internal static string PropertyDoesNotExist {
+ get {
+ return "Property doesn't exist on the provided type";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Field doesn't exist on provided type"
+ /// </summary>
+ internal static string FieldDoesNotExist {
+ get {
+ return "Field doesn't exist on provided type";
+ }
+ }
+
+ /// <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 "Type doesn't have a method with a given name."
+ /// </summary>
+ internal static string TypeDoesNotHaveMethodForName {
+ get {
+ return "Type doesn't have a method with a given name.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Type doesn't have a method with a given name and signature."
+ /// </summary>
+ internal static string TypeDoesNotHaveMethodForNameSignature {
+ get {
+ return "Type doesn't have a method with a given name and 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 "Either code or target must be specified."
+ /// </summary>
+ internal static string MustHaveCodeOrTarget {
+ get {
+ return "Either code or target must be specified.";
+ }
+ }
+
+ /// <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 "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 "unknown member type: '{0}'. "
+ /// </summary>
+ internal static string UnknownMemberType(object p0) {
+ return FormatString("unknown member type: '{0}'. ", p0);
+ }
+
+ /// <summary>
+ /// A string like "RuleBuilder can only be used with delegates whose first argument is CallSite."
+ /// </summary>
+ internal static string FirstArgumentMustBeCallSite {
+ get {
+ return "RuleBuilder can only be used with delegates whose first argument is CallSite.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "no instance for call."
+ /// </summary>
+ internal static string NoInstanceForCall {
+ get {
+ return "no instance for call.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Missing Test."
+ /// </summary>
+ internal static string MissingTest {
+ get {
+ return "Missing Test.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Missing Target."
+ /// </summary>
+ internal static string MissingTarget {
+ get {
+ return "Missing Target.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "The operation requires a non-generic type for {0}, but this represents generic types only"
+ /// </summary>
+ internal static string NonGenericWithGenericGroup(object p0) {
+ return FormatString("The operation requires a non-generic type for {0}, but this represents generic types only", p0);
+ }
+
+ /// <summary>
+ /// A string like "Invalid operation: '{0}'"
+ /// </summary>
+ internal static string InvalidOperation(object p0) {
+ return FormatString("Invalid operation: '{0}'", p0);
+ }
+
+ /// <summary>
+ /// A string like "Finally already defined."
+ /// </summary>
+ internal static string FinallyAlreadyDefined {
+ get {
+ return "Finally already defined.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Can not have fault and finally."
+ /// </summary>
+ internal static string CannotHaveFaultAndFinally {
+ get {
+ return "Can not have fault and finally.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Fault already defined."
+ /// </summary>
+ internal static string FaultAlreadyDefined {
+ get {
+ return "Fault already defined.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot create default value for type {0}."
+ /// </summary>
+ internal static string CantCreateDefaultTypeFor(object p0) {
+ return FormatString("Cannot create default value for 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 "{0}.{1} has no publiclly visible method."
+ /// </summary>
+ internal static string NoCallableMethods(object p0, object p1) {
+ return FormatString("{0}.{1} has no publiclly visible method.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Global/top-level local variable names must be unique."
+ /// </summary>
+ internal static string GlobalsMustBeUnique {
+ get {
+ return "Global/top-level local variable names must be unique.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Generating code from non-serializable CallSiteBinder."
+ /// </summary>
+ internal static string GenNonSerializableBinder {
+ get {
+ return "Generating code from non-serializable CallSiteBinder.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "pecified path is invalid."
+ /// </summary>
+ internal static string InvalidPath {
+ get {
+ return "pecified path is invalid.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Dictionaries are not hashable."
+ /// </summary>
+ internal static string DictionaryNotHashable {
+ get {
+ return "Dictionaries are not hashable.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "language already registered."
+ /// </summary>
+ internal static string LanguageRegistered {
+ get {
+ return "language already registered.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "The method or operation is not implemented."
+ /// </summary>
+ internal static string MethodOrOperatorNotImplemented {
+ get {
+ return "The method or operation is not implemented.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "No exception."
+ /// </summary>
+ internal static string NoException {
+ get {
+ return "No exception.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Extension type {0} must be public."
+ /// </summary>
+ internal static string ExtensionMustBePublic(object p0) {
+ return FormatString("Extension type {0} must be public.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Already initialized."
+ /// </summary>
+ internal static string AlreadyInitialized {
+ get {
+ return "Already initialized.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "CreateScopeExtension must return a scope extension."
+ /// </summary>
+ internal static string MustReturnScopeExtension {
+ get {
+ return "CreateScopeExtension must return a scope extension.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid number of parameters for the service."
+ /// </summary>
+ internal static string InvalidParamNumForService {
+ get {
+ return "Invalid number of parameters for the service.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid type of argument {0}; expecting {1}."
+ /// </summary>
+ internal static string InvalidArgumentType(object p0, object p1) {
+ return FormatString("Invalid type of argument {0}; expecting {1}.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "Cannot change non-caching value."
+ /// </summary>
+ internal static string CannotChangeNonCachingValue {
+ get {
+ return "Cannot change non-caching value.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Field {0} is read-only"
+ /// </summary>
+ internal static string FieldReadonly(object p0) {
+ return FormatString("Field {0} is read-only", p0);
+ }
+
+ /// <summary>
+ /// A string like "Property {0} is read-only"
+ /// </summary>
+ internal static string PropertyReadonly(object p0) {
+ return FormatString("Property {0} is read-only", p0);
+ }
+
+ /// <summary>
+ /// A string like "Expected event from {0}.{1}, got event from {2}.{3}."
+ /// </summary>
+ internal static string UnexpectedEvent(object p0, object p1, object p2, object p3) {
+ return FormatString("Expected event from {0}.{1}, got event from {2}.{3}.", p0, p1, p2, p3);
+ }
+
+ /// <summary>
+ /// A string like "expected bound event, got {0}."
+ /// </summary>
+ internal static string ExpectedBoundEvent(object p0) {
+ return FormatString("expected bound event, got {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Expected type {0}, got {1}."
+ /// </summary>
+ internal static string UnexpectedType(object p0, object p1) {
+ return FormatString("Expected type {0}, got {1}.", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "can only write to member {0}."
+ /// </summary>
+ internal static string MemberWriteOnly(object p0) {
+ return FormatString("can only write to member {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "No code to compile."
+ /// </summary>
+ internal static string NoCodeToCompile {
+ get {
+ return "No code to compile.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Invalid stream type: {0}."
+ /// </summary>
+ internal static string InvalidStreamType(object p0) {
+ return FormatString("Invalid stream type: {0}.", p0);
+ }
+
+ /// <summary>
+ /// A string like "Queue empty."
+ /// </summary>
+ internal static string QueueEmpty {
+ get {
+ return "Queue empty.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Enumeration has not started. Call MoveNext."
+ /// </summary>
+ internal static string EnumerationNotStarted {
+ get {
+ return "Enumeration has not started. Call MoveNext.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Enumeration already finished."
+ /// </summary>
+ internal static string EnumerationFinished {
+ get {
+ return "Enumeration already finished.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "can't add another casing for identifier {0}"
+ /// </summary>
+ internal static string CantAddCasing(object p0) {
+ return FormatString("can't add another casing for identifier {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "can't add new identifier {0}"
+ /// </summary>
+ internal static string CantAddIdentifier(object p0) {
+ return FormatString("can't add new identifier {0}", p0);
+ }
+
+ /// <summary>
+ /// A string like "Type '{0}' doesn't provide a suitable public constructor or its implementation is faulty: {1}"
+ /// </summary>
+ internal static string InvalidCtorImplementation(object p0, object p1) {
+ return FormatString("Type '{0}' doesn't provide a suitable public constructor or its implementation is faulty: {1}", p0, p1);
+ }
+
+ /// <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 "Cannot emit constant {0} ({1})"
+ /// </summary>
+ internal static string CanotEmitConstant(object p0, object p1) {
+ return FormatString("Cannot emit constant {0} ({1})", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "No implicit cast from {0} to {1}"
+ /// </summary>
+ internal static string NoImplicitCast(object p0, object p1) {
+ return FormatString("No implicit cast from {0} to {1}", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "No explicit cast from {0} to {1}"
+ /// </summary>
+ internal static string NoExplicitCast(object p0, object p1) {
+ return FormatString("No explicit cast from {0} to {1}", p0, p1);
+ }
+
+ /// <summary>
+ /// A string like "name '{0}' not defined"
+ /// </summary>
+ internal static string NameNotDefined(object p0) {
+ return FormatString("name '{0}' not defined", p0);
+ }
+
+ /// <summary>
+ /// A string like "No default value for a given type."
+ /// </summary>
+ internal static string NoDefaultValue {
+ get {
+ return "No default value for a given type.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Specified language provider type is not registered."
+ /// </summary>
+ internal static string UnknownLanguageProviderType {
+ get {
+ return "Specified language provider type is not registered.";
+ }
+ }
+
+ /// <summary>
+ /// A string like "can't read from property"
+ /// </summary>
+ internal static string CantReadProperty {
+ get {
+ return "can't read from property";
+ }
+ }
+
+ /// <summary>
+ /// A string like "can't write to property"
+ /// </summary>
+ internal static string CantWriteProperty {
+ get {
+ return "can't write to property";
+ }
+ }
+
+ /// <summary>
+ /// A string like "Cannot create instance of {0} because it contains generic parameters"
+ /// </summary>
+ internal static string IllegalNew_GenericParams(object p0) {
+ return FormatString("Cannot create instance of {0} because it contains generic parameters", p0);
+ }
+
+ /// <summary>
+ /// A string like "Non-verifiable assembly generated: {0}:\nAssembly preserved as {1}\nError text:\n{2}\n"
+ /// </summary>
+ internal static string VerificationException(object p0, object p1, object p2) {
+ return FormatString("Non-verifiable assembly generated: {0}:\nAssembly preserved as {1}\nError text:\n{2}\n", p0, p1, p2);
+ }
+
+ }
+ /// <summary>
+ /// Strongly-typed and parameterized exception factory.
+ /// </summary>
+
+ internal static partial class Error {
+ /// <summary>
+ /// ArgumentException with message like "Either code or target must be specified."
+ /// </summary>
+ internal static Exception MustHaveCodeOrTarget() {
+ return new ArgumentException(Strings.MustHaveCodeOrTarget);
+ }
+
+ /// <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 "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>
+ /// InvalidOperationException with message like "unknown member type: '{0}'. "
+ /// </summary>
+ internal static Exception UnknownMemberType(object p0) {
+ return new InvalidOperationException(Strings.UnknownMemberType(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "RuleBuilder can only be used with delegates whose first argument is CallSite."
+ /// </summary>
+ internal static Exception FirstArgumentMustBeCallSite() {
+ return new InvalidOperationException(Strings.FirstArgumentMustBeCallSite);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "no instance for call."
+ /// </summary>
+ internal static Exception NoInstanceForCall() {
+ return new InvalidOperationException(Strings.NoInstanceForCall);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Missing Test."
+ /// </summary>
+ internal static Exception MissingTest() {
+ return new InvalidOperationException(Strings.MissingTest);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Missing Target."
+ /// </summary>
+ internal static Exception MissingTarget() {
+ return new InvalidOperationException(Strings.MissingTarget);
+ }
+
+ /// <summary>
+ /// TypeLoadException with message like "The operation requires a non-generic type for {0}, but this represents generic types only"
+ /// </summary>
+ internal static Exception NonGenericWithGenericGroup(object p0) {
+ return new TypeLoadException(Strings.NonGenericWithGenericGroup(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid operation: '{0}'"
+ /// </summary>
+ internal static Exception InvalidOperation(object p0) {
+ return new ArgumentException(Strings.InvalidOperation(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Finally already defined."
+ /// </summary>
+ internal static Exception FinallyAlreadyDefined() {
+ return new InvalidOperationException(Strings.FinallyAlreadyDefined);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Can not have fault and finally."
+ /// </summary>
+ internal static Exception CannotHaveFaultAndFinally() {
+ return new InvalidOperationException(Strings.CannotHaveFaultAndFinally);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Fault already defined."
+ /// </summary>
+ internal static Exception FaultAlreadyDefined() {
+ return new InvalidOperationException(Strings.FaultAlreadyDefined);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Cannot create default value for type {0}."
+ /// </summary>
+ internal static Exception CantCreateDefaultTypeFor(object p0) {
+ return new ArgumentException(Strings.CantCreateDefaultTypeFor(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Unhandled convert: {0}"
+ /// </summary>
+ internal static Exception UnhandledConvert(object p0) {
+ return new ArgumentException(Strings.UnhandledConvert(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "{0}.{1} has no publiclly visible method."
+ /// </summary>
+ internal static Exception NoCallableMethods(object p0, object p1) {
+ return new InvalidOperationException(Strings.NoCallableMethods(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Global/top-level local variable names must be unique."
+ /// </summary>
+ internal static Exception GlobalsMustBeUnique() {
+ return new ArgumentException(Strings.GlobalsMustBeUnique);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Generating code from non-serializable CallSiteBinder."
+ /// </summary>
+ internal static Exception GenNonSerializableBinder() {
+ return new ArgumentException(Strings.GenNonSerializableBinder);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "pecified path is invalid."
+ /// </summary>
+ internal static Exception InvalidPath() {
+ return new ArgumentException(Strings.InvalidPath);
+ }
+
+ /// <summary>
+ /// ArgumentTypeException with message like "Dictionaries are not hashable."
+ /// </summary>
+ internal static Exception DictionaryNotHashable() {
+ return new ArgumentTypeException(Strings.DictionaryNotHashable);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "language already registered."
+ /// </summary>
+ internal static Exception LanguageRegistered() {
+ return new InvalidOperationException(Strings.LanguageRegistered);
+ }
+
+ /// <summary>
+ /// NotImplementedException with message like "The method or operation is not implemented."
+ /// </summary>
+ internal static Exception MethodOrOperatorNotImplemented() {
+ return new NotImplementedException(Strings.MethodOrOperatorNotImplemented);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No exception."
+ /// </summary>
+ internal static Exception NoException() {
+ return new InvalidOperationException(Strings.NoException);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Extension type {0} must be public."
+ /// </summary>
+ internal static Exception ExtensionMustBePublic(object p0) {
+ return new ArgumentException(Strings.ExtensionMustBePublic(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Already initialized."
+ /// </summary>
+ internal static Exception AlreadyInitialized() {
+ return new InvalidOperationException(Strings.AlreadyInitialized);
+ }
+
+ /// <summary>
+ /// InvalidImplementationException with message like "CreateScopeExtension must return a scope extension."
+ /// </summary>
+ internal static Exception MustReturnScopeExtension() {
+ return new InvalidImplementationException(Strings.MustReturnScopeExtension);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid number of parameters for the service."
+ /// </summary>
+ internal static Exception InvalidParamNumForService() {
+ return new ArgumentException(Strings.InvalidParamNumForService);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid type of argument {0}; expecting {1}."
+ /// </summary>
+ internal static Exception InvalidArgumentType(object p0, object p1) {
+ return new ArgumentException(Strings.InvalidArgumentType(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Cannot change non-caching value."
+ /// </summary>
+ internal static Exception CannotChangeNonCachingValue() {
+ return new ArgumentException(Strings.CannotChangeNonCachingValue);
+ }
+
+ /// <summary>
+ /// MissingMemberException with message like "Field {0} is read-only"
+ /// </summary>
+ internal static Exception FieldReadonly(object p0) {
+ return new MissingMemberException(Strings.FieldReadonly(p0));
+ }
+
+ /// <summary>
+ /// MissingMemberException with message like "Property {0} is read-only"
+ /// </summary>
+ internal static Exception PropertyReadonly(object p0) {
+ return new MissingMemberException(Strings.PropertyReadonly(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Expected event from {0}.{1}, got event from {2}.{3}."
+ /// </summary>
+ internal static Exception UnexpectedEvent(object p0, object p1, object p2, object p3) {
+ return new ArgumentException(Strings.UnexpectedEvent(p0, p1, p2, p3));
+ }
+
+ /// <summary>
+ /// ArgumentTypeException with message like "expected bound event, got {0}."
+ /// </summary>
+ internal static Exception ExpectedBoundEvent(object p0) {
+ return new ArgumentTypeException(Strings.ExpectedBoundEvent(p0));
+ }
+
+ /// <summary>
+ /// ArgumentTypeException with message like "Expected type {0}, got {1}."
+ /// </summary>
+ internal static Exception UnexpectedType(object p0, object p1) {
+ return new ArgumentTypeException(Strings.UnexpectedType(p0, p1));
+ }
+
+ /// <summary>
+ /// MemberAccessException with message like "can only write to member {0}."
+ /// </summary>
+ internal static Exception MemberWriteOnly(object p0) {
+ return new MemberAccessException(Strings.MemberWriteOnly(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "No code to compile."
+ /// </summary>
+ internal static Exception NoCodeToCompile() {
+ return new InvalidOperationException(Strings.NoCodeToCompile);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Invalid stream type: {0}."
+ /// </summary>
+ internal static Exception InvalidStreamType(object p0) {
+ return new ArgumentException(Strings.InvalidStreamType(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Queue empty."
+ /// </summary>
+ internal static Exception QueueEmpty() {
+ return new InvalidOperationException(Strings.QueueEmpty);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Enumeration has not started. Call MoveNext."
+ /// </summary>
+ internal static Exception EnumerationNotStarted() {
+ return new InvalidOperationException(Strings.EnumerationNotStarted);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "Enumeration already finished."
+ /// </summary>
+ internal static Exception EnumerationFinished() {
+ return new InvalidOperationException(Strings.EnumerationFinished);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "can't add another casing for identifier {0}"
+ /// </summary>
+ internal static Exception CantAddCasing(object p0) {
+ return new InvalidOperationException(Strings.CantAddCasing(p0));
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "can't add new identifier {0}"
+ /// </summary>
+ internal static Exception CantAddIdentifier(object p0) {
+ return new InvalidOperationException(Strings.CantAddIdentifier(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>
+ /// ArgumentException with message like "Cannot emit constant {0} ({1})"
+ /// </summary>
+ internal static Exception CanotEmitConstant(object p0, object p1) {
+ return new ArgumentException(Strings.CanotEmitConstant(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "No implicit cast from {0} to {1}"
+ /// </summary>
+ internal static Exception NoImplicitCast(object p0, object p1) {
+ return new ArgumentException(Strings.NoImplicitCast(p0, p1));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "No explicit cast from {0} to {1}"
+ /// </summary>
+ internal static Exception NoExplicitCast(object p0, object p1) {
+ return new ArgumentException(Strings.NoExplicitCast(p0, p1));
+ }
+
+ /// <summary>
+ /// MissingMemberException with message like "name '{0}' not defined"
+ /// </summary>
+ internal static Exception NameNotDefined(object p0) {
+ return new MissingMemberException(Strings.NameNotDefined(p0));
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "No default value for a given type."
+ /// </summary>
+ internal static Exception NoDefaultValue() {
+ return new ArgumentException(Strings.NoDefaultValue);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Specified language provider type is not registered."
+ /// </summary>
+ internal static Exception UnknownLanguageProviderType() {
+ return new ArgumentException(Strings.UnknownLanguageProviderType);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "can't read from property"
+ /// </summary>
+ internal static Exception CantReadProperty() {
+ return new InvalidOperationException(Strings.CantReadProperty);
+ }
+
+ /// <summary>
+ /// InvalidOperationException with message like "can't write to property"
+ /// </summary>
+ internal static Exception CantWriteProperty() {
+ return new InvalidOperationException(Strings.CantWriteProperty);
+ }
+
+ /// <summary>
+ /// ArgumentException with message like "Cannot create instance of {0} because it contains generic parameters"
+ /// </summary>
+ internal static Exception IllegalNew_GenericParams(object p0) {
+ return new ArgumentException(Strings.IllegalNew_GenericParams(p0));
+ }
+
+ /// <summary>
+ /// System.Security.VerificationException with message like "Non-verifiable assembly generated: {0}:\nAssembly preserved as {1}\nError text:\n{2}\n"
+ /// </summary>
+ internal static Exception VerificationException(object p0, object p1, object p2) {
+ return new System.Security.VerificationException(Strings.VerificationException(p0, p1, p2));
+ }
+
+ }
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionUtils.cs
new file mode 100644
index 00000000000..89449659612
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ExceptionUtils.cs
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Microsoft.Scripting.Utils {
+ public static class ExceptionUtils {
+ public static ArgumentOutOfRangeException MakeArgumentOutOfRangeException(string paramName, object actualValue, string message) {
+#if SILVERLIGHT || WP75 // ArgumentOutOfRangeException ctor overload
+ throw new ArgumentOutOfRangeException(paramName, string.Format("{0} (actual value is '{1}')", message, actualValue));
+#else
+ throw new ArgumentOutOfRangeException(paramName, actualValue, message);
+#endif
+ }
+
+ public static ArgumentNullException MakeArgumentItemNullException(int index, string arrayName) {
+ return new ArgumentNullException(String.Format("{0}[{1}]", arrayName, index));
+ }
+
+#if FEATURE_REMOTING
+ public static object GetData(this Exception e, object key) {
+ return e.Data[key];
+ }
+
+ public static void SetData(this Exception e, object key, object data) {
+ e.Data[key] = data;
+ }
+
+ public static void RemoveData(this Exception e, object key) {
+ e.Data.Remove(key);
+ }
+#else
+
+#if WP75
+ private static WeakDictionary<Exception, List<KeyValuePair<object, object>>> _exceptionData;
+#else
+ private static ConditionalWeakTable<Exception, List<KeyValuePair<object, object>>> _exceptionData;
+#endif
+
+ public static void SetData(this Exception e, object key, object value) {
+ if (_exceptionData == null) {
+#if WP75
+ Interlocked.CompareExchange(ref _exceptionData, new WeakDictionary<Exception, List<KeyValuePair<object, object>>>(), null);
+#else
+ Interlocked.CompareExchange(ref _exceptionData, new ConditionalWeakTable<Exception, List<KeyValuePair<object, object>>>(), null);
+#endif
+ }
+
+ lock (_exceptionData) {
+ var data = _exceptionData.GetOrCreateValue(e);
+
+ int index = data.FindIndex(entry => entry.Key == key);
+ if (index >= 0) {
+ data[index] = new KeyValuePair<object, object>(key, value);
+ } else {
+ data.Add(new KeyValuePair<object, object>(key, value));
+ }
+ }
+ }
+
+ public static object GetData(this Exception e, object key) {
+ if (_exceptionData == null) {
+ return null;
+ }
+
+ lock (_exceptionData) {
+ List<KeyValuePair<object, object>> data;
+ if (!_exceptionData.TryGetValue(e, out data)) {
+ return null;
+ }
+
+ return data.FirstOrDefault(entry => entry.Key == key).Value;
+ }
+ }
+
+ public static void RemoveData(this Exception e, object key) {
+ if (_exceptionData == null) {
+ return;
+ }
+
+ lock (_exceptionData) {
+ List<KeyValuePair<object, object>> data;
+ if (!_exceptionData.TryGetValue(e, out data)) {
+ return;
+ }
+
+ int index = data.FindIndex(entry => entry.Key == key);
+ if (index >= 0) {
+ data.RemoveAt(index);
+ }
+ }
+ }
+#endif
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/HybridReferenceDictionary.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/HybridReferenceDictionary.cs
new file mode 100644
index 00000000000..13b62d45f07
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/HybridReferenceDictionary.cs
@@ -0,0 +1,170 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace Microsoft.Scripting.Utils {
+ /// <summary>
+ /// A hybrid dictionary which compares based upon object identity.
+ /// </summary>
+ class HybridReferenceDictionary<TKey, TValue> where TKey : class {
+ private KeyValuePair<TKey, TValue>[] _keysAndValues;
+ private Dictionary<TKey, TValue> _dict;
+ private int _count;
+ private const int _arraySize = 10;
+
+ public HybridReferenceDictionary() {
+ }
+
+ public HybridReferenceDictionary(int initialCapicity) {
+ if (initialCapicity > _arraySize) {
+ _dict = new Dictionary<TKey, TValue>(initialCapicity);
+ } else {
+ _keysAndValues = new KeyValuePair<TKey, TValue>[initialCapicity];
+ }
+ }
+
+ public bool TryGetValue(TKey key, out TValue value) {
+ Debug.Assert(key != null);
+
+ if (_dict != null) {
+ return _dict.TryGetValue(key, out value);
+ } else if (_keysAndValues != null) {
+ for (int i = 0; i < _keysAndValues.Length; i++) {
+ if (_keysAndValues[i].Key == key) {
+ value = _keysAndValues[i].Value;
+ return true;
+ }
+ }
+ }
+ value = default(TValue);
+ return false;
+ }
+
+ public bool Remove(TKey key) {
+ Debug.Assert(key != null);
+
+ if (_dict != null) {
+ return _dict.Remove(key);
+ } else if (_keysAndValues != null) {
+ for (int i = 0; i < _keysAndValues.Length; i++) {
+ if (_keysAndValues[i].Key == key) {
+ _keysAndValues[i] = new KeyValuePair<TKey, TValue>();
+ _count--;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public bool ContainsKey(TKey key) {
+ Debug.Assert(key != null);
+
+ if (_dict != null) {
+ return _dict.ContainsKey(key);
+ } else if (_keysAndValues != null) {
+ for (int i = 0; i < _keysAndValues.Length; i++) {
+ if (_keysAndValues[i].Key == key) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public int Count {
+ get {
+ if (_dict != null) {
+ return _dict.Count;
+ }
+ return _count;
+ }
+
+ }
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
+ if (_dict != null) {
+ return _dict.GetEnumerator();
+ }
+
+ return GetEnumeratorWorker();
+ }
+
+ private IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorWorker() {
+ if (_keysAndValues != null) {
+ for (int i = 0; i < _keysAndValues.Length; i++) {
+ if (_keysAndValues[i].Key != null) {
+ yield return _keysAndValues[i];
+ }
+ }
+ }
+ }
+
+ public TValue this[TKey key] {
+ get {
+ Debug.Assert(key != null);
+
+ TValue res;
+ if (TryGetValue(key, out res)) {
+ return res;
+ }
+
+ throw new KeyNotFoundException();
+ }
+ set {
+ Debug.Assert(key != null);
+
+ if (_dict != null) {
+ _dict[key] = value;
+ } else {
+ int index;
+ if (_keysAndValues != null) {
+ index = -1;
+ for (int i = 0; i < _keysAndValues.Length; i++) {
+ if (_keysAndValues[i].Key == key) {
+ _keysAndValues[i] = new KeyValuePair<TKey, TValue>(key, value);
+ return;
+ } else if (_keysAndValues[i].Key == null) {
+ index = i;
+ }
+ }
+ } else {
+ _keysAndValues = new KeyValuePair<TKey, TValue>[_arraySize];
+ index = 0;
+ }
+
+ if (index != -1) {
+ _count++;
+ _keysAndValues[index] = new KeyValuePair<TKey, TValue>(key, value);
+ } else {
+ _dict = new Dictionary<TKey, TValue>();
+ for (int i = 0; i < _keysAndValues.Length; i++) {
+ _dict[_keysAndValues[i].Key] = _keysAndValues[i].Value;
+ }
+ _keysAndValues = null;
+
+ _dict[key] = value;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ListEqualityComparer.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ListEqualityComparer.cs
new file mode 100644
index 00000000000..3d04b8f27f3
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ListEqualityComparer.cs
@@ -0,0 +1,34 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System.Collections.Generic;
+
+namespace Microsoft.Scripting.Utils {
+ // Compares two ICollection<T>'s using element equality
+ internal sealed class ListEqualityComparer<T> : EqualityComparer<ICollection<T>> {
+ internal static readonly ListEqualityComparer<T> Instance = new ListEqualityComparer<T>();
+
+ private ListEqualityComparer() { }
+
+ // EqualityComparer<T> handles null and object identity for us
+ public override bool Equals(ICollection<T> x, ICollection<T> y) {
+ return x.ListEquals(y);
+ }
+
+ public override int GetHashCode(ICollection<T> obj) {
+ return obj.ListHashCode();
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/MathUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/MathUtils.cs
new file mode 100644
index 00000000000..3b164273526
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/MathUtils.cs
@@ -0,0 +1,1229 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_NUMERICS
+using BigInt = System.Numerics.BigInteger;
+using Complex = System.Numerics.Complex;
+#endif
+
+using System;
+using System.Text;
+using System.Collections.Generic;
+using Microsoft.Scripting.Math;
+using Microsoft.Scripting.Runtime;
+
+namespace Microsoft.Scripting.Utils {
+ using Math = System.Math;
+
+ public static class MathUtils {
+ /// <summary>
+ /// Calculates the quotient of two 32-bit signed integers rounded towards negative infinity.
+ /// </summary>
+ /// <param name="x">Dividend.</param>
+ /// <param name="y">Divisor.</param>
+ /// <returns>The quotient of the specified numbers rounded towards negative infinity, or <code>(int)Floor((double)x/(double)y)</code>.</returns>
+ /// <exception cref="DivideByZeroException"><paramref name="y"/> is 0.</exception>
+ /// <remarks>The caller must check for overflow (x = Int32.MinValue, y = -1)</remarks>
+ public static int FloorDivideUnchecked(int x, int y) {
+ int q = x / y;
+
+ if (x >= 0) {
+ if (y > 0) {
+ return q;
+ } else if (x % y == 0) {
+ return q;
+ } else {
+ return q - 1;
+ }
+ } else {
+ if (y > 0) {
+ if (x % y == 0) {
+ return q;
+ } else {
+ return q - 1;
+ }
+ } else {
+ return q;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculates the quotient of two 32-bit signed integers rounded towards negative infinity.
+ /// </summary>
+ /// <param name="x">Dividend.</param>
+ /// <param name="y">Divisor.</param>
+ /// <returns>The quotient of the specified numbers rounded towards negative infinity, or <code>(int)Floor((double)x/(double)y)</code>.</returns>
+ /// <exception cref="DivideByZeroException"><paramref name="y"/> is 0.</exception>
+ /// <remarks>The caller must check for overflow (x = Int64.MinValue, y = -1)</remarks>
+ public static long FloorDivideUnchecked(long x, long y) {
+ long q = x / y;
+
+ if (x >= 0) {
+ if (y > 0) {
+ return q;
+ } else if (x % y == 0) {
+ return q;
+ } else {
+ return q - 1;
+ }
+ } else {
+ if (y > 0) {
+ if (x % y == 0) {
+ return q;
+ } else {
+ return q - 1;
+ }
+ } else {
+ return q;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculates the remainder of floor division of two 32-bit signed integers.
+ /// </summary>
+ /// <param name="x">Dividend.</param>
+ /// <param name="y">Divisor.</param>
+ /// <returns>The remainder of of floor division of the specified numbers, or <code>x - (int)Floor((double)x/(double)y) * y</code>.</returns>
+ /// <exception cref="DivideByZeroException"><paramref name="y"/> is 0.</exception>
+ public static int FloorRemainder(int x, int y) {
+ if (y == -1) return 0;
+ int r = x % y;
+
+ if (x >= 0) {
+ if (y > 0) {
+ return r;
+ } else if (r == 0) {
+ return 0;
+ } else {
+ return r + y;
+ }
+ } else {
+ if (y > 0) {
+ if (r == 0) {
+ return 0;
+ } else {
+ return r + y;
+ }
+ } else {
+ return r;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculates the remainder of floor division of two 32-bit signed integers.
+ /// </summary>
+ /// <param name="x">Dividend.</param>
+ /// <param name="y">Divisor.</param>
+ /// <returns>The remainder of of floor division of the specified numbers, or <code>x - (int)Floor((double)x/(double)y) * y</code>.</returns>
+ /// <exception cref="DivideByZeroException"><paramref name="y"/> is 0.</exception>
+ public static long FloorRemainder(long x, long y) {
+ if (y == -1) return 0;
+ long r = x % y;
+
+ if (x >= 0) {
+ if (y > 0) {
+ return r;
+ } else if (r == 0) {
+ return 0;
+ } else {
+ return r + y;
+ }
+ } else {
+ if (y > 0) {
+ if (r == 0) {
+ return 0;
+ } else {
+ return r + y;
+ }
+ } else {
+ return r;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Behaves like Math.Round(value, MidpointRounding.AwayFromZero)
+ /// Needed because CoreCLR doesn't support this particular overload of Math.Round
+ /// </summary>
+ public static double RoundAwayFromZero(double value) {
+#if !SILVERLIGHT && !WP75
+ return Math.Round(value, MidpointRounding.AwayFromZero);
+#else
+ if (value < 0) {
+ return -RoundAwayFromZero(-value);
+ }
+
+ // we can assume positive value
+ double result = Math.Floor(value);
+ if (value - result >= 0.5) {
+ result += 1.0;
+ }
+ return result;
+#endif
+ }
+
+ private static readonly double[] _RoundPowersOfTens = new double[] { 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15 };
+
+ private static double GetPowerOf10(int precision) {
+ return (precision < 16) ? _RoundPowersOfTens[precision] : Math.Pow(10, precision);
+ }
+
+ /// <summary>
+ /// Behaves like Math.Round(value, precision, MidpointRounding.AwayFromZero)
+ /// However, it works correctly on negative precisions and cases where precision is
+ /// outside of the [-15, 15] range.
+ ///
+ /// (This function is also needed because CoreCLR lacks this overload.)
+ /// </summary>
+ public static double RoundAwayFromZero(double value, int precision) {
+ if (double.IsInfinity(value) || double.IsNaN(value)) {
+ return value;
+ }
+
+ if (precision >= 0) {
+ if (precision > 308) {
+ return value;
+ }
+
+ double num = GetPowerOf10(precision);
+ return RoundAwayFromZero(value * num) / num;
+ } else if (precision >= -308) {
+ // Note: this code path could be merged with the precision >= 0 path,
+ // (by extending the cache to negative powers of 10)
+ // but the results seem to be more precise if we do it this way
+ double num = GetPowerOf10(-precision);
+ return RoundAwayFromZero(value / num) * num;
+ } else {
+ // Preserve the sign of the input, including +/-0.0
+ return value < 0.0 || 1.0 / value < 0.0 ? -0.0 : 0.0;
+ }
+ }
+
+ public static bool IsNegativeZero(double self) {
+#if SILVERLIGHT // BitConverter.DoubleToInt64Bits
+ if ( self != 0.0 ) {
+ return false;
+ }
+ byte[] bits = BitConverter.GetBytes(self);
+ return (bits[7] == 0x80 && bits[6] == 0x00 && bits[5] == 0x00 && bits[4] == 0x00
+ && bits[3] == 0x00 && bits[2] == 0x00 && bits[1] == 0x00 && bits[0] == 0x00);
+#else
+ return (self == 0.0 && 1.0 / self < 0);
+#endif
+ }
+
+ #region Special Functions
+
+ public static double Erf(double v0) {
+ // Calculate the error function using the approximation method outlined in
+ // W. J. Cody's "Rational Chebyshev Approximations for the Error Function"
+
+ if (v0 >= 10.0) {
+ return 1.0;
+ } else if (v0 <= -10.0) {
+ return -1.0;
+ }
+
+ if (v0 > 0.47 || v0 < -0.47) {
+ return 1.0 - ErfComplement(v0);
+ }
+
+ double sq = v0 * v0;
+ double numer = EvalPolynomial(sq, ErfNumerCoeffs);
+ double denom = EvalPolynomial(sq, ErfDenomCoeffs);
+
+ return v0 * numer / denom;
+ }
+
+ public static double ErfComplement(double v0) {
+ if (v0 >= 30.0) {
+ return 0.0;
+ } else if (v0 <= -10.0) {
+ return 2.0;
+ }
+
+ double a = Math.Abs(v0);
+ if (a < 0.47) {
+ return 1.0 - Erf(v0);
+ }
+
+ // Different approximations are required for different ranges of v0
+ double res;
+ if (a <= 4.0) {
+ // Use the approximation method outlined in W. J. Cody's "Rational Chebyshev
+ // Approximations for the Error Function"
+ double numer = EvalPolynomial(a, ErfcNumerCoeffs);
+ double denom = EvalPolynomial(a, ErfcDenomCoeffs);
+
+ res = Math.Exp(-a * a) * numer / denom;
+ } else {
+ // Use the approximation method introduced by C. Tellambura and A. Annamalai
+ // in "Efficient Computation of erfc(x) for Large Arguments"
+ const double h = 0.5;
+ const double hSquared = 0.25;
+ const int nTerms = 10;
+ double sq = a * a;
+ res = 0.0;
+ for (int i = nTerms; i > 0; i--) {
+ double term = i * i * hSquared;
+ res += Math.Exp(-term) / (term + sq);
+ }
+
+ res = h * a * Math.Exp(-sq) / Math.PI * (res * 2 + 1.0 / sq);
+ }
+
+ if (v0 < 0.0) {
+ res = 2.0 - res;
+ }
+ return res;
+ }
+
+ public static double Gamma(double v0) {
+ // Calculate the Gamma function using the Lanczos approximation
+
+ if (double.IsNegativeInfinity(v0)) {
+ return double.NaN;
+ }
+ double a = Math.Abs(v0);
+
+ // Special-case integers
+ if (a % 1.0 == 0.0) {
+ // Gamma is undefined on non-positive integers
+ if (v0 <= 0.0) {
+ return double.NaN;
+ }
+
+ // factorial(v0 - 1)
+ if (a <= 25.0) {
+ if (a <= 2.0) {
+ return 1.0;
+ }
+ a -= 1.0;
+ v0 -= 1.0;
+ while (--v0 > 1.0) {
+ a *= v0;
+ }
+ return a;
+ }
+ }
+
+ // lim(Gamma(v0)) = 1.0 / v0 as v0 approaches 0.0
+ if (a < 1e-50) {
+ return 1.0 / v0;
+ }
+
+ double res;
+ if (v0 < -150.0) {
+ // If Gamma(1 - v0) could overflow for large v0, use the duplication formula to
+ // compute Gamma(1 - v0):
+ // Gamma(x) * Gamma(x + 0,5) = sqrt(pi) * 2**(1 - 2x) * Gamma(2x)
+ // ==> Gamma(1 - x) = Gamma((1-x)/2) * Gamma((2-x)/2) / (2**x * sqrt(pi))
+ // Then apply the reflection formula:
+ // Gamma(x) = pi / sin(pi * x) / Gamma(1 - x)
+ double halfV0 = v0 / 2.0;
+ res = Math.Pow(Math.PI, 1.5) / SinPi(v0);
+ res *= Math.Pow(2.0, v0);
+ res /= PositiveGamma(0.5 - halfV0);
+ res /= PositiveGamma(1.0 - halfV0);
+ } else if (v0 < 0.001) {
+ // For values less than or close to zero, just use the reflection formula
+ res = Math.PI / SinPi(v0);
+ double v1 = 1.0 - v0;
+ if (v0 == 1.0 - v1) {
+ res /= PositiveGamma(v1);
+ } else {
+ // Computing v1 has resulted in a loss of precision. To avoid this, use the
+ // recurrence relation Gamma(x + 1) = x * Gamma(x).
+ res /= -v0 * PositiveGamma(-v0);
+ }
+ } else {
+ res = PositiveGamma(v0);
+ }
+
+ return res;
+ }
+
+ public static double LogGamma(double v0) {
+ // Calculate the log of the Gamma function using the Lanczos approximation
+
+ if (double.IsInfinity(v0)) {
+ return double.PositiveInfinity;
+ }
+ double a = Math.Abs(v0);
+
+ // Gamma is undefined on non-positive integers
+ if (v0 <= 0.0 && a % 1.0 == 0.0) {
+ return double.NaN;
+ }
+
+ // lim(LGamma(v0)) = -log|v0| as v0 approaches 0.0
+ if (a < 1e-50) {
+ return -Math.Log(a);
+ }
+
+ double res;
+ if (v0 < 0.0) {
+ // For negative values, use the reflection formula:
+ // Gamma(x) = pi / sin(pi * x) / Gamma(1 - x)
+ // ==> LGamma(x) = log(pi / |sin(pi * x)|) - LGamma(1 - x)
+ res = Math.Log(Math.PI / AbsSinPi(v0));
+ res -= PositiveLGamma(1.0 - v0);
+ } else {
+ res = PositiveLGamma(v0);
+ }
+
+ return res;
+ }
+
+ public static double Hypot(double x, double y) {
+ //
+ // sqrt(x*x + y*y) == sqrt(x*x * (1 + (y*y)/(x*x))) ==
+ // sqrt(x*x) * sqrt(1 + (y/x)*(y/x)) ==
+ // abs(x) * sqrt(1 + (y/x)*(y/x))
+ //
+
+ // Handle infinities
+ if (double.IsInfinity(x) || double.IsInfinity(y)) {
+ return double.PositiveInfinity;
+ }
+
+ // First, get abs
+ if (x < 0.0) x = -x;
+ if (y < 0.0) y = -y;
+
+ // Obvious cases
+ if (x == 0.0) return y;
+ if (y == 0.0) return x;
+
+ // Divide smaller number by bigger number to safeguard the (y/x)*(y/x)
+ if (x < y) {
+ double temp = y; y = x; x = temp;
+ }
+
+ y /= x;
+
+ // calculate abs(x) * sqrt(1 + (y/x)*(y/x))
+ return x * System.Math.Sqrt(1 + y * y);
+ }
+
+ /// <summary>
+ /// Evaluates a polynomial in v0 where the coefficients are ordered in increasing degree
+ /// </summary>
+ private static double EvalPolynomial(double v0, double[] coeffs) {
+ double res = 0.0;
+ for (int i = coeffs.Length - 1; i >= 0; i--) {
+ res = checked(res * v0 + coeffs[i]);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Evaluates a polynomial in v0 where the coefficients are ordered in increasing degree
+ /// if reverse is false, and increasing degree if reverse is true.
+ /// </summary>
+ private static double EvalPolynomial(double v0, double[] coeffs, bool reverse) {
+ if (!reverse) {
+ return EvalPolynomial(v0, coeffs);
+ }
+
+ double res = 0.0;
+ for (int i = 0; i < coeffs.Length; i++) {
+ res = checked(res * v0 + coeffs[i]);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// A numerically precise version of sin(v0 * pi)
+ /// </summary>
+ private static double SinPi(double v0) {
+ double res = Math.Abs(v0) % 2.0;
+
+ if (res < 0.25) {
+ res = Math.Sin(res * Math.PI);
+ } else if (res < 0.75) {
+ res = Math.Cos((res - 0.5) * Math.PI);
+ } else if (res < 1.25) {
+ res = -Math.Sin((res - 1.0) * Math.PI);
+ } else if (res < 1.75) {
+ res = -Math.Cos((res - 1.5) * Math.PI);
+ } else {
+ res = Math.Sin((res - 2.0) * Math.PI);
+ }
+
+ return v0 < 0 ? -res : res;
+ }
+
+ /// <summary>
+ /// A numerically precise version of |sin(v0 * pi)|
+ /// </summary>
+ private static double AbsSinPi(double v0) {
+ double res = Math.Abs(v0) % 1.0;
+
+ if (res < 0.25) {
+ res = Math.Sin(res * Math.PI);
+ } else if (res < 0.75) {
+ res = Math.Cos((res - 0.5) * Math.PI);
+ } else {
+ res = Math.Sin((res - 1.0) * Math.PI);
+ }
+
+ return Math.Abs(res);
+ }
+
+ // polynomial coefficients ordered by increasing degree
+ private static double[] ErfNumerCoeffs = {
+ 2.4266795523053175e02, 2.1979261618294152e01,
+ 6.9963834886191355, -3.5609843701815385e-02
+ };
+ private static double[] ErfDenomCoeffs = {
+ 2.1505887586986120e02, 9.1164905404514901e01,
+ 1.5082797630407787e01, 1.0
+ };
+ private static double[] ErfcNumerCoeffs = {
+ 3.004592610201616005e02, 4.519189537118729422e02,
+ 3.393208167343436870e02, 1.529892850469404039e02,
+ 4.316222722205673530e01, 7.211758250883093659,
+ 5.641955174789739711e-01, -1.368648573827167067e-07
+ };
+ private static double[] ErfcDenomCoeffs = {
+ 3.004592609569832933e02, 7.909509253278980272e02,
+ 9.313540948506096211e02, 6.389802644656311665e02,
+ 2.775854447439876434e02, 7.700015293522947295e01,
+ 1.278272731962942351e01, 1.0
+ };
+ private static double[] GammaNumerCoeffs = {
+ 4.401213842800460895436e13, 4.159045335859320051581e13,
+ 1.801384278711799677796e13, 4.728736263475388896889e12,
+ 8.379100836284046470415e11, 1.055837072734299344907e11,
+ 9.701363618494999493386e09, 6.549143975482052641016e08,
+ 3.223832294213356530668e07, 1.128514219497091438040e06,
+ 2.666579378459858944762e04, 3.818801248632926870394e02,
+ 2.506628274631000502415
+ };
+ private static double[] GammaDenomCoeffs = {
+ 0.0, 39916800.0, 120543840.0, 150917976.0,
+ 105258076.0, 45995730.0, 13339535.0, 2637558.0,
+ 357423.0, 32670.0, 1925.0, 66.0, 1.0
+ };
+
+ /// <summary>
+ /// Take the quotient of the 2 polynomials forming the Lanczos approximation
+ /// with N=13 and G=13.144565
+ /// </summary>
+ private static double GammaRationalFunc(double v0) {
+ double numer = 0.0;
+ double denom = 0.0;
+
+ if (v0 < 1e15) {
+ numer = EvalPolynomial(v0, GammaNumerCoeffs);
+ denom = EvalPolynomial(v0, GammaDenomCoeffs);
+ } else {
+ double vRecip = 1.0 / v0;
+ numer = EvalPolynomial(vRecip, GammaNumerCoeffs, true);
+ denom = EvalPolynomial(vRecip, GammaDenomCoeffs, true);
+ }
+
+ return numer / denom;
+ }
+
+ /// <summary>
+ /// Computes the Gamma function on positive values, using the Lanczos approximation.
+ /// Lanczos parameters are N=13 and G=13.144565.
+ /// </summary>
+ private static double PositiveGamma(double v0) {
+ if (v0 > 200.0) {
+ return Double.PositiveInfinity;
+ }
+
+ double vg = v0 + 12.644565; // v0 + g - 0.5
+ double res = GammaRationalFunc(v0);
+ res /= Math.Exp(vg);
+ if (v0 < 120.0) {
+ res *= Math.Pow(vg, v0 - 0.5);
+ } else {
+ // Use a smaller exponent if we're in danger of overflowing Math.Pow
+ double sqrt = Math.Pow(vg, v0 / 2.0 - 0.25);
+ res *= sqrt;
+ res *= sqrt;
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Computes the Log-Gamma function on positive values, using the Lanczos approximation.
+ /// Lanczos parameters are N=13 and G=13.144565.
+ /// </summary>
+ private static double PositiveLGamma(double v0) {
+ double vg = v0 + 12.644565; // v0 + g - 0.5
+ double res = Math.Log(GammaRationalFunc(v0)) - vg;
+ res += (v0 - 0.5) * Math.Log(vg);
+
+ return res;
+ }
+
+ #endregion
+
+ #region BigInteger
+
+ // generated by scripts/radix_generator.py
+ private static readonly uint[] maxCharsPerDigit = { 0, 0, 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };
+ private static readonly uint[] groupRadixValues = { 0, 0, 2147483648, 3486784401, 1073741824, 1220703125, 2176782336, 1977326743, 1073741824, 3486784401, 1000000000, 2357947691, 429981696, 815730721, 1475789056, 2562890625, 268435456, 410338673, 612220032, 893871739, 1280000000, 1801088541, 2494357888, 3404825447, 191102976, 244140625, 308915776, 387420489, 481890304, 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, 1838265625, 2176782336 };
+
+ internal static string BigIntegerToString(uint[] d, int sign, int radix, bool lowerCase) {
+ if (radix < 2) {
+ throw ExceptionUtils.MakeArgumentOutOfRangeException("radix", radix, "radix must be >= 2");
+ }
+ if (radix > 36) {
+ throw ExceptionUtils.MakeArgumentOutOfRangeException("radix", radix, "radix must be <= 36");
+ }
+
+ int dl = d.Length;
+ if (dl == 0) {
+ return "0";
+ }
+
+ List<uint> digitGroups = new List<uint>();
+
+ uint groupRadix = groupRadixValues[radix];
+ while (dl > 0) {
+ uint rem = div(d, ref dl, groupRadix);
+ digitGroups.Add(rem);
+ }
+
+ StringBuilder ret = new StringBuilder();
+ if (sign == -1) {
+ ret.Append("-");
+ }
+
+ int digitIndex = digitGroups.Count - 1;
+
+ char[] tmpDigits = new char[maxCharsPerDigit[radix]];
+
+ AppendRadix((uint)digitGroups[digitIndex--], (uint)radix, tmpDigits, ret, false, lowerCase);
+ while (digitIndex >= 0) {
+ AppendRadix((uint)digitGroups[digitIndex--], (uint)radix, tmpDigits, ret, true, lowerCase);
+ }
+ return ret.Length == 0 ? "0" : ret.ToString();
+ }
+
+ private const int BitsPerDigit = 32;
+
+ private static uint div(uint[] n, ref int nl, uint d) {
+ ulong rem = 0;
+ int i = nl;
+ bool seenNonZero = false;
+ while (--i >= 0) {
+ rem <<= BitsPerDigit;
+ rem |= n[i];
+ uint v = (uint)(rem / d);
+ n[i] = v;
+ if (v == 0) {
+ if (!seenNonZero) nl--;
+ } else {
+ seenNonZero = true;
+ }
+ rem %= d;
+ }
+ return (uint)rem;
+ }
+
+ private static void AppendRadix(uint rem, uint radix, char[] tmp, StringBuilder buf, bool leadingZeros, bool lowerCase) {
+ string symbols = lowerCase ? "0123456789abcdefghijklmnopqrstuvwxyz" : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ int digits = tmp.Length;
+ int i = digits;
+ while (i > 0 && (leadingZeros || rem != 0)) {
+ uint digit = rem % radix;
+ rem /= radix;
+ tmp[--i] = symbols[(int)digit];
+ }
+ if (leadingZeros) buf.Append(tmp);
+ else buf.Append(tmp, i, digits - i);
+ }
+
+ // Helper for GetRandBits
+ private static uint GetWord(byte[] bytes, int start, int end) {
+ uint four = 0;
+ int bits = end - start;
+ int shift = 0;
+ if (bits > 32) {
+ bits = 32;
+ }
+ start /= 8;
+ while (bits > 0) {
+ uint value = bytes[start];
+ if (bits < 8) {
+ value &= (1u << bits) - 1u;
+ }
+ value <<= shift;
+ four |= value;
+ bits -= 8;
+ shift += 8;
+ start++;
+ }
+
+ return four;
+ }
+
+#if !FEATURE_NUMERICS
+ public static BigInteger GetRandBits(this Random generator, int bits) {
+ ContractUtils.Requires(bits > 0);
+
+ // equivalent to (bits + 7) / 8 without possibility of overflow
+ int count = bits % 8 == 0 ? bits / 8 : bits / 8 + 1;
+
+ // Pad the end (most significant) with zeros if we align to the byte
+ // to ensure that we end up with a positive value
+ byte[] bytes = new byte[bits % 8 == 0 ? count + 1 : count];
+ generator.NextBytes(bytes);
+ if (bits % 8 == 0) {
+ bytes[bytes.Length - 1] = 0;
+ } else {
+ bytes[bytes.Length - 1] = (byte)(bytes[bytes.Length - 1] & ((1 << (bits % 8)) - 1));
+ }
+
+ if (bits <= 32) {
+ return (BigInteger)GetWord(bytes, 0, bits);
+ } else if (bits <= 64) {
+ ulong a = GetWord(bytes, 0, bits);
+ ulong b = GetWord(bytes, 32, bits);
+ return (BigInteger)(a | (b << 32));
+ } else {
+ count = (count + 3) / 4;
+ uint[] data = new uint[count];
+ for (int i = 0; i < count; i++) {
+ data[i] = GetWord(bytes, i * 32, bits);
+ }
+ return new BigInteger(1, data);
+ }
+ }
+
+ public static BigInteger Random(this Random generator, BigInteger limit) {
+ ContractUtils.Requires(limit.Sign > 0, "limit");
+ ContractUtils.RequiresNotNull(generator, "generator");
+
+ // TODO: this doesn't yield a uniform distribution (small numbers will be picked more frequently):
+ uint[] result = new uint[limit.GetWordCount() + 1];
+ for (int i = 0; i < result.Length; i++) {
+ result[i] = unchecked((uint)generator.Next());
+ }
+ return new BigInteger(1, result) % limit;
+ }
+#else
+ public static BigInt GetRandBits(this Random generator, int bits) {
+ ContractUtils.Requires(bits > 0);
+
+ // equivalent to (bits + 7) / 8 without possibility of overflow
+ int count = bits % 8 == 0 ? bits / 8 : bits / 8 + 1;
+
+ // Pad the end (most significant) with zeros if we align to the byte
+ // to ensure that we end up with a positive value
+ byte[] bytes = new byte[bits % 8 == 0 ? count + 1 : count];
+ generator.NextBytes(bytes);
+ if (bits % 8 == 0) {
+ bytes[bytes.Length - 1] = 0;
+ } else {
+ bytes[bytes.Length - 1] = (byte)(bytes[bytes.Length - 1] & ((1 << (bits % 8)) - 1));
+ }
+
+ if (bits <= 32) {
+ return (BigInt)GetWord(bytes, 0, bits);
+ } else if (bits <= 64) {
+ ulong a = GetWord(bytes, 0, bits);
+ ulong b = GetWord(bytes, 32, bits);
+ return (BigInt)(a | (b << 32));
+ }
+
+ return new BigInt(bytes);
+ }
+
+ public static BigInteger Random(this Random generator, BigInteger limit) {
+ return new BigInteger(generator.Random(limit.Value));
+ }
+
+ public static BigInt Random(this Random generator, BigInt limit) {
+ ContractUtils.Requires(limit.Sign > 0, "limit");
+ ContractUtils.RequiresNotNull(generator, "generator");
+
+ BigInt res = BigInt.Zero;
+
+ while (true) {
+ // if we've run out of significant digits, we can return the total
+ if (limit == BigInt.Zero) {
+ return res;
+ }
+
+ // if we're small enough to fit in an int, do so
+ int iLimit;
+ if (limit.AsInt32(out iLimit)) {
+ return res + generator.Next(iLimit);
+ }
+
+ // get the 3 or 4 uppermost bytes that fit into an int
+ int hiData;
+ byte[] data = limit.ToByteArray();
+ int index = data.Length;
+ while (data[--index] == 0) ;
+ if (data[index] < 0x80) {
+ hiData = data[index] << 24;
+ data[index--] = (byte)0;
+ } else {
+ hiData = 0;
+ }
+ hiData |= data[index] << 16;
+ data[index--] = (byte)0;
+ hiData |= data[index] << 8;
+ data[index--] = (byte)0;
+ hiData |= data[index];
+ data[index--] = (byte)0;
+
+ // get a uniform random number for the uppermost portion of the bigint
+ byte[] randomData = new byte[index + 2];
+ generator.NextBytes(randomData);
+ randomData[index + 1] = (byte)0;
+ res += new BigInt(randomData);
+ res += (BigInt)generator.Next(hiData) << ((index + 1) * 8);
+
+ // sum it with a uniform random number for the remainder of the bigint
+ limit = new BigInt(data);
+ }
+ }
+
+ public static bool TryToFloat64(this BigInt self, out double result) {
+ return StringUtils.TryParseDouble(
+ self.ToString(),
+ System.Globalization.NumberStyles.Number,
+ System.Globalization.CultureInfo.InvariantCulture.NumberFormat,
+ out result
+ );
+ }
+
+ public static double ToFloat64(this BigInt self) {
+ return double.Parse(
+ self.ToString(),
+ System.Globalization.NumberStyles.Number,
+ System.Globalization.CultureInfo.InvariantCulture.NumberFormat
+ );
+ }
+#endif
+
+ public static bool TryToFloat64(this BigInteger self, out double result) {
+ return StringUtils.TryParseDouble(
+ self.ToString(10),
+ System.Globalization.NumberStyles.Number,
+ System.Globalization.CultureInfo.InvariantCulture.NumberFormat,
+ out result
+ );
+ }
+
+ public static double ToFloat64(this BigInteger self) {
+ return double.Parse(
+ self.ToString(10),
+ System.Globalization.NumberStyles.Number,
+ System.Globalization.CultureInfo.InvariantCulture.NumberFormat
+ );
+ }
+
+ // Like GetBitCount(Abs(x)), except 0 maps to 0
+ public static int BitLength(BigInteger x) {
+ if (x.IsZero()) {
+ return 0;
+ }
+
+ return x.Abs().GetBitCount();
+ }
+
+#if FEATURE_NUMERICS
+ public static int BitLength(BigInt x) {
+ if (x.IsZero) {
+ return 0;
+ }
+
+ byte[] bytes = BigInt.Abs(x).ToByteArray();
+ int index = bytes.Length;
+ while (bytes[--index] == 0) ;
+
+ return index * 8 + BitLength((int)bytes[index]);
+ }
+#endif
+
+ // Like GetBitCount(Abs(x)), except 0 maps to 0
+ public static int BitLength(long x) {
+ if (x == 0) {
+ return 0;
+ }
+ if (x == Int64.MinValue) {
+ return 64;
+ }
+
+ x = Math.Abs(x);
+ int res = 1;
+ if (x >= 1L << 32) {
+ x >>= 32;
+ res += 32;
+ }
+ if (x >= 1L << 16) {
+ x >>= 16;
+ res += 16;
+ }
+ if (x >= 1L << 8) {
+ x >>= 8;
+ res += 8;
+ }
+ if (x >= 1L << 4) {
+ x >>= 4;
+ res += 4;
+ }
+ if (x >= 1L << 2) {
+ x >>= 2;
+ res += 2;
+ }
+ if (x >= 1L << 1) {
+ res += 1;
+ }
+
+ return res;
+ }
+
+ // Like GetBitCount(Abs(x)), except 0 maps to 0
+ [CLSCompliant(false)]
+ public static int BitLengthUnsigned(ulong x) {
+ if (x >= 1uL << 63) {
+ return 64;
+ }
+ return BitLength((long)x);
+ }
+
+ // Like GetBitCount(Abs(x)), except 0 maps to 0
+ public static int BitLength(int x) {
+ if (x == 0) {
+ return 0;
+ }
+ if (x == Int32.MinValue) {
+ return 32;
+ }
+
+ x = Math.Abs(x);
+ int res = 1;
+ if (x >= 1 << 16) {
+ x >>= 16;
+ res += 16;
+ }
+ if (x >= 1 << 8) {
+ x >>= 8;
+ res += 8;
+ }
+ if (x >= 1 << 4) {
+ x >>= 4;
+ res += 4;
+ }
+ if (x >= 1 << 2) {
+ x >>= 2;
+ res += 2;
+ }
+ if (x >= 1 << 1) {
+ res += 1;
+ }
+
+ return res;
+ }
+
+ // Like GetBitCount(Abs(x)), except 0 maps to 0
+ [CLSCompliant(false)]
+ public static int BitLengthUnsigned(uint x) {
+ if (x >= 1u << 31) {
+ return 32;
+ }
+ return BitLength((int)x);
+ }
+
+ #region Extending BigInt with BigInteger API
+#if FEATURE_NUMERICS
+
+ public static bool AsInt32(this BigInt self, out int ret) {
+ if (self >= Int32.MinValue && self <= Int32.MaxValue) {
+ ret = (Int32)self;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ public static bool AsInt64(this BigInt self, out long ret) {
+ if (self >= Int64.MinValue && self <= Int64.MaxValue) {
+ ret = (long)self;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ [CLSCompliant(false)]
+ public static bool AsUInt32(this BigInt self, out uint ret) {
+ if (self >= UInt32.MinValue && self <= UInt32.MaxValue) {
+ ret = (UInt32)self;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ [CLSCompliant(false)]
+ public static bool AsUInt64(this BigInt self, out ulong ret) {
+ if (self >= UInt64.MinValue && self <= UInt64.MaxValue) {
+ ret = (UInt64)self;
+ return true;
+ }
+ ret = 0;
+ return false;
+ }
+
+ public static BigInt Abs(this BigInt self) {
+ return BigInt.Abs(self);
+ }
+
+ public static bool IsZero(this BigInt self) {
+ return self.IsZero;
+ }
+
+ public static bool IsPositive(this BigInt self) {
+ return self.Sign > 0;
+ }
+
+ public static bool IsNegative(this BigInt self) {
+ return self.Sign < 0;
+ }
+
+ public static double Log(this BigInt self) {
+ return BigInt.Log(self);
+ }
+
+ public static double Log(this BigInt self, double baseValue) {
+ return BigInt.Log(self, baseValue);
+ }
+
+ public static double Log10(this BigInt self) {
+ return BigInt.Log10(self);
+ }
+
+ public static BigInt Power(this BigInt self, int exp) {
+ return BigInt.Pow(self, exp);
+ }
+
+ public static BigInt ModPow(this BigInt self, int power, BigInt mod) {
+ return BigInt.ModPow(self, power, mod);
+ }
+
+ public static BigInt ModPow(this BigInt self, BigInt power, BigInt mod) {
+ return BigInt.ModPow(self, power, mod);
+ }
+
+ public static string ToString(this BigInt self, int radix) {
+ const string symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ if (radix < 2) {
+ throw ExceptionUtils.MakeArgumentOutOfRangeException("radix", radix, "radix must be >= 2");
+ }
+ if (radix > 36) {
+ throw ExceptionUtils.MakeArgumentOutOfRangeException("radix", radix, "radix must be <= 36");
+ }
+
+ bool isNegative = false;
+ if (self < BigInt.Zero) {
+ self = -self;
+ isNegative = true;
+ } else if (self == BigInt.Zero) {
+ return "0";
+ }
+
+ List<char> digits = new List<char>();
+ while (self > 0) {
+ digits.Add(symbols[(int)(self % radix)]);
+ self /= radix;
+ }
+
+ StringBuilder ret = new StringBuilder();
+ if (isNegative) {
+ ret.Append('-');
+ }
+ for (int digitIndex = digits.Count - 1; digitIndex >= 0; digitIndex--) {
+ ret.Append(digits[digitIndex]);
+ }
+ return ret.ToString();
+ }
+#endif
+ #endregion
+
+ #region Exposing underlying data
+#if FEATURE_NUMERICS
+
+ [CLSCompliant(false)]
+ public static uint[] GetWords(this BigInt self) {
+ if (self.IsZero) {
+ return new uint[] { 0 };
+ }
+
+ int hi;
+ byte[] bytes;
+ GetHighestByte(self, out hi, out bytes);
+
+ uint[] result = new uint[(hi + 1 + 3) / 4];
+ int i = 0;
+ int j = 0;
+ uint u = 0;
+ int shift = 0;
+ while (i < bytes.Length) {
+ u |= (uint)bytes[i++] << shift;
+ if (i % 4 == 0) {
+ result[j++] = u;
+ u = 0;
+ }
+ shift += 8;
+ }
+ if (u != 0) {
+ result[j] = u;
+ }
+ return result;
+ }
+
+ [CLSCompliant(false)]
+ public static uint GetWord(this BigInt self, int index) {
+ return GetWords(self)[index];
+ }
+
+ public static int GetWordCount(this BigInt self) {
+ int index;
+ byte[] bytes;
+ GetHighestByte(self, out index, out bytes);
+ return index / 4 + 1; // return (index + 1 + 3) / 4;
+ }
+
+ public static int GetByteCount(this BigInt self) {
+ int index;
+ byte[] bytes;
+ GetHighestByte(self, out index, out bytes);
+ return index + 1;
+ }
+
+ public static int GetBitCount(this BigInt self) {
+ if (self.IsZero) {
+ return 1;
+ }
+ byte[] bytes = BigInt.Abs(self).ToByteArray();
+
+ int index = bytes.Length;
+ while (bytes[--index] == 0) ;
+
+ int count = index * 8;
+ for (int hiByte = bytes[index]; hiByte > 0; hiByte >>= 1) {
+ count++;
+ }
+ return count;
+ }
+
+ private static byte GetHighestByte(BigInt self, out int index, out byte[] byteArray) {
+ byte[] bytes = BigInt.Abs(self).ToByteArray();
+ if (self.IsZero) {
+ byteArray = bytes;
+ index = 0;
+ return 1;
+ }
+
+ int hi = bytes.Length;
+ byte b;
+ do {
+ b = bytes[--hi];
+ } while (b == 0);
+ index = hi;
+ byteArray = bytes;
+ return b;
+ }
+
+#endif
+ #endregion
+
+ #endregion
+
+ #region Complex
+
+#if !FEATURE_NUMERICS
+ public static Complex64 MakeReal(double real) {
+ return new Complex64(real, 0.0);
+ }
+
+ public static Complex64 MakeImaginary(double imag) {
+ return new Complex64(0.0, imag);
+ }
+
+ public static Complex64 MakeComplex(double real, double imag) {
+ return new Complex64(real, imag);
+ }
+
+ public static double Imaginary(this Complex64 self) {
+ return self.Imag;
+ }
+
+ public static bool IsZero(this Complex64 self) {
+ return self.IsZero;
+ }
+
+ public static Complex64 Pow(this Complex64 self, Complex64 power) {
+ return self.Power(power);
+ }
+#else
+ public static Complex MakeReal(double real) {
+ return new Complex(real, 0.0);
+ }
+
+ public static Complex MakeImaginary(double imag) {
+ return new Complex(0.0, imag);
+ }
+
+ public static Complex MakeComplex(double real, double imag) {
+ return new Complex(real, imag);
+ }
+
+ public static double Imaginary(this Complex self) {
+ return self.Imaginary;
+ }
+
+ public static bool IsZero(this Complex self) {
+ return self.Equals(Complex.Zero);
+ }
+
+ public static Complex Conjugate(this Complex self) {
+ return new Complex(self.Real, -self.Imaginary);
+ }
+
+ public static double Abs(this Complex self) {
+ return Complex.Abs(self);
+ }
+
+ public static Complex Pow(this Complex self, Complex power) {
+ return Complex.Pow(self, power);
+ }
+#endif
+
+ #endregion
+ }
+
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReferenceEqualityComparer.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReferenceEqualityComparer.cs
new file mode 100644
index 00000000000..291a23eec16
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReferenceEqualityComparer.cs
@@ -0,0 +1,48 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Linq.Expressions;
+using System.Dynamic;
+
+namespace Microsoft.Scripting.Utils {
+ public sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T> where T : class {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly ReferenceEqualityComparer<T> Instance = new ReferenceEqualityComparer<T>();
+
+ private ReferenceEqualityComparer() { }
+
+ public bool Equals(T x, T y) {
+ return object.ReferenceEquals(x, y);
+ }
+
+#if WIN8
+ private static Expression NullConst = Expression.Constant(null);
+ private static int H = 536870912 ^ NullConst.GetHashCode();
+#endif
+
+ public int GetHashCode(T obj) {
+#if WP75 // CF RH.GetHashCode throws NullReferenceException if the argument is null
+ return obj != null ? RuntimeHelpers.GetHashCode(obj) : 0;
+#elif WIN8
+ // TODO: HACK!
+ return BindingRestrictions.GetInstanceRestriction(NullConst, obj).GetHashCode() ^ H;
+#else
+ return RuntimeHelpers.GetHashCode(obj);
+#endif
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReflectionUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReflectionUtils.cs
new file mode 100644
index 00000000000..95e23e634a8
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/ReflectionUtils.cs
@@ -0,0 +1,1951 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_METADATA_READER
+using Microsoft.Scripting.Metadata;
+#endif
+
+#if !WIN8
+using TypeInfo = System.Type;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+#if FEATURE_REFEMIT
+using System.Reflection.Emit;
+#endif
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Dynamic;
+using System.Linq.Expressions;
+
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Runtime;
+using Microsoft.Scripting.Utils;
+
+#if WIN8 || WP75
+namespace System.Runtime.CompilerServices {
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event)]
+ public sealed class SpecialNameAttribute : Attribute {
+ public SpecialNameAttribute() {
+ }
+ }
+}
+#endif
+
+#if WIN8
+namespace System {
+ public enum TypeCode {
+ Empty,
+ Object,
+ DBNull,
+ Boolean,
+ Char,
+ SByte,
+ Byte,
+ Int16,
+ UInt16,
+ Int32,
+ UInt32,
+ Int64,
+ UInt64,
+ Single,
+ Double,
+ Decimal,
+ DateTime,
+ String = 18
+ }
+}
+
+namespace System.Reflection {
+ [Flags]
+ public enum BindingFlags {
+ /// <summary>Specifies that instance members are to be included in the search.</summary>
+ Instance = 4,
+ /// <summary>Specifies that static members are to be included in the search.</summary>
+ Static = 8,
+ /// <summary>Specifies that public members are to be included in the search.</summary>
+ Public = 16,
+ /// <summary>Specifies that non-public members are to be included in the search.</summary>
+ NonPublic = 32
+ }
+}
+#elif !CLR45
+namespace System.Reflection {
+ public static class RuntimeReflectionExtensions {
+ public static MethodInfo GetRuntimeBaseDefinition(this MethodInfo method) {
+ return method.GetBaseDefinition();
+ }
+
+ public static IEnumerable<MethodInfo> GetRuntimeMethods(this Type type) {
+ return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
+ }
+ }
+}
+#endif
+
+namespace Microsoft.Scripting.Utils {
+ // CF doesn't support DefaultParameterValue attribute. Define our own, but not in System.Runtime.InteropServices namespace as that would
+ // make C# compiler emit the parameter's default value metadata not the attribute itself. The default value metadata are not accessible on CF.
+#if !FEATURE_DEFAULT_PARAMETER_VALUE
+ /// <summary>
+ /// The Default Parameter Value Attribute.
+ /// </summary>
+ public sealed class DefaultParameterValueAttribute : Attribute
+ {
+ private readonly object _value;
+
+ public object Value
+ {
+ get { return _value; }
+ }
+
+ /// <summary>
+ /// The constructor
+ /// </summary>
+ /// <param name="value">The value.</param>
+ public DefaultParameterValueAttribute(object value)
+ {
+ _value = value;
+ }
+ }
+
+#if !ANDROID
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false), ComVisible(true)]
+ public sealed class OptionalAttribute : Attribute {
+ }
+#endif
+#endif
+
+ public static class ReflectionUtils {
+ #region Accessibility
+
+ public static BindingFlags AllMembers = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+
+ public static bool IsPublic(this PropertyInfo property) {
+ return property.GetGetMethod(nonPublic: false) != null
+ || property.GetSetMethod(nonPublic: false) != null;
+ }
+
+ public static bool IsStatic(this PropertyInfo property) {
+ var getter = property.GetGetMethod(nonPublic: true);
+ var setter = property.GetSetMethod(nonPublic: true);
+
+ return getter != null && getter.IsStatic
+ || setter != null && setter.IsStatic;
+ }
+
+ public static bool IsStatic(this EventInfo evnt) {
+ var add = evnt.GetAddMethod(nonPublic: true);
+ var remove = evnt.GetRemoveMethod(nonPublic: true);
+
+ return add != null && add.IsStatic
+ || remove != null && remove.IsStatic;
+ }
+
+ public static bool IsPrivate(this PropertyInfo property) {
+ var getter = property.GetGetMethod(nonPublic: true);
+ var setter = property.GetSetMethod(nonPublic: true);
+
+ return (getter == null || getter.IsPrivate)
+ && (setter == null || setter.IsPrivate);
+ }
+
+ public static bool IsPrivate(this EventInfo evnt) {
+ var add = evnt.GetAddMethod(nonPublic: true);
+ var remove = evnt.GetRemoveMethod(nonPublic: true);
+
+ return (add == null || add.IsPrivate)
+ && (remove == null || remove.IsPrivate);
+ }
+
+ private static bool MatchesFlags(ConstructorInfo member, BindingFlags flags) {
+ return
+ ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
+ ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
+ }
+
+ private static bool MatchesFlags(MethodInfo member, BindingFlags flags) {
+ return
+ ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
+ ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
+ }
+
+ private static bool MatchesFlags(FieldInfo member, BindingFlags flags) {
+ return
+ ((member.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
+ ((member.IsStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
+ }
+
+ private static bool MatchesFlags(PropertyInfo member, BindingFlags flags) {
+ return
+ ((member.IsPublic() ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
+ ((member.IsStatic() ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
+ }
+
+ private static bool MatchesFlags(EventInfo member, BindingFlags flags) {
+ var add = member.GetAddMethod();
+ var remove = member.GetRemoveMethod();
+ var raise = member.GetRaiseMethod();
+
+ bool isPublic = add != null && add.IsPublic || remove != null && remove.IsPublic || raise != null && raise.IsPublic;
+ bool isStatic = add != null && add.IsStatic || remove != null && remove.IsStatic || raise != null && raise.IsStatic;
+
+ return
+ ((isPublic ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0 &&
+ ((isStatic ? BindingFlags.Static : BindingFlags.Instance) & flags) != 0;
+ }
+
+ private static bool MatchesFlags(TypeInfo member, BindingFlags flags) {
+ // Static/Instance are ignored
+ return (((member.IsPublic || member.IsNestedPublic) ? BindingFlags.Public : BindingFlags.NonPublic) & flags) != 0;
+ }
+
+ private static bool MatchesFlags(MemberInfo member, BindingFlags flags) {
+ ConstructorInfo ctor;
+ MethodInfo method;
+ FieldInfo field;
+ EventInfo evnt;
+ PropertyInfo property;
+
+ if ((method = member as MethodInfo) != null) {
+ return MatchesFlags(method, flags);
+ }
+
+ if ((field = member as FieldInfo) != null) {
+ return MatchesFlags(field, flags);
+ }
+
+ if ((ctor = member as ConstructorInfo) != null) {
+ return MatchesFlags(ctor, flags);
+ }
+
+ if ((evnt = member as EventInfo) != null) {
+ return MatchesFlags(evnt, flags);
+ }
+
+ if ((property = member as PropertyInfo) != null) {
+ return MatchesFlags(property, flags);
+ }
+
+ return MatchesFlags((TypeInfo)member, flags);
+ }
+
+ private static IEnumerable<T> WithBindingFlags<T>(this IEnumerable<T> members, Func<T, BindingFlags, bool> matchFlags, BindingFlags flags)
+ where T : MemberInfo {
+ return members.Where(member => matchFlags(member, flags));
+ }
+
+ public static IEnumerable<MemberInfo> WithBindingFlags(this IEnumerable<MemberInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static IEnumerable<MethodInfo> WithBindingFlags(this IEnumerable<MethodInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static IEnumerable<ConstructorInfo> WithBindingFlags(this IEnumerable<ConstructorInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static IEnumerable<FieldInfo> WithBindingFlags(this IEnumerable<FieldInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static IEnumerable<PropertyInfo> WithBindingFlags(this IEnumerable<PropertyInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static IEnumerable<EventInfo> WithBindingFlags(this IEnumerable<EventInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static IEnumerable<TypeInfo> WithBindingFlags(this IEnumerable<TypeInfo> members, BindingFlags flags) {
+ return members.WithBindingFlags(MatchesFlags, flags);
+ }
+
+ public static MemberInfo WithBindingFlags(this MemberInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ public static MethodInfo WithBindingFlags(this MethodInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ public static ConstructorInfo WithBindingFlags(this ConstructorInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ public static FieldInfo WithBindingFlags(this FieldInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ public static PropertyInfo WithBindingFlags(this PropertyInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ public static EventInfo WithBindingFlags(this EventInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ public static TypeInfo WithBindingFlags(this TypeInfo member, BindingFlags flags) {
+ return member != null && MatchesFlags(member, flags) ? member : null;
+ }
+
+ #endregion
+
+ #region Signatures
+
+ public static IEnumerable<MethodInfo> WithSignature(this IEnumerable<MethodInfo> members, Type[] parameterTypes) {
+ return members.Where(c => {
+ var ps = c.GetParameters();
+ if (ps.Length != parameterTypes.Length) {
+ return false;
+ }
+
+ for (int i = 0; i < ps.Length; i++) {
+ if (parameterTypes[i] != ps[i].ParameterType) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+ }
+
+ public static IEnumerable<ConstructorInfo> WithSignature(this IEnumerable<ConstructorInfo> members, Type[] parameterTypes) {
+ return members.Where(c => {
+ var ps = c.GetParameters();
+ if (ps.Length != parameterTypes.Length) {
+ return false;
+ }
+
+ for (int i = 0; i < ps.Length; i++) {
+ if (parameterTypes[i] != ps[i].ParameterType) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+ }
+
+ #endregion
+
+ #region Member Inheritance
+
+ // CLI specification, partition I, 8.10.4: Hiding, overriding, and layout
+ // ----------------------------------------------------------------------
+ // While hiding applies to all members of a type, overriding deals with object layout and is applicable only to instance fields
+ // and virtual methods. The CTS provides two forms of member overriding, new slot and expect existing slot. A member of a derived
+ // type that is marked as a new slot will always get a new slot in the object’s layout, guaranteeing that the base field or method
+ // is available in the object by using a qualified reference that combines the name of the base type with the name of the member
+ // and its type or signature. A member of a derived type that is marked as expect existing slot will re-use (i.e., share or override)
+ // a slot that corresponds to a member of the same kind (field or method), name, and type if one already exists from the base type;
+ // if no such slot exists, a new slot is allocated and used.
+ //
+ // The general algorithm that is used for determining the names in a type and the layout of objects of the type is roughly as follows:
+ // - Flatten the inherited names (using the hide by name or hide by name-and-signature rule) ignoring accessibility rules.
+ // - For each new member that is marked “expect existing slot”, look to see if an exact match on kind (i.e., field or method),
+ // name, and signature exists and use that slot if it is found, otherwise allocate a new slot.
+ // - After doing this for all new members, add these new member-kind/name/signatures to the list of members of this type
+ // - Finally, remove any inherited names that match the new members based on the hide by name or hide by name-and-signature rules.
+
+ // NOTE: Following GetXxx only implement overriding, not hiding specified by hide-by-name or hide-by-name-and-signature flags.
+
+ public static IEnumerable<MethodInfo> GetInheritedMethods(this Type type, string name = null, bool flattenHierarchy = false) {
+ while (type.IsGenericParameter) {
+ type = type.GetBaseType();
+ }
+
+ var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
+ foreach (var ancestor in type.Ancestors()) {
+ foreach (var declaredMethod in ancestor.GetDeclaredMethods(name)) {
+ if (declaredMethod != null && IncludeMethod(declaredMethod, type, baseDefinitions, flattenHierarchy)) {
+ yield return declaredMethod;
+ }
+ }
+ }
+ }
+
+ private static bool IncludeMethod(MethodInfo member, Type reflectedType, HashSet<MethodInfo> baseDefinitions, bool flattenHierarchy) {
+ if (member.IsVirtual) {
+ if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(member))) {
+ return true;
+ }
+ } else if (member.DeclaringType == reflectedType) {
+ return true;
+ } else if (!member.IsPrivate && (!member.IsStatic || flattenHierarchy)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static IEnumerable<PropertyInfo> GetInheritedProperties(this Type type, string name = null, bool flattenHierarchy = false) {
+ while (type.IsGenericParameter) {
+ type = type.GetBaseType();
+ }
+
+ var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
+ foreach (var ancestor in type.Ancestors()) {
+ if (name != null) {
+ var declaredProperty = ancestor.GetDeclaredProperty(name);
+ if (declaredProperty != null && IncludeProperty(declaredProperty, type, baseDefinitions, flattenHierarchy)) {
+ yield return declaredProperty;
+ }
+ } else {
+ foreach (var declaredProperty in ancestor.GetDeclaredProperties()) {
+ if (IncludeProperty(declaredProperty, type, baseDefinitions, flattenHierarchy)) {
+ yield return declaredProperty;
+ }
+ }
+ }
+ }
+ }
+
+ // CLI spec 22.34 Properties
+ // -------------------------
+ // [Note: The CLS (see Partition I) refers to instance, virtual, and static properties.
+ // The signature of a property (from the Type column) can be used to distinguish a static property,
+ // since instance and virtual properties will have the “HASTHIS” bit set in the signature (§23.2.1)
+ // while a static property will not. The distinction between an instance and a virtual property
+ // depends on the signature of the getter and setter methods, which the CLS requires to be either
+ // both virtual or both instance. end note]
+ private static bool IncludeProperty(PropertyInfo member, Type reflectedType, HashSet<MethodInfo> baseDefinitions, bool flattenHierarchy) {
+ var getter = member.GetGetMethod(nonPublic: true);
+ var setter = member.GetSetMethod(nonPublic: true);
+
+ MethodInfo virtualAccessor;
+ if (getter != null && getter.IsVirtual) {
+ virtualAccessor = getter;
+ } else if (setter != null && setter.IsVirtual) {
+ virtualAccessor = setter;
+ } else {
+ virtualAccessor = null;
+ }
+
+ if (virtualAccessor != null) {
+ if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(virtualAccessor))) {
+ return true;
+ }
+ } else if (member.DeclaringType == reflectedType) {
+ return true;
+ } else if (!member.IsPrivate() && (!member.IsStatic() || flattenHierarchy)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static IEnumerable<EventInfo> GetInheritedEvents(this Type type, string name = null, bool flattenHierarchy = false) {
+ while (type.IsGenericParameter) {
+ type = type.GetBaseType();
+ }
+
+ var baseDefinitions = new HashSet<MethodInfo>(ReferenceEqualityComparer<MethodInfo>.Instance);
+ foreach (var ancestor in type.Ancestors()) {
+ if (name != null) {
+ var declaredEvent = ancestor.GetDeclaredEvent(name);
+ if (declaredEvent != null && IncludeEvent(declaredEvent, type, baseDefinitions, flattenHierarchy)) {
+ yield return declaredEvent;
+ }
+ } else {
+ foreach (var declaredEvent in ancestor.GetDeclaredEvents()) {
+ if (IncludeEvent(declaredEvent, type, baseDefinitions, flattenHierarchy)) {
+ yield return declaredEvent;
+ }
+ }
+ }
+ }
+ }
+
+ private static bool IncludeEvent(EventInfo member, Type reflectedType, HashSet<MethodInfo> baseDefinitions, bool flattenHierarchy) {
+ var add = member.GetAddMethod(nonPublic: true);
+ var remove = member.GetRemoveMethod(nonPublic: true);
+
+ // TOOD: fire method?
+
+ MethodInfo virtualAccessor;
+ if (add != null && add.IsVirtual) {
+ virtualAccessor = add;
+ } else if (remove != null && remove.IsVirtual) {
+ virtualAccessor = remove;
+ } else {
+ virtualAccessor = null;
+ }
+
+ if (virtualAccessor != null) {
+ if (baseDefinitions.Add(RuntimeReflectionExtensions.GetRuntimeBaseDefinition(virtualAccessor))) {
+ return true;
+ }
+ } else if (member.DeclaringType == reflectedType) {
+ return true;
+ } else if (!member.IsPrivate() && (!member.IsStatic() || flattenHierarchy)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static IEnumerable<FieldInfo> GetInheritedFields(this Type type, string name = null, bool flattenHierarchy = false) {
+ while (type.IsGenericParameter) {
+ type = type.GetBaseType();
+ }
+
+ foreach (var ancestor in type.Ancestors()) {
+ if (name != null) {
+ var declaredField = ancestor.GetDeclaredField(name);
+ if (declaredField != null && IncludeField(declaredField, type, flattenHierarchy)) {
+ yield return declaredField;
+ }
+ } else {
+ foreach (var declaredField in ancestor.GetDeclaredFields()) {
+ if (IncludeField(declaredField, type, flattenHierarchy)) {
+ yield return declaredField;
+ }
+ }
+ }
+ }
+ }
+
+ private static bool IncludeField(FieldInfo member, Type reflectedType, bool flattenHierarchy) {
+ if (member.DeclaringType == reflectedType) {
+ return true;
+ } else if (!member.IsPrivate && (!member.IsStatic || flattenHierarchy)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static IEnumerable<MemberInfo> GetInheritedMembers(this Type type, string name = null, bool flattenHierarchy = false) {
+ var result =
+ type.GetInheritedMethods(name, flattenHierarchy).Cast<MethodInfo, MemberInfo>().Concat(
+ type.GetInheritedProperties(name, flattenHierarchy).Cast<PropertyInfo, MemberInfo>().Concat(
+ type.GetInheritedEvents(name, flattenHierarchy).Cast<EventInfo, MemberInfo>().Concat(
+ type.GetInheritedFields(name, flattenHierarchy).Cast<FieldInfo, MemberInfo>())));
+
+ if (name == null) {
+ return result.Concat<MemberInfo>(
+ type.GetDeclaredConstructors().Cast<ConstructorInfo, MemberInfo>().Concat(
+ type.GetDeclaredNestedTypes().Cast<TypeInfo, MemberInfo>()));
+ }
+
+ var nestedType = type.GetDeclaredNestedType(name);
+ return (nestedType != null) ? result.Concat(new[] { nestedType }) : result;
+ }
+
+ #endregion
+
+ #region Declared Members
+
+ public static IEnumerable<ConstructorInfo> GetDeclaredConstructors(this Type type) {
+#if WIN8
+ return type.GetTypeInfo().DeclaredConstructors;
+#else
+ return type.GetConstructors(BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+#if WIN8
+ public static ConstructorInfo GetConstructor(this Type type, Type[] parameterTypes) {
+ return type.GetDeclaredConstructors().Where(ci => !ci.IsStatic && ci.IsPublic).WithSignature(parameterTypes).SingleOrDefault();
+ }
+#endif
+
+ public static IEnumerable<MethodInfo> GetDeclaredMethods(this Type type, string name = null) {
+#if WIN8
+ if (name == null) {
+ return type.GetTypeInfo().DeclaredMethods;
+ } else {
+ return type.GetTypeInfo().GetDeclaredMethods(name);
+ }
+#else
+ if (name == null) {
+ return type.GetMethods(BindingFlags.DeclaredOnly | AllMembers);
+ } else {
+ return type.GetMember(name, MemberTypes.Method, BindingFlags.DeclaredOnly | AllMembers).OfType<MethodInfo>();
+ }
+#endif
+ }
+
+ public static IEnumerable<PropertyInfo> GetDeclaredProperties(this Type type) {
+#if WIN8
+ return type.GetTypeInfo().DeclaredProperties;
+#else
+ return type.GetProperties(BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static PropertyInfo GetDeclaredProperty(this Type type, string name) {
+ Debug.Assert(name != null);
+#if WIN8
+ return type.GetTypeInfo().GetDeclaredProperty(name);
+#else
+ return type.GetProperty(name, BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static IEnumerable<EventInfo> GetDeclaredEvents(this Type type) {
+#if WIN8
+ return type.GetTypeInfo().DeclaredEvents;
+#else
+ return type.GetEvents(BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static EventInfo GetDeclaredEvent(this Type type, string name) {
+ Debug.Assert(name != null);
+#if WIN8
+ return type.GetTypeInfo().GetDeclaredEvent(name);
+#else
+ return type.GetEvent(name, BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static IEnumerable<FieldInfo> GetDeclaredFields(this Type type) {
+#if WIN8
+ return type.GetTypeInfo().DeclaredFields;
+#else
+ return type.GetFields(BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static FieldInfo GetDeclaredField(this Type type, string name) {
+ Debug.Assert(name != null);
+#if WIN8
+ return type.GetTypeInfo().GetDeclaredField(name);
+#else
+ return type.GetField(name, BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static IEnumerable<TypeInfo> GetDeclaredNestedTypes(this Type type) {
+#if WIN8
+ return type.GetTypeInfo().DeclaredNestedTypes;
+#else
+ return type.GetNestedTypes(BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static TypeInfo GetDeclaredNestedType(this Type type, string name) {
+ Debug.Assert(name != null);
+#if WIN8
+ return type.GetTypeInfo().GetDeclaredNestedType(name);
+#else
+ return type.GetNestedType(name, BindingFlags.DeclaredOnly | AllMembers);
+#endif
+ }
+
+ public static IEnumerable<MemberInfo> GetDeclaredMembers(this Type type, string name = null) {
+#if WIN8
+ var info = type.GetTypeInfo();
+ if (name == null) {
+ return info.DeclaredMembers;
+ } else {
+ return GetDeclaredMembersWithName(info, name);
+ }
+#else
+ if (name == null) {
+ return type.GetMembers(BindingFlags.DeclaredOnly | AllMembers);
+ } else {
+ return type.GetMember(name, BindingFlags.DeclaredOnly | AllMembers);
+ }
+#endif
+ }
+
+#if WIN8
+ private static IEnumerable<MemberInfo> GetDeclaredMembersWithName(TypeInfo info, string name) {
+ MemberInfo member;
+
+ if ((member = info.GetDeclaredMethod(name)) != null) {
+ yield return member;
+ }
+
+ if ((member = info.GetDeclaredField(name)) != null) {
+ yield return member;
+ }
+
+ if ((member = info.GetDeclaredProperty(name)) != null) {
+ yield return member;
+ }
+
+ if ((member = info.GetDeclaredEvent(name)) != null) {
+ yield return member;
+ }
+
+ if ((member = info.GetDeclaredNestedType(name)) != null) {
+ yield return member;
+ }
+ }
+#endif
+
+ #endregion
+
+ #region Win8
+#if WIN8 || CLR45
+ public static TypeCode GetTypeCode(this Enum e) {
+ return GetTypeCode(Enum.GetUnderlyingType(e.GetType()));
+ }
+
+ // TODO: reduce to numeric types?
+ public static TypeCode GetTypeCode(this Type type) {
+ if (type == typeof(int)) {
+ return TypeCode.Int32;
+ }
+ if (type == typeof(sbyte)) {
+ return TypeCode.SByte;
+ }
+ if (type == typeof(short)) {
+ return TypeCode.Int16;
+ }
+ if (type == typeof(long)) {
+ return TypeCode.Int64;
+ }
+ if (type == typeof(uint)) {
+ return TypeCode.UInt32;
+ }
+ if (type == typeof(byte)) {
+ return TypeCode.Byte;
+ }
+ if (type == typeof(ushort)) {
+ return TypeCode.UInt16;
+ }
+ if (type == typeof(ulong)) {
+ return TypeCode.UInt64;
+ }
+ if (type == typeof(bool)) {
+ return TypeCode.Boolean;
+ }
+ if (type == typeof(char)) {
+ return TypeCode.Char;
+ }
+
+ // TODO: do we need this?
+ if (type == typeof(string)) {
+ return TypeCode.String;
+ }
+ if (type == typeof(bool)) {
+ return TypeCode.Boolean;
+ }
+ if (type == typeof(double)) {
+ return TypeCode.Double;
+ }
+ if (type == typeof(float)) {
+ return TypeCode.Single;
+ }
+ if (type == typeof(decimal)) {
+ return TypeCode.Decimal;
+ }
+ if (type == typeof(DateTime)) {
+ return TypeCode.DateTime;
+ }
+ return TypeCode.Object;
+ }
+
+ public static IEnumerable<Type> GetImplementedInterfaces(this Type type) {
+ return type.GetTypeInfo().ImplementedInterfaces;
+ }
+
+ public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic = false) {
+ var accessor = propertyInfo.GetMethod;
+ return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
+ }
+
+ public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic = false) {
+ var accessor = propertyInfo.SetMethod;
+ return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
+ }
+
+ public static MethodInfo GetAddMethod(this EventInfo eventInfo, bool nonPublic = false) {
+ var accessor = eventInfo.AddMethod;
+ return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
+ }
+
+ public static MethodInfo GetRemoveMethod(this EventInfo eventInfo, bool nonPublic = false) {
+ var accessor = eventInfo.RemoveMethod;
+ return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
+ }
+
+ public static MethodInfo GetRaiseMethod(this EventInfo eventInfo, bool nonPublic = false) {
+ var accessor = eventInfo.RaiseMethod;
+ return nonPublic || accessor == null || accessor.IsPublic ? accessor : null;
+ }
+
+ public static MethodInfo GetMethod(this Type type, string name) {
+ return type.GetTypeInfo().GetDeclaredMethod(name);
+ }
+
+ // TODO: FlattenHierarchy
+ // TODO: inherited!
+ public static MethodInfo GetMethod(this Type type, string name, Type[] parameterTypes) {
+ return type.GetTypeInfo().GetDeclaredMethods(name).WithSignature(parameterTypes).Single();
+ }
+
+ public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags) {
+ return type.GetMethods(name, bindingFlags).Single();
+ }
+
+ private static IEnumerable<MethodInfo> GetMethods(this Type type, string name, BindingFlags bindingFlags) {
+ return type.GetTypeInfo().GetDeclaredMethods(name).WithBindingFlags(bindingFlags);
+ }
+
+ public static MethodInfo GetMethod(this Delegate d) {
+ return d.GetMethodInfo();
+ }
+
+ // TODO: Callers should distinguish parameters from arguments. Stop using this method.
+ public static Type[] GetGenericArguments(this Type type) {
+ var info = type.GetTypeInfo();
+ return info.IsGenericTypeDefinition ? info.GenericTypeParameters : info.GenericTypeArguments;
+ }
+
+ public static Type[] GetGenericTypeArguments(this Type type) {
+ return type.GetTypeInfo().GenericTypeArguments;
+ }
+
+ public static Type[] GetGenericTypeParameters(this Type type) {
+ return type.GetTypeInfo().GenericTypeParameters;
+ }
+
+ public static bool IsAssignableFrom(this Type type, Type other) {
+ return type.GetTypeInfo().IsAssignableFrom(other.GetTypeInfo());
+ }
+
+ public static Type[] GetGenericParameterConstraints(this Type type) {
+ return type.GetTypeInfo().GetGenericParameterConstraints();
+ }
+
+ public static bool IsSubclassOf(this Type type, Type other) {
+ return type.GetTypeInfo().IsSubclassOf(other);
+ }
+
+ public static IEnumerable<Type> GetInterfaces(this Type type) {
+ return type.GetTypeInfo().ImplementedInterfaces;
+ }
+
+ public static Type[] GetRequiredCustomModifiers(this ParameterInfo parameter) {
+ return EmptyTypes;
+ }
+
+ public static Type[] GetOptionalCustomModifiers(this ParameterInfo parameter) {
+ return EmptyTypes;
+ }
+
+ public static IEnumerable<Module> GetModules(this Assembly assembly) {
+ return assembly.Modules;
+ }
+
+ private static string GetDefaultMemberName(this Type type) {
+ foreach (var ancestor in type.Ancestors()) {
+ var attr = ancestor.GetTypeInfo().GetCustomAttributes<DefaultMemberAttribute>().SingleOrDefault();
+ if (attr != null) {
+ return attr.MemberName;
+ }
+ }
+
+ return null;
+ }
+
+ public static IEnumerable<MemberInfo> GetDefaultMembers(this Type type) {
+ string defaultMemberName = type.GetDefaultMemberName();
+ if (defaultMemberName != null) {
+ return type.GetInheritedMembers(defaultMemberName).WithBindingFlags(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+ }
+
+ return Enumerable.Empty<MemberInfo>();
+ }
+#else
+ public static Type[] GetGenericTypeArguments(this Type type) {
+ return type.IsGenericType && !type.IsGenericTypeDefinition ? type.GetTypeInfo().GetGenericArguments() : null;
+ }
+
+ public static Type[] GetGenericTypeParameters(this Type type) {
+ return type.IsGenericTypeDefinition ? type.GetTypeInfo().GetGenericArguments() : null;
+ }
+
+ public static IEnumerable<Module> GetModules(this Assembly assembly) {
+ return assembly.GetModules();
+ }
+
+ public static IEnumerable<Type> GetImplementedInterfaces(this Type type) {
+ return type.GetInterfaces();
+ }
+
+ public static TypeCode GetTypeCode(this Type type) {
+ return Type.GetTypeCode(type);
+ }
+
+ public static MethodInfo GetMethodInfo(this Delegate d) {
+ return d.Method;
+ }
+
+ public static bool IsDefined(this Assembly assembly, Type attributeType) {
+ return assembly.IsDefined(attributeType, false);
+ }
+
+ public static T GetCustomAttribute<T>(this Assembly assembly, bool inherit = false) where T : Attribute {
+ return (T)Attribute.GetCustomAttribute(assembly, typeof(T), inherit);
+ }
+
+ public static T GetCustomAttribute<T>(this MemberInfo member, bool inherit = false) where T : Attribute {
+ return (T)Attribute.GetCustomAttribute(member, typeof(T), inherit);
+ }
+
+ public static IEnumerable<T> GetCustomAttributes<T>(this Assembly assembly, bool inherit = false) where T : Attribute {
+ return Attribute.GetCustomAttributes(assembly, typeof(T), inherit).Cast<T>();
+ }
+
+ public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo member, bool inherit = false) where T : Attribute {
+ return Attribute.GetCustomAttributes(member, typeof(T), inherit).Cast<T>();
+ }
+#endif
+
+ public static bool ContainsGenericParameters(this Type type) {
+ return type.GetTypeInfo().ContainsGenericParameters;
+ }
+
+ public static bool IsInterface(this Type type) {
+ return type.GetTypeInfo().IsInterface;
+ }
+
+ public static bool IsClass(this Type type) {
+ return type.GetTypeInfo().IsClass;
+ }
+
+ public static bool IsGenericType(this Type type) {
+ return type.GetTypeInfo().IsGenericType;
+ }
+
+ public static bool IsGenericTypeDefinition(this Type type) {
+ return type.GetTypeInfo().IsGenericTypeDefinition;
+ }
+
+ public static bool IsSealed(this Type type) {
+ return type.GetTypeInfo().IsSealed;
+ }
+
+ public static bool IsAbstract(this Type type) {
+ return type.GetTypeInfo().IsAbstract;
+ }
+
+ public static bool IsPublic(this Type type) {
+ return type.GetTypeInfo().IsPublic;
+ }
+
+ public static bool IsVisible(this Type type) {
+ return type.GetTypeInfo().IsVisible;
+ }
+
+ public static Type GetBaseType(this Type type) {
+ return type.GetTypeInfo().BaseType;
+ }
+
+ public static bool IsValueType(this Type type) {
+ return type.GetTypeInfo().IsValueType;
+ }
+
+ public static bool IsEnum(this Type type) {
+ return type.GetTypeInfo().IsEnum;
+ }
+
+ public static bool IsPrimitive(this Type type) {
+ return type.GetTypeInfo().IsPrimitive;
+ }
+
+ public static GenericParameterAttributes GetGenericParameterAttributes(this Type type) {
+ return type.GetTypeInfo().GenericParameterAttributes;
+ }
+
+ public static Type[] EmptyTypes = new Type[0];
+
+ public static object GetRawConstantValue(this FieldInfo field) {
+ if (!field.IsLiteral) {
+ throw new ArgumentException(field + " not a literal.");
+ }
+
+ object value = field.GetValue(null);
+ return field.FieldType.IsEnum() ? UnwrapEnumValue(value) : value;
+ }
+
+ /// <summary>
+ /// Converts a boxed enum value to the underlying integer value.
+ /// </summary>
+ public static object UnwrapEnumValue(object value) {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ switch (value.GetType().GetTypeCode()) {
+ case TypeCode.Byte:
+ return System.Convert.ToByte(value);
+
+ case TypeCode.Int16:
+ return System.Convert.ToInt16(value);
+
+ case TypeCode.Int32:
+ return System.Convert.ToInt32(value);
+
+ case TypeCode.Int64:
+ return System.Convert.ToInt64(value);
+
+ case TypeCode.SByte:
+ return System.Convert.ToSByte(value);
+
+ case TypeCode.UInt16:
+ return System.Convert.ToUInt16(value);
+
+ case TypeCode.UInt32:
+ return System.Convert.ToUInt32(value);
+
+ case TypeCode.UInt64:
+ return System.Convert.ToUInt64(value);
+
+ default:
+ throw new ArgumentException("Value must be a boxed enum.", "value");
+ }
+ }
+
+ #endregion
+
+#if FEATURE_REFEMIT
+#if FEATURE_ASSEMBLYBUILDER_DEFINEDYNAMICASSEMBLY
+ public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
+ return AssemblyBuilder.DefineDynamicAssembly(name, access);
+ }
+#else
+ public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
+ return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access);
+ }
+#endif
+#if !FEATURE_PDBEMIT
+ public static ModuleBuilder DefineDynamicModule(this AssemblyBuilder assembly, string name, bool emitDebugInfo) {
+ // ignore the flag
+ return assembly.DefineDynamicModule(name);
+ }
+#endif
+#endif
+
+ #region Signature and Type Formatting
+
+ // Generic type names have the arity (number of generic type paramters) appended at the end.
+ // For eg. the mangled name of System.List<T> is "List`1". This mangling is done to enable multiple
+ // generic types to exist as long as they have different arities.
+ public const char GenericArityDelimiter = '`';
+
+#if !WIN8
+ public static StringBuilder FormatSignature(StringBuilder result, MethodBase method) {
+ return FormatSignature(result, method, (t) => t.FullName);
+ }
+
+ public static StringBuilder FormatSignature(StringBuilder result, MethodBase method, Func<Type, string> nameDispenser) {
+ ContractUtils.RequiresNotNull(result, "result");
+ ContractUtils.RequiresNotNull(method, "method");
+ ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
+
+ MethodInfo methodInfo = method as MethodInfo;
+ if (methodInfo != null) {
+ FormatTypeName(result, methodInfo.ReturnType, nameDispenser);
+ result.Append(' ');
+ }
+
+#if FEATURE_REFEMIT
+ MethodBuilder builder = method as MethodBuilder;
+ if (builder != null) {
+ result.Append(builder.Signature);
+ return result;
+ }
+
+ ConstructorBuilder cb = method as ConstructorBuilder;
+ if (cb != null) {
+ result.Append(cb.Signature);
+ return result;
+ }
+#endif
+ FormatTypeName(result, method.DeclaringType, nameDispenser);
+ result.Append("::");
+ result.Append(method.Name);
+
+ if (!method.IsConstructor) {
+ FormatTypeArgs(result, method.GetGenericArguments(), nameDispenser);
+ }
+
+ result.Append("(");
+
+ if (!method.ContainsGenericParameters) {
+ ParameterInfo[] ps = method.GetParameters();
+ for (int i = 0; i < ps.Length; i++) {
+ if (i > 0) result.Append(", ");
+ FormatTypeName(result, ps[i].ParameterType, nameDispenser);
+ if (!System.String.IsNullOrEmpty(ps[i].Name)) {
+ result.Append(" ");
+ result.Append(ps[i].Name);
+ }
+ }
+ } else {
+ result.Append("?");
+ }
+
+ result.Append(")");
+ return result;
+ }
+#endif
+
+ public static StringBuilder FormatTypeName(StringBuilder result, Type type) {
+ return FormatTypeName(result, type, (t) => t.FullName);
+ }
+
+ public static StringBuilder FormatTypeName(StringBuilder result, Type type, Func<Type, string> nameDispenser) {
+ ContractUtils.RequiresNotNull(result, "result");
+ ContractUtils.RequiresNotNull(type, "type");
+ ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
+
+ if (type.IsGenericType()) {
+ Type genType = type.GetGenericTypeDefinition();
+ string genericName = nameDispenser(genType).Replace('+', '.');
+ int tickIndex = genericName.IndexOf('`');
+ result.Append(tickIndex != -1 ? genericName.Substring(0, tickIndex) : genericName);
+
+ Type[] typeArgs = type.GetGenericArguments();
+ if (type.IsGenericTypeDefinition()) {
+ result.Append('<');
+ result.Append(',', typeArgs.Length - 1);
+ result.Append('>');
+ } else {
+ FormatTypeArgs(result, typeArgs, nameDispenser);
+ }
+ } else if (type.IsGenericParameter) {
+ result.Append(type.Name);
+ } else {
+ // cut namespace off:
+ result.Append(nameDispenser(type).Replace('+', '.'));
+ }
+ return result;
+ }
+
+ public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types) {
+ return FormatTypeArgs(result, types, (t) => t.FullName);
+ }
+
+ public static StringBuilder FormatTypeArgs(StringBuilder result, Type[] types, Func<Type, string> nameDispenser) {
+ ContractUtils.RequiresNotNull(result, "result");
+ ContractUtils.RequiresNotNullItems(types, "types");
+ ContractUtils.RequiresNotNull(nameDispenser, "nameDispenser");
+
+ if (types.Length > 0) {
+ result.Append("<");
+
+ for (int i = 0; i < types.Length; i++) {
+ if (i > 0) result.Append(", ");
+ FormatTypeName(result, types[i], nameDispenser);
+ }
+
+ result.Append(">");
+ }
+ return result;
+ }
+
+ internal static string ToValidTypeName(string str) {
+ if (String.IsNullOrEmpty(str)) {
+ return "_";
+ }
+
+ StringBuilder sb = new StringBuilder(str);
+ for (int i = 0; i < str.Length; i++) {
+ if (str[i] == '\0' || str[i] == '.' || str[i] == '*' || str[i] == '+' || str[i] == '[' || str[i] == ']' || str[i] == '\\') {
+ sb[i] = '_';
+ }
+ }
+ return sb.ToString();
+ }
+
+ public static string GetNormalizedTypeName(Type type) {
+ string name = type.Name;
+ if (type.IsGenericType()) {
+ return GetNormalizedTypeName(name);
+ }
+ return name;
+ }
+
+ public static string GetNormalizedTypeName(string typeName) {
+ Debug.Assert(typeName.IndexOf('.') == -1); // This is the simple name, not the full name
+ int backtick = typeName.IndexOf(ReflectionUtils.GenericArityDelimiter);
+ if (backtick != -1) return typeName.Substring(0, backtick);
+ return typeName;
+ }
+
+ #endregion
+
+ #region Delegates and Dynamic Methods
+
+#if WP75
+ /// <summary>
+ /// Creates an open delegate for the given (dynamic)method.
+ /// </summary>
+ public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
+ return CreateDelegate(methodInfo, delegateType, null);
+ }
+
+ /// <summary>
+ /// Creates a closed delegate for the given (dynamic)method.
+ /// </summary>
+ public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
+ return Delegate.CreateDelegate(delegateType, target, methodInfo);
+ }
+#elif !WIN8
+ /// <summary>
+ /// Creates an open delegate for the given (dynamic)method.
+ /// </summary>
+ public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType) {
+ return CreateDelegate(methodInfo, delegateType, null);
+ }
+
+ /// <summary>
+ /// Creates a closed delegate for the given (dynamic)method.
+ /// </summary>
+ public static Delegate CreateDelegate(this MethodInfo methodInfo, Type delegateType, object target) {
+#if FEATURE_REFEMIT
+ DynamicMethod dm = methodInfo as DynamicMethod;
+ if (dm != null) {
+ return dm.CreateDelegate(delegateType, target);
+#endif
+ return Delegate.CreateDelegate(delegateType, target, methodInfo);
+ }
+#endif
+
+#if FEATURE_LCG
+ public static bool IsDynamicMethod(MethodBase method) {
+ return !PlatformAdaptationLayer.IsCompactFramework && IsDynamicMethodInternal(method);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool IsDynamicMethodInternal(MethodBase method) {
+ return method is DynamicMethod;
+ }
+#else
+ public static bool IsDynamicMethod(MethodBase method) {
+ return false;
+ }
+#endif
+
+ public static void GetDelegateSignature(Type delegateType, out ParameterInfo[] parameterInfos, out ParameterInfo returnInfo) {
+ ContractUtils.RequiresNotNull(delegateType, "delegateType");
+
+ MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
+ ContractUtils.Requires(invokeMethod != null, "delegateType", Strings.InvalidDelegate);
+
+ parameterInfos = invokeMethod.GetParameters();
+ returnInfo = invokeMethod.ReturnParameter;
+ }
+
+ /// <summary>
+ /// Gets a Func of CallSite, object * paramCnt, object delegate type
+ /// that's suitable for use in a non-strongly typed call site.
+ /// </summary>
+ public static Type GetObjectCallSiteDelegateType(int paramCnt) {
+ switch (paramCnt) {
+ case 0: return typeof(Func<CallSite, object, object>);
+ case 1: return typeof(Func<CallSite, object, object, object>);
+ case 2: return typeof(Func<CallSite, object, object, object, object>);
+ case 3: return typeof(Func<CallSite, object, object, object, object, object>);
+ case 4: return typeof(Func<CallSite, object, object, object, object, object, object>);
+ case 5: return typeof(Func<CallSite, object, object, object, object, object, object, object>);
+ case 6: return typeof(Func<CallSite, object, object, object, object, object, object, object, object>);
+ case 7: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object>);
+ case 8: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object>);
+ case 9: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object>);
+ case 10: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object>);
+ case 11: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object>);
+ case 12: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
+ case 13: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
+ case 14: return typeof(Func<CallSite, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>);
+ default:
+#if FEATURE_REFEMIT
+ Type[] paramTypes = new Type[paramCnt + 2];
+ paramTypes[0] = typeof(CallSite);
+ paramTypes[1] = typeof(object);
+ for (int i = 0; i < paramCnt; i++) {
+ paramTypes[i + 2] = typeof(object);
+ }
+ return Snippets.Shared.DefineDelegate("InvokeDelegate" + paramCnt, typeof(object), paramTypes);
+#else
+ throw new NotSupportedException("Signature not supported on this platform.");
+#endif
+ }
+ }
+
+#if FEATURE_LCG
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework")]
+ internal static DynamicMethod RawCreateDynamicMethod(string name, Type returnType, Type[] parameterTypes) {
+#if SILVERLIGHT // Module-hosted DynamicMethod is not available in SILVERLIGHT
+ return new DynamicMethod(name, returnType, parameterTypes);
+#else
+ //
+ // WARNING: we set restrictedSkipVisibility == true (last parameter)
+ // setting this bit will allow accessing nonpublic members
+ // for more information see http://msdn.microsoft.com/en-us/library/bb348332.aspx
+ //
+ return new DynamicMethod(name, returnType, parameterTypes, true);
+#endif
+ }
+#endif
+
+ #endregion
+
+ #region Methods and Parameters
+
+ public static MethodBase[] GetMethodInfos(MemberInfo[] members) {
+ return ArrayUtils.ConvertAll<MemberInfo, MethodBase>(
+ members,
+ delegate(MemberInfo inp) { return (MethodBase)inp; });
+ }
+
+ public static Type[] GetParameterTypes(ParameterInfo[] parameterInfos) {
+ return GetParameterTypes((IList<ParameterInfo>)parameterInfos);
+ }
+
+ public static Type[] GetParameterTypes(IList<ParameterInfo> parameterInfos) {
+ Type[] result = new Type[parameterInfos.Count];
+ for (int i = 0; i < result.Length; i++) {
+ result[i] = parameterInfos[i].ParameterType;
+ }
+ return result;
+ }
+
+ public static Type GetReturnType(this MethodBase mi) {
+ return (mi.IsConstructor) ? mi.DeclaringType : ((MethodInfo)mi).ReturnType;
+ }
+
+ public static bool SignatureEquals(MethodInfo method, params Type[] requiredSignature) {
+ ContractUtils.RequiresNotNull(method, "method");
+
+ Type[] actualTypes = ReflectionUtils.GetParameterTypes(method.GetParameters());
+ Debug.Assert(actualTypes.Length == requiredSignature.Length - 1);
+ int i = 0;
+ while (i < actualTypes.Length) {
+ if (actualTypes[i] != requiredSignature[i]) return false;
+ i++;
+ }
+
+ return method.ReturnType == requiredSignature[i];
+ }
+
+#if CLR2 && !SILVERLIGHT
+ private static Type _ExtensionAttributeType;
+#endif
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ public static bool IsExtension(this MemberInfo member) {
+ var dlrExtension = typeof(ExtensionAttribute);
+ if (member.IsDefined(dlrExtension, false)) {
+ return true;
+ }
+
+#if CLR2 && !SILVERLIGHT
+ if (_ExtensionAttributeType == null) {
+ try {
+ _ExtensionAttributeType = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
+ .GetType("System.Runtime.CompilerServices.ExtensionAttribute");
+ } catch {
+ _ExtensionAttributeType = dlrExtension;
+ }
+ }
+
+ if (_ExtensionAttributeType != dlrExtension) {
+ return member.IsDefined(_ExtensionAttributeType, false);
+ }
+#endif
+ return false;
+ }
+
+ public static bool IsOutParameter(this ParameterInfo pi) {
+ // not using IsIn/IsOut properties as they are not available in Silverlight:
+ return pi.ParameterType.IsByRef && (pi.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out;
+ }
+
+ /// <summary>
+ /// Returns <c>true</c> if the specified parameter is mandatory, i.e. is not optional and doesn't have a default value.
+ /// </summary>
+ public static bool IsMandatory(this ParameterInfo pi) {
+ return (pi.Attributes & ParameterAttributes.Optional) == 0 && !pi.HasDefaultValue();
+ }
+
+ public static bool HasDefaultValue(this ParameterInfo pi) {
+#if !FEATURE_DEFAULT_PARAMETER_VALUE
+ return pi.IsDefined(typeof(DefaultParameterValueAttribute), false);
+#else
+ return (pi.Attributes & ParameterAttributes.HasDefault) != 0;
+#endif
+ }
+
+ public static bool ProhibitsNull(this ParameterInfo parameter) {
+ return parameter.IsDefined(typeof(NotNullAttribute), false);
+ }
+
+ public static bool ProhibitsNullItems(this ParameterInfo parameter) {
+ return parameter.IsDefined(typeof(NotNullItemsAttribute), false);
+ }
+
+ public static bool IsParamArray(this ParameterInfo parameter) {
+ return parameter.IsDefined(typeof(ParamArrayAttribute), false);
+ }
+
+ public static bool IsParamDictionary(this ParameterInfo parameter) {
+ return parameter.IsDefined(typeof(ParamDictionaryAttribute), false);
+ }
+
+ public static bool IsParamsMethod(MethodBase method) {
+ return IsParamsMethod(method.GetParameters());
+ }
+
+ public static bool IsParamsMethod(ParameterInfo[] pis) {
+ foreach (ParameterInfo pi in pis) {
+ if (pi.IsParamArray() || pi.IsParamDictionary()) return true;
+ }
+ return false;
+ }
+
+ public static object GetDefaultValue(this ParameterInfo info) {
+#if !FEATURE_DEFAULT_PARAMETER_VALUE
+ if (info.IsOptional) {
+ return info.ParameterType == typeof(object) ? Missing.Value : ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(info.ParameterType);
+ }
+
+ var defaultValueAttribute = info.GetCustomAttributes(typeof(DefaultParameterValueAttribute), false);
+ if (defaultValueAttribute.Length > 0) {
+ return ((DefaultParameterValueAttribute)defaultValueAttribute[0]).Value;
+ }
+
+ return null;
+#else
+ return info.DefaultValue;
+#endif
+ }
+
+ #endregion
+
+ #region Types
+
+ /// <summary>
+ /// Yields all ancestors of the given type including the type itself.
+ /// Does not include implemented interfaces.
+ /// </summary>
+ public static IEnumerable<Type> Ancestors(this Type type) {
+ do {
+ yield return type;
+ type = type.GetTypeInfo().BaseType;
+ } while (type != null);
+ }
+
+ /// <summary>
+ /// Like Type.GetInterfaces, but only returns the interfaces implemented by this type
+ /// and not its parents.
+ /// </summary>
+ public static List<Type> GetDeclaredInterfaces(Type type) {
+ IEnumerable<Type> baseInterfaces = (type.GetBaseType() != null) ? type.GetBaseType().GetInterfaces() : EmptyTypes;
+ List<Type> interfaces = new List<Type>();
+ foreach (Type iface in type.GetInterfaces()) {
+ if (!baseInterfaces.Contains(iface)) {
+ interfaces.Add(iface);
+ }
+ }
+ return interfaces;
+ }
+
+ internal static IEnumerable<TypeInfo> GetAllTypesFromAssembly(Assembly asm) {
+ // TODO: WP7, SL5
+#if SILVERLIGHT // ReflectionTypeLoadException
+ try {
+ return asm.GetTypes();
+ } catch (Exception) {
+ return ReflectionUtils.EmptyTypes;
+ }
+#elif WIN8
+ return asm.DefinedTypes;
+#else
+ foreach (Module module in asm.GetModules()) {
+ Type[] moduleTypes;
+ try {
+ moduleTypes = module.GetTypes();
+ } catch (ReflectionTypeLoadException e) {
+ moduleTypes = e.Types;
+ }
+
+ foreach (var type in moduleTypes) {
+ if (type != null) {
+ yield return type;
+ }
+ }
+ }
+#endif
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ internal static IEnumerable<TypeInfo> GetAllTypesFromAssembly(Assembly assembly, bool includePrivateTypes) {
+ ContractUtils.RequiresNotNull(assembly, "assembly");
+
+ if (includePrivateTypes) {
+ return GetAllTypesFromAssembly(assembly);
+ }
+
+ try {
+#if WIN8
+ return assembly.ExportedTypes.Select(t => t.GetTypeInfo());
+#else
+ return assembly.GetExportedTypes();
+#endif
+ } catch (NotSupportedException) {
+ // GetExportedTypes does not work with dynamic assemblies
+ } catch (Exception) {
+ // Some type loads may cause exceptions. Unfortunately, there is no way to ask GetExportedTypes
+ // for just the list of types that we successfully loaded.
+ }
+
+ return GetAllTypesFromAssembly(assembly).Where(type => type.IsPublic);
+ }
+
+ #endregion
+
+ #region Type Builder
+#if FEATURE_REFEMIT
+
+#if WIN8 // TODO: what is ReservedMask?
+ private const MethodAttributes MethodAttributesToEraseInOveride = MethodAttributes.Abstract | (MethodAttributes)0xD000;
+#else
+ private const MethodAttributes MethodAttributesToEraseInOveride = MethodAttributes.Abstract | MethodAttributes.ReservedMask;
+#endif
+
+ public static MethodBuilder DefineMethodOverride(TypeBuilder tb, MethodAttributes extra, MethodInfo decl) {
+ MethodAttributes finalAttrs = (decl.Attributes & ~MethodAttributesToEraseInOveride) | extra;
+ if (!decl.DeclaringType.GetTypeInfo().IsInterface) {
+ finalAttrs &= ~MethodAttributes.NewSlot;
+ }
+
+ if ((extra & MethodAttributes.MemberAccessMask) != 0) {
+ // remove existing member access, add new member access
+ finalAttrs &= ~MethodAttributes.MemberAccessMask;
+ finalAttrs |= extra;
+ }
+
+ MethodBuilder impl = tb.DefineMethod(decl.Name, finalAttrs, decl.CallingConvention);
+ CopyMethodSignature(decl, impl, false);
+ return impl;
+ }
+
+ public static void CopyMethodSignature(MethodInfo from, MethodBuilder to, bool substituteDeclaringType) {
+ ParameterInfo[] paramInfos = from.GetParameters();
+ Type[] parameterTypes = new Type[paramInfos.Length];
+ Type[][] parameterRequiredModifiers = null, parameterOptionalModifiers = null;
+ Type[] returnRequiredModifiers = null, returnOptionalModifiers = null;
+
+#if FEATURE_CUSTOM_MODIFIERS
+ returnRequiredModifiers = from.ReturnParameter.GetRequiredCustomModifiers();
+ returnOptionalModifiers = from.ReturnParameter.GetOptionalCustomModifiers();
+#endif
+ for (int i = 0; i < paramInfos.Length; i++) {
+ if (substituteDeclaringType && paramInfos[i].ParameterType == from.DeclaringType) {
+ parameterTypes[i] = to.DeclaringType;
+ } else {
+ parameterTypes[i] = paramInfos[i].ParameterType;
+ }
+
+#if FEATURE_CUSTOM_MODIFIERS
+ var mods = paramInfos[i].GetRequiredCustomModifiers();
+ if (mods.Length > 0) {
+ if (parameterRequiredModifiers == null) {
+ parameterRequiredModifiers = new Type[paramInfos.Length][];
+ }
+
+ parameterRequiredModifiers[i] = mods;
+ }
+
+ mods = paramInfos[i].GetOptionalCustomModifiers();
+ if (mods.Length > 0) {
+ if (parameterOptionalModifiers == null) {
+ parameterOptionalModifiers = new Type[paramInfos.Length][];
+ }
+
+ parameterOptionalModifiers[i] = mods;
+ }
+#endif
+ }
+
+ to.SetSignature(
+ from.ReturnType, returnRequiredModifiers, returnOptionalModifiers,
+ parameterTypes, parameterRequiredModifiers, parameterOptionalModifiers
+ );
+
+ CopyGenericMethodAttributes(from, to);
+
+ for (int i = 0; i < paramInfos.Length; i++) {
+ to.DefineParameter(i + 1, paramInfos[i].Attributes, paramInfos[i].Name);
+ }
+ }
+
+ private static void CopyGenericMethodAttributes(MethodInfo from, MethodBuilder to) {
+ if (from.IsGenericMethodDefinition) {
+ Type[] args = from.GetGenericArguments();
+ string[] names = new string[args.Length];
+ for (int i = 0; i < args.Length; i++) {
+ names[i] = args[i].Name;
+ }
+ var builders = to.DefineGenericParameters(names);
+ for (int i = 0; i < args.Length; i++) {
+ // Copy template parameter attributes
+ builders[i].SetGenericParameterAttributes(args[i].GetGenericParameterAttributes());
+
+ // Copy template parameter constraints
+ Type[] constraints = args[i].GetGenericParameterConstraints();
+ List<Type> interfaces = new List<Type>(constraints.Length);
+ foreach (Type constraint in constraints) {
+ if (constraint.IsInterface()) {
+ interfaces.Add(constraint);
+ } else {
+ builders[i].SetBaseTypeConstraint(constraint);
+ }
+ }
+ if (interfaces.Count > 0) {
+ builders[i].SetInterfaceConstraints(interfaces.ToArray());
+ }
+ }
+ }
+ }
+#endif
+ #endregion
+
+ #region Extension Methods
+
+ public static IEnumerable<MethodInfo> GetVisibleExtensionMethods(Assembly assembly) {
+#if FEATURE_METADATA_READER
+ if (!assembly.IsDynamic && AppDomain.CurrentDomain.IsFullyTrusted) {
+ try {
+ return GetVisibleExtensionMethodsFast(assembly);
+ } catch (SecurityException) {
+ // full-demand can still fail if there is a partial trust domain on the stack
+ }
+ }
+#endif
+ return GetVisibleExtensionMethodsSlow(assembly);
+ }
+
+#if FEATURE_METADATA_READER
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2116:AptcaMethodsShouldOnlyCallAptcaMethods")]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static IEnumerable<MethodInfo> GetVisibleExtensionMethodsFast(Assembly assembly) {
+ // Security: link demand
+ return MetadataServices.GetVisibleExtensionMethodInfos(assembly);
+ }
+#endif
+
+ // TODO: make internal
+ // TODO: handle type load exceptions
+ public static IEnumerable<MethodInfo> GetVisibleExtensionMethodsSlow(Assembly assembly) {
+ var ea = typeof(ExtensionAttribute);
+ if (assembly.IsDefined(ea)) {
+ foreach (TypeInfo type in ReflectionUtils.GetAllTypesFromAssembly(assembly)) {
+ if ((type.IsPublic || type.IsNestedPublic) &&
+ type.IsAbstract &&
+ type.IsSealed &&
+ type.IsDefined(ea, false)) {
+
+ foreach (MethodInfo method in type.AsType().GetDeclaredMethods()) {
+ if (method.IsPublic && method.IsStatic && method.IsDefined(ea, false)) {
+ yield return method;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Value is null if there are no extension methods in the assembly.
+ private static Dictionary<Assembly, Dictionary<string, List<ExtensionMethodInfo>>> _extensionMethodsCache;
+
+ /// <summary>
+ /// Enumerates extension methods in given assembly. Groups the methods by declaring namespace.
+ /// Uses a global cache if <paramref name="useCache"/> is true.
+ /// </summary>
+ public static IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>> GetVisibleExtensionMethodGroups(Assembly/*!*/ assembly, bool useCache) {
+#if !CLR2 && FEATURE_REFEMIT
+ useCache &= !assembly.IsDynamic;
+#endif
+ if (useCache) {
+ if (_extensionMethodsCache == null) {
+ _extensionMethodsCache = new Dictionary<Assembly, Dictionary<string, List<ExtensionMethodInfo>>>();
+ }
+
+ lock (_extensionMethodsCache) {
+ Dictionary<string, List<ExtensionMethodInfo>> existing;
+ if (_extensionMethodsCache.TryGetValue(assembly, out existing)) {
+ return EnumerateExtensionMethods(existing);
+ }
+ }
+ }
+
+ Dictionary<string, List<ExtensionMethodInfo>> result = null;
+ foreach (MethodInfo method in ReflectionUtils.GetVisibleExtensionMethodsSlow(assembly)) {
+ if (method.DeclaringType == null || method.DeclaringType.IsGenericTypeDefinition()) {
+ continue;
+ }
+
+ var parameters = method.GetParameters();
+ if (parameters.Length == 0) {
+ continue;
+ }
+
+ Type type = parameters[0].ParameterType;
+ if (type.IsByRef || type.IsPointer) {
+ continue;
+ }
+
+ string ns = method.DeclaringType.Namespace ?? String.Empty;
+ List<ExtensionMethodInfo> extensions = null;
+
+ if (result == null) {
+ result = new Dictionary<string, List<ExtensionMethodInfo>>();
+ }
+
+ if (!result.TryGetValue(ns, out extensions)) {
+ result.Add(ns, extensions = new List<ExtensionMethodInfo>());
+ }
+
+ extensions.Add(new ExtensionMethodInfo(type, method));
+ }
+
+ if (useCache) {
+ lock (_extensionMethodsCache) {
+ _extensionMethodsCache[assembly] = result;
+ }
+ }
+
+ return EnumerateExtensionMethods(result);
+ }
+
+ // TODO: GetVisibleExtensionMethods(Hashset<string> namespaces, Type type, string methodName) : IEnumerable<MethodInfo> {}
+
+ private static IEnumerable<KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>> EnumerateExtensionMethods(Dictionary<string, List<ExtensionMethodInfo>> dict) {
+ if (dict != null) {
+ foreach (var entry in dict) {
+ yield return new KeyValuePair<string, IEnumerable<ExtensionMethodInfo>>(entry.Key, new ReadOnlyCollection<ExtensionMethodInfo>(entry.Value));
+ }
+ }
+ }
+
+ #endregion
+
+ #region Generic Types
+
+ internal static Dictionary<Type, Type> BindGenericParameters(Type/*!*/ openType, Type/*!*/ closedType, bool ignoreUnboundParameters) {
+ var binding = new Dictionary<Type, Type>();
+ BindGenericParameters(openType, closedType, (parameter, type) => {
+ Type existing;
+ if (binding.TryGetValue(parameter, out existing)) {
+ return type == existing;
+ }
+
+ binding[parameter] = type;
+
+ return true;
+ });
+
+ return ConstraintsViolated(binding, ignoreUnboundParameters) ? null : binding;
+ }
+
+ /// <summary>
+ /// Binds occurances of generic parameters in <paramref name="openType"/> against corresponding types in <paramref name="closedType"/>.
+ /// Invokes <paramref name="binder"/>(parameter, type) for each such binding.
+ /// Returns false if the <paramref name="openType"/> is structurally different from <paramref name="closedType"/> or if the binder returns false.
+ /// </summary>
+ internal static bool BindGenericParameters(Type/*!*/ openType, Type/*!*/ closedType, Func<Type, Type, bool>/*!*/ binder) {
+ if (openType.IsGenericParameter) {
+ return binder(openType, closedType);
+ }
+
+ if (openType.IsArray) {
+ if (!closedType.IsArray) {
+ return false;
+ }
+ return BindGenericParameters(openType.GetElementType(), closedType.GetElementType(), binder);
+ }
+
+ if (!openType.IsGenericType() || !closedType.IsGenericType()) {
+ return openType == closedType;
+ }
+
+ if (openType.GetGenericTypeDefinition() != closedType.GetGenericTypeDefinition()) {
+ return false;
+ }
+
+ Type[] closedArgs = closedType.GetGenericArguments();
+ Type[] openArgs = openType.GetGenericArguments();
+
+ for (int i = 0; i < openArgs.Length; i++) {
+ if (!BindGenericParameters(openArgs[i], closedArgs[i], binder)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ internal static bool ConstraintsViolated(Dictionary<Type, Type>/*!*/ binding, bool ignoreUnboundParameters) {
+ foreach (var entry in binding) {
+ if (ConstraintsViolated(entry.Key, entry.Value, binding, ignoreUnboundParameters)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal static bool ConstraintsViolated(Type/*!*/ genericParameter, Type/*!*/ closedType, Dictionary<Type, Type>/*!*/ binding, bool ignoreUnboundParameters) {
+ if ((genericParameter.GetGenericParameterAttributes() & GenericParameterAttributes.ReferenceTypeConstraint) != 0 && closedType.IsValueType()) {
+ // value type to parameter type constrained as class
+ return true;
+ }
+
+ if ((genericParameter.GetGenericParameterAttributes() & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0 &&
+ (!closedType.IsValueType() || (closedType.IsGenericType() && closedType.GetGenericTypeDefinition() == typeof(Nullable<>)))) {
+ // nullable<T> or class/interface to parameter type constrained as struct
+ return true;
+ }
+
+ if ((genericParameter.GetGenericParameterAttributes() & GenericParameterAttributes.DefaultConstructorConstraint) != 0 &&
+ (!closedType.IsValueType() && closedType.GetConstructor(ReflectionUtils.EmptyTypes) == null)) {
+ // reference type w/o a default constructor to type constrianed as new()
+ return true;
+ }
+
+ Type[] constraints = genericParameter.GetGenericParameterConstraints();
+ for (int i = 0; i < constraints.Length; i++) {
+ Type instantiation = InstantiateConstraint(constraints[i], binding);
+
+ if (instantiation == null) {
+ if (ignoreUnboundParameters) {
+ continue;
+ } else {
+ return true;
+ }
+ }
+
+ if (!instantiation.IsAssignableFrom(closedType)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal static Type InstantiateConstraint(Type/*!*/ constraint, Dictionary<Type, Type>/*!*/ binding) {
+ Debug.Assert(!constraint.IsArray && !constraint.IsByRef && !constraint.IsGenericTypeDefinition());
+ if (!constraint.ContainsGenericParameters()) {
+ return constraint;
+ }
+
+ Type closedType;
+ if (constraint.IsGenericParameter) {
+ return binding.TryGetValue(constraint, out closedType) ? closedType : null;
+ }
+
+ Type[] args = constraint.GetGenericArguments();
+ for (int i = 0; i < args.Length; i++) {
+ if ((args[i] = InstantiateConstraint(args[i], binding)) == null) {
+ return null;
+ }
+ }
+
+ return constraint.GetGenericTypeDefinition().MakeGenericType(args);
+ }
+
+ #endregion
+ }
+
+ public struct ExtensionMethodInfo : IEquatable<ExtensionMethodInfo> {
+ private readonly Type/*!*/ _extendedType; // cached type of the first parameter
+ private readonly MethodInfo/*!*/ _method;
+
+ internal ExtensionMethodInfo(Type/*!*/ extendedType, MethodInfo/*!*/ method) {
+ Assert.NotNull(extendedType, method);
+ _extendedType = extendedType;
+ _method = method;
+ }
+
+ public Type/*!*/ ExtendedType {
+ get { return _extendedType; }
+ }
+
+ public MethodInfo/*!*/ Method {
+ get { return _method; }
+ }
+
+ public override bool Equals(object obj) {
+ return obj is ExtensionMethodInfo && Equals((ExtensionMethodInfo)obj);
+ }
+
+ public bool Equals(ExtensionMethodInfo other) {
+ return _method.Equals(other._method);
+ }
+
+ public static bool operator ==(ExtensionMethodInfo self, ExtensionMethodInfo other) {
+ return self.Equals(other);
+ }
+
+ public static bool operator !=(ExtensionMethodInfo self, ExtensionMethodInfo other) {
+ return !self.Equals(other);
+ }
+
+ public override int GetHashCode() {
+ return _method.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines if a given type matches the type that the method extends.
+ /// The match might be non-trivial if the extended type is an open generic type with constraints.
+ /// </summary>
+ public bool IsExtensionOf(Type/*!*/ type) {
+ ContractUtils.RequiresNotNull(type, "type");
+#if FEATURE_TYPE_EQUIVALENCE
+ if (type.IsEquivalentTo(ExtendedType)) {
+ return true;
+ }
+#else
+ if (type == _extendedType) {
+ return true;
+ }
+#endif
+ if (!_extendedType.GetTypeInfo().ContainsGenericParameters) {
+ return false;
+ }
+
+ //
+ // Ignores constraints that can't be instantiated given the information we have (type of the first parameter).
+ //
+ // For example,
+ // void Foo<S, T>(this S x, T y) where S : T;
+ //
+ // We make such methods available on all types.
+ // If they are not called with arguments that satisfy the constraint the overload resolver might fail.
+ //
+ return ReflectionUtils.BindGenericParameters(_extendedType, type, true) != null;
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/StringUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/StringUtils.cs
new file mode 100644
index 00000000000..934021ff69b
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/StringUtils.cs
@@ -0,0 +1,269 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace Microsoft.Scripting.Utils {
+ public static class StringUtils {
+
+ public static Encoding DefaultEncoding {
+ get {
+#if FEATURE_ENCODING
+ return Encoding.Default;
+#else
+ return Encoding.UTF8;
+#endif
+ }
+ }
+
+ public static string GetSuffix(string str, char separator, bool includeSeparator) {
+ ContractUtils.RequiresNotNull(str, "str");
+ int last = str.LastIndexOf(separator);
+ return (last != -1) ? str.Substring(includeSeparator ? last : last + 1) : null;
+ }
+
+ public static string GetLongestPrefix(string str, char separator, bool includeSeparator) {
+ ContractUtils.RequiresNotNull(str, "str");
+ int last = str.LastIndexOf(separator);
+ return (last != -1) ? str.Substring(0, (includeSeparator || last == 0) ? last : last - 1) : null;
+ }
+
+ public static int CountOf(string str, char c) {
+ if (System.String.IsNullOrEmpty(str)) return 0;
+
+ int result = 0;
+ for (int i = 0; i < str.Length; i++) {
+ if (c == str[i]) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ public static string[] Split(string str, string separator, int maxComponents, StringSplitOptions options) {
+ ContractUtils.RequiresNotNull(str, "str");
+#if SILVERLIGHT || WP75
+ if (string.IsNullOrEmpty(separator)) throw new ArgumentNullException("separator");
+
+ bool keep_empty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries;
+
+ List<string> result = new List<string>(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1);
+
+ int i = 0;
+ int next;
+ while (maxComponents > 1 && i < str.Length && (next = str.IndexOf(separator, i)) != -1) {
+
+ if (next > i || keep_empty) {
+ result.Add(str.Substring(i, next - i));
+ maxComponents--;
+ }
+
+ i = next + separator.Length;
+ }
+
+ if (i < str.Length || keep_empty) {
+ result.Add(str.Substring(i));
+ }
+
+ return result.ToArray();
+#else
+ return str.Split(new string[] { separator }, maxComponents, options);
+#endif
+ }
+
+ public static string[] Split(string str, char[] separators, int maxComponents, StringSplitOptions options) {
+ ContractUtils.RequiresNotNull(str, "str");
+#if SILVERLIGHT || WP75
+ if (separators == null) return SplitOnWhiteSpace(str, maxComponents, options);
+
+ bool keep_empty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries;
+
+ List<string> result = new List<string>(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1);
+
+ int i = 0;
+ int next;
+ while (maxComponents > 1 && i < str.Length && (next = str.IndexOfAny(separators, i)) != -1) {
+
+ if (next > i || keep_empty) {
+ result.Add(str.Substring(i, next - i));
+ maxComponents--;
+ }
+
+ i = next + 1;
+ }
+
+ if (i < str.Length || keep_empty) {
+ result.Add(str.Substring(i));
+ }
+
+ return result.ToArray();
+#else
+ return str.Split(separators, maxComponents, options);
+#endif
+ }
+
+#if SILVERLIGHT|| WP75
+ public static string[] SplitOnWhiteSpace(string str, int maxComponents, StringSplitOptions options) {
+ ContractUtils.RequiresNotNull(str, "str");
+
+ bool keep_empty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries;
+
+ List<string> result = new List<string>(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1);
+
+ int i = 0;
+ int next;
+ while (maxComponents > 1 && i < str.Length && (next = IndexOfWhiteSpace(str, i)) != -1) {
+
+ if (next > i || keep_empty) {
+ result.Add(str.Substring(i, next - i));
+ maxComponents--;
+ }
+
+ i = next + 1;
+ }
+
+ if (i < str.Length || keep_empty) {
+ result.Add(str.Substring(i));
+ }
+
+ return result.ToArray();
+ }
+
+ public static int IndexOfWhiteSpace(string str, int start) {
+ ContractUtils.RequiresNotNull(str, "str");
+ if (start < 0 || start > str.Length) throw new ArgumentOutOfRangeException("start");
+
+ while (start < str.Length && !Char.IsWhiteSpace(str[start])) start++;
+
+ return (start == str.Length) ? -1 : start;
+ }
+#endif
+
+ /// <summary>
+ /// Splits text and optionally indents first lines - breaks along words, not characters.
+ /// </summary>
+ public static string SplitWords(string text, bool indentFirst, int lineWidth) {
+ ContractUtils.RequiresNotNull(text, "text");
+
+ const string indent = " ";
+
+ if (text.Length <= lineWidth || lineWidth <= 0) {
+ if (indentFirst) return indent + text;
+ return text;
+ }
+
+ StringBuilder res = new StringBuilder();
+ int start = 0, len = lineWidth;
+ while (start != text.Length) {
+ if (len >= lineWidth) {
+ // find last space to break on
+ while (len != 0 && !Char.IsWhiteSpace(text[start + len - 1]))
+ len--;
+ }
+
+ if (res.Length != 0) res.Append(' ');
+ if (indentFirst || res.Length != 0) res.Append(indent);
+
+ if (len == 0) {
+ int copying = System.Math.Min(lineWidth, text.Length - start);
+ res.Append(text, start, copying);
+ start += copying;
+ } else {
+ res.Append(text, start, len);
+ start += len;
+ }
+ res.AppendLine();
+ len = System.Math.Min(lineWidth, text.Length - start);
+ }
+ return res.ToString();
+ }
+
+ public static string AddSlashes(string str) {
+ ContractUtils.RequiresNotNull(str, "str");
+
+ // TODO: optimize
+ StringBuilder result = new StringBuilder(str.Length);
+ for (int i = 0; i < str.Length; i++) {
+ switch (str[i]) {
+ case '\a': result.Append("\\a"); break;
+ case '\b': result.Append("\\b"); break;
+ case '\f': result.Append("\\f"); break;
+ case '\n': result.Append("\\n"); break;
+ case '\r': result.Append("\\r"); break;
+ case '\t': result.Append("\\t"); break;
+ case '\v': result.Append("\\v"); break;
+ default: result.Append(str[i]); break;
+ }
+ }
+
+ return result.ToString();
+ }
+
+ public static bool TryParseDouble(string s, NumberStyles style, IFormatProvider provider, out double result) {
+ return Double.TryParse(s, style, provider, out result);
+ }
+
+ public static bool TryParseInt32(string s, out int result) {
+ return Int32.TryParse(s, out result);
+ }
+
+ public static bool TryParseDateTimeExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
+ return DateTime.TryParseExact(s, format, provider, style, out result);
+ }
+
+ public static bool TryParseDateTimeExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
+ return DateTime.TryParseExact(s, formats, provider, style, out result);
+ }
+
+ public static bool TryParseDate(string s, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
+ return DateTime.TryParse(s, provider, style, out result);
+ }
+
+#if !WIN8
+#if SILVERLIGHT || WP75
+ private static Dictionary<string, CultureInfo> _cultureInfoCache = new Dictionary<string, CultureInfo>();
+#endif
+
+ // Aims to be equivalent to Culture.GetCultureInfo for Silverlight
+ public static CultureInfo GetCultureInfo(string name) {
+#if SILVERLIGHT || WP75
+ lock (_cultureInfoCache) {
+ CultureInfo result;
+ if (_cultureInfoCache.TryGetValue(name, out result)) {
+ return result;
+ }
+ _cultureInfoCache[name] = result = new CultureInfo(name);
+ return result;
+ }
+#else
+ return CultureInfo.GetCultureInfo(name);
+#endif
+ }
+#endif
+ // Like string.Split, but enumerates
+ public static IEnumerable<string> Split(string str, string sep) {
+ int start = 0, end;
+ while ((end = str.IndexOf(sep, start)) != -1) {
+ yield return str.Substring(start, end - start);
+
+ start = end + sep.Length;
+ }
+ yield return str.Substring(start);
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/TypeUtils.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/TypeUtils.cs
new file mode 100644
index 00000000000..c20371d0f0e
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Utils/TypeUtils.cs
@@ -0,0 +1,375 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Reflection;
+using System.Dynamic;
+using Microsoft.Scripting.Generation;
+using Microsoft.Scripting.Runtime;
+
+namespace Microsoft.Scripting.Utils {
+ public static class TypeUtils {
+ public static bool IsNested(this Type t) {
+ return t.DeclaringType != null;
+ }
+
+ // keep in sync with System.Core version
+ internal static Type GetNonNullableType(Type type) {
+ if (IsNullableType(type)) {
+ return type.GetGenericArguments()[0];
+ }
+ return type;
+ }
+
+ // keep in sync with System.Core version
+ internal static bool IsNullableType(Type type) {
+ return type.IsGenericType() && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+ // keep in sync with System.Core version
+ internal static bool IsBool(Type type) {
+ return GetNonNullableType(type) == typeof(bool);
+ }
+
+ // keep in sync with System.Core version
+ internal static bool IsNumeric(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum()) {
+ return IsNumeric(type.GetTypeCode());
+ }
+ return false;
+ }
+
+ internal static bool IsNumeric(TypeCode typeCode) {
+ switch (typeCode) {
+ 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;
+ }
+
+ // keep in sync with System.Core version
+ internal static bool IsArithmetic(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum()) {
+ switch (type.GetTypeCode()) {
+ 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;
+ }
+
+ // keep in sync with System.Core version
+ internal static bool IsUnsignedInt(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum()) {
+ switch (type.GetTypeCode()) {
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // keep in sync with System.Core version
+ internal static bool IsIntegerOrBool(Type type) {
+ type = GetNonNullableType(type);
+ if (!type.IsEnum()) {
+ switch (type.GetTypeCode()) {
+ 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 CanAssign(Type to, Expression from) {
+ if (CanAssign(to, from.Type)) return true;
+
+ if (to.IsValueType() &&
+ to.IsGenericType() &&
+ to.GetGenericTypeDefinition() == typeof(Nullable<>) &&
+ ConstantCheck.Check(from, null)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ internal static bool CanAssign(Type to, Type from) {
+ if (to == from) {
+ return true;
+ }
+ // Reference types
+ if (!to.IsValueType() && !from.IsValueType()) {
+ if (to.IsAssignableFrom(from)) {
+ return true;
+ }
+ // Arrays can be assigned if they have same rank and assignable element types.
+ if (to.IsArray && from.IsArray &&
+ to.GetArrayRank() == from.GetArrayRank() &&
+ CanAssign(to.GetElementType(), from.GetElementType())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal static bool IsGeneric(Type type) {
+ return type.ContainsGenericParameters() || type.IsGenericTypeDefinition();
+ }
+
+ internal static bool CanCompareToNull(Type type) {
+ // This is a bit too conservative.
+ return !type.IsValueType();
+ }
+
+ /// <summary>
+ /// Returns a numerical code of the size of a type. All types get both a horizontal
+ /// and vertical code. Types that are lower in both dimensions have implicit conversions
+ /// to types that are higher in both dimensions.
+ /// </summary>
+ internal static bool GetNumericConversionOrder(TypeCode code, out int x, out int y) {
+ // implicit conversions:
+ // 0 1 2 3 4
+ // 0: U1 -> U2 -> U4 -> U8
+ // | | |
+ // v v v
+ // 1: I1 -> I2 -> I4 -> I8
+ // | |
+ // v v
+ // 2: R4 -> R8
+
+ switch (code) {
+ case TypeCode.Byte: x = 0; y = 0; break;
+ case TypeCode.UInt16: x = 1; y = 0; break;
+ case TypeCode.UInt32: x = 2; y = 0; break;
+ case TypeCode.UInt64: x = 3; y = 0; break;
+
+ case TypeCode.SByte: x = 0; y = 1; break;
+ case TypeCode.Int16: x = 1; y = 1; break;
+ case TypeCode.Int32: x = 2; y = 1; break;
+ case TypeCode.Int64: x = 3; y = 1; break;
+
+ case TypeCode.Single: x = 1; y = 2; break;
+ case TypeCode.Double: x = 2; y = 2; break;
+
+ default:
+ x = y = 0;
+ return false;
+ }
+ return true;
+ }
+
+ internal static bool IsImplicitlyConvertible(int fromX, int fromY, int toX, int toY) {
+ return fromX <= toX && fromY <= toY;
+ }
+
+ internal static bool HasBuiltinEquality(Type left, Type right) {
+ // Reference type can be compared to interfaces
+ if (left.IsInterface() && !right.IsValueType() ||
+ right.IsInterface() && !left.IsValueType()) {
+ return true;
+ }
+
+ // Reference types compare if they are assignable
+ if (!left.IsValueType() && !right.IsValueType()) {
+ if (CanAssign(left, right) || CanAssign(right, left)) {
+ return true;
+ }
+ }
+
+ // Nullable<T> vs null
+ if (NullVsNullable(left, right) || NullVsNullable(right, left)) {
+ return true;
+ }
+
+ if (left != right) {
+ return false;
+ }
+
+ if (left == typeof(bool) || IsNumeric(left) || left.IsEnum()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool NullVsNullable(Type left, Type right) {
+ return IsNullableType(left) && right == typeof(DynamicNull);
+ }
+
+ // keep in sync with System.Core version
+ internal static bool AreEquivalent(Type t1, Type t2) {
+#if FEATURE_TYPE_EQUIVALENCE
+ return t1 == t2 || t1.IsEquivalentTo(t2);
+#else
+ return t1 == t2;
+#endif
+ }
+
+ // keep in sync with System.Core version
+ 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;
+ }
+
+ // keep in sync with System.Core version
+ 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;
+ }
+
+ // keep in sync with System.Core version
+ internal static Type GetConstantType(Type type) {
+ // If it's a visible type, we're done
+ if (type.IsVisible()) {
+ return type;
+ }
+
+ // Get the visible base type
+ Type bt = type;
+ do {
+ bt = bt.GetBaseType();
+ } while (!bt.IsVisible());
+
+ // If it's one of the known reflection types,
+ // return the known type.
+ if (bt == typeof(Type) ||
+ bt == typeof(ConstructorInfo) ||
+ bt == typeof(EventInfo) ||
+ bt == typeof(FieldInfo) ||
+ bt == typeof(MethodInfo) ||
+ bt == typeof(PropertyInfo)) {
+ return bt;
+ }
+
+ // else return the original type
+ return type;
+ }
+
+ internal static bool IsConvertible(Type type) {
+ type = GetNonNullableType(type);
+ if (type.IsEnum()) {
+ return true;
+ }
+ switch (type.GetTypeCode()) {
+ 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 IsFloatingPoint(Type type) {
+ type = GetNonNullableType(type);
+ switch (type.GetTypeCode()) {
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+#if FEATURE_COM
+ public static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
+
+ public static bool IsComObjectType(Type/*!*/ type) {
+ return ComObjectType.IsAssignableFrom(type);
+ }
+
+ // we can't use System.Runtime.InteropServices.Marshal.IsComObject(obj) since it doesn't work in partial trust
+ public static bool IsComObject(object obj) {
+ return obj != null && IsComObjectType(obj.GetType());
+ }
+#else
+ public static bool IsComObjectType(Type/*!*/ type) {
+ return false;
+ }
+
+ public static bool IsComObject(object obj) {
+ return false;
+ }
+#endif
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting/ArgumentTypeException.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting/ArgumentTypeException.cs
new file mode 100644
index 00000000000..5d1e9e2d726
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting/ArgumentTypeException.cs
@@ -0,0 +1,38 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Microsoft.Scripting {
+ [Serializable]
+ public class ArgumentTypeException : Exception {
+ public ArgumentTypeException()
+ : base() {
+ }
+
+ public ArgumentTypeException(string message)
+ : base(message) {
+ }
+
+ public ArgumentTypeException(string message, Exception innerException)
+ : base(message, innerException) {
+ }
+
+#if FEATURE_SERIALIZATION
+ protected ArgumentTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+#endif
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting/InvalidImplementationException.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting/InvalidImplementationException.cs
new file mode 100644
index 00000000000..dff8c291a41
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting/InvalidImplementationException.cs
@@ -0,0 +1,38 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Microsoft.Scripting {
+ [Serializable]
+ public class InvalidImplementationException : Exception {
+ public InvalidImplementationException()
+ : base() {
+ }
+
+ public InvalidImplementationException(string message)
+ : base(message) {
+ }
+
+ public InvalidImplementationException(string message, Exception e)
+ : base(message, e) {
+ }
+
+#if FEATURE_SERIALIZATION
+ protected InvalidImplementationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+#endif
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting/PlatformAdaptationLayer.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting/PlatformAdaptationLayer.cs
new file mode 100644
index 00000000000..d197e8ee4be
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting/PlatformAdaptationLayer.cs
@@ -0,0 +1,471 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
+#else
+using Microsoft.Scripting.Ast;
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using Microsoft.Scripting.Utils;
+using System.Runtime.CompilerServices;
+using System.Collections;
+
+namespace Microsoft.Scripting {
+
+#if !FEATURE_PROCESS
+ public class ExitProcessException : Exception {
+
+ public int ExitCode { get { return exitCode; } }
+ int exitCode;
+
+ public ExitProcessException(int exitCode) {
+ this.exitCode = exitCode;
+ }
+ }
+#endif
+
+ /// <summary>
+ /// Abstracts system operations that are used by DLR and could potentially be platform specific.
+ /// The host can implement its PAL to adapt DLR to the platform it is running on.
+ /// For example, the Silverlight host adapts some file operations to work against files on the server.
+ /// </summary>
+ [Serializable]
+ public class PlatformAdaptationLayer {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
+ public static readonly PlatformAdaptationLayer Default = new PlatformAdaptationLayer();
+
+ public static readonly bool IsCompactFramework =
+#if WIN8
+ false;
+#else
+ Environment.OSVersion.Platform == PlatformID.WinCE ||
+ Environment.OSVersion.Platform == PlatformID.Xbox;
+#endif
+
+#if SILVERLIGHT
+
+ // this dictionary is readonly after initialization:
+ private Dictionary<string, string> _assemblyFullNames = new Dictionary<string, string>();
+
+ public PlatformAdaptationLayer() {
+ LoadSilverlightAssemblyNameMapping();
+ }
+
+ // TODO: remove the need for this
+ private void LoadSilverlightAssemblyNameMapping() {
+ // non-trasparent assemblies
+ AssemblyName platformKeyVer = new AssemblyName(typeof(object).Assembly.FullName);
+ AddAssemblyMappings(platformKeyVer,
+ "mscorlib",
+ "System",
+ "System.Core",
+ "System.Net",
+ "System.Runtime.Serialization",
+ "System.ServiceModel.Web",
+ "System.Windows",
+ "System.Windows.Browser",
+ "System.Xml",
+ "Microsoft.VisualBasic"
+ );
+
+ // DLR + language assemblies
+ AssemblyName languageKeyVer = new AssemblyName(typeof(PlatformAdaptationLayer).Assembly.FullName);
+ AddAssemblyMappings(languageKeyVer,
+ "Microsoft.Scripting",
+ "Microsoft.Dynamic",
+ "Microsoft.Scripting.Core",
+ "Microsoft.Scripting.Silverlight",
+ "IronPython",
+ "IronPython.Modules",
+ "IronRuby",
+ "IronRuby.Libraries"
+ );
+
+ // transparent assemblies => same version as mscorlib but uses transparent key (same as languages)
+ AssemblyName transparentKeyVer = new AssemblyName(typeof(object).Assembly.FullName);
+ transparentKeyVer.SetPublicKeyToken(languageKeyVer.GetPublicKeyToken());
+ AddAssemblyMappings(transparentKeyVer,
+ "System.ServiceModel",
+ "System.ServiceModel.Syndication",
+ "System.Windows.Controls",
+ "System.Windows.Controls.Data",
+ "System.Windows.Controls.Data.Design",
+ "System.Windows.Controls.Design",
+ "System.Windows.Controls.Extended",
+ "System.Windows.Controls.Extended.Design",
+ "System.Xml.Linq",
+ "System.Xml.Serialization"
+ );
+ }
+
+ private void AddAssemblyMappings(AssemblyName keyVersion, params string[] names) {
+ foreach (string asm in names) {
+ keyVersion.Name = asm;
+ _assemblyFullNames.Add(asm.ToLower(), keyVersion.FullName);
+ }
+ }
+
+ protected string LookupFullName(string name) {
+ AssemblyName asm = new AssemblyName(name);
+ if (asm.Version != null || asm.GetPublicKeyToken() != null || asm.GetPublicKey() != null) {
+ return name;
+ }
+ return _assemblyFullNames.ContainsKey(name.ToLower()) ? _assemblyFullNames[name.ToLower()] : name;
+ }
+#endif
+ #region Assembly Loading
+
+ public virtual Assembly LoadAssembly(string name) {
+#if WIN8
+ throw new NotImplementedException();
+#elif !SILVERLIGHT
+ return Assembly.Load(name);
+#else
+ return Assembly.Load(LookupFullName(name));
+#endif
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFile")]
+ public virtual Assembly LoadAssemblyFromPath(string path) {
+#if FEATURE_FILESYSTEM
+ return Assembly.LoadFile(path);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ public virtual void TerminateScriptExecution(int exitCode) {
+#if FEATURE_PROCESS
+ System.Environment.Exit(exitCode);
+#else
+ throw new ExitProcessException(exitCode);
+#endif
+ }
+
+ #endregion
+
+ #region Virtual File System
+
+ public virtual bool IsSingleRootFileSystem {
+ get {
+#if FEATURE_FILESYSTEM
+ return Environment.OSVersion.Platform == PlatformID.Unix
+ || Environment.OSVersion.Platform == PlatformID.MacOSX;
+#elif WIN8
+ return false;
+#else
+ return true;
+#endif
+ }
+ }
+
+ public virtual StringComparer PathComparer {
+ get {
+#if FEATURE_FILESYSTEM
+ return Environment.OSVersion.Platform == PlatformID.Unix ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
+#else
+ return StringComparer.OrdinalIgnoreCase;
+#endif
+ }
+ }
+
+ public virtual bool FileExists(string path) {
+#if FEATURE_FILESYSTEM
+ return File.Exists(path);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ public virtual bool DirectoryExists(string path) {
+#if FEATURE_FILESYSTEM
+ return Directory.Exists(path);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+#if !CLR2
+ // TODO: better APIs
+ public virtual Stream OpenFileStream(string path, FileMode mode = FileMode.OpenOrCreate, FileAccess access = FileAccess.ReadWrite, FileShare share = FileShare.Read, int bufferSize = 8192) {
+#if FEATURE_FILESYSTEM
+ if (string.Equals("nul", path, StringComparison.InvariantCultureIgnoreCase)) {
+ return Stream.Null;
+ }
+ return new FileStream(path, mode, access, share, bufferSize);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ // TODO: better APIs
+ public virtual Stream OpenInputFileStream(string path, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read, FileShare share = FileShare.Read, int bufferSize = 8192) {
+ return OpenFileStream(path, mode, access, share, bufferSize);
+ }
+
+ // TODO: better APIs
+ public virtual Stream OpenOutputFileStream(string path) {
+ return OpenFileStream(path, FileMode.Create, FileAccess.Write);
+ }
+#else
+ public virtual Stream OpenFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) {
+#if FEATURE_FILESYSTEM
+ if (string.Equals("nul", path, StringComparison.InvariantCultureIgnoreCase)) {
+ return Stream.Null;
+ }
+ return new FileStream(path, mode, access, share, bufferSize);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ // TODO: better APIs
+ public virtual Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share) {
+ return OpenFileStream(path, mode, access, share, 8912);
+ }
+
+ // TODO: better APIs
+ public virtual Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) {
+ return OpenFileStream(path, mode, access, share, bufferSize);
+ }
+
+ // TODO: better APIs
+ public virtual Stream OpenInputFileStream(string path) {
+ return OpenFileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 8912);
+ }
+
+ // TODO: better APIs
+ public virtual Stream OpenOutputFileStream(string path) {
+ return OpenFileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 8912);
+ }
+#endif
+
+ public virtual void DeleteFile(string path, bool deleteReadOnly) {
+#if FEATURE_FILESYSTEM
+ FileInfo info = new FileInfo(path);
+#if !ANDROID
+ if (deleteReadOnly && info.IsReadOnly) {
+ info.IsReadOnly = false;
+ }
+#endif
+ info.Delete();
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ public string[] GetFiles(string path, string searchPattern) {
+ return GetFileSystemEntries(path, searchPattern, true, false);
+ }
+
+ public string[] GetDirectories(string path, string searchPattern) {
+ return GetFileSystemEntries(path, searchPattern, false, true);
+ }
+
+ public string[] GetFileSystemEntries(string path, string searchPattern) {
+ return GetFileSystemEntries(path, searchPattern, true, true);
+ }
+
+ public virtual string[] GetFileSystemEntries(string path, string searchPattern, bool includeFiles, bool includeDirectories) {
+#if FEATURE_FILESYSTEM
+ if (includeFiles && includeDirectories) {
+ return Directory.GetFileSystemEntries(path, searchPattern);
+ }
+ if (includeFiles) {
+ return Directory.GetFiles(path, searchPattern);
+ }
+ if (includeDirectories) {
+ return Directory.GetDirectories(path, searchPattern);
+ }
+ return ArrayUtils.EmptyStrings;
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ /// <exception cref="ArgumentException">Invalid path.</exception>
+ public virtual string GetFullPath(string path) {
+#if FEATURE_FILESYSTEM
+ try {
+ return Path.GetFullPath(path);
+ } catch (Exception) {
+ throw Error.InvalidPath();
+ }
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ public virtual string CombinePaths(string path1, string path2) {
+ return Path.Combine(path1, path2);
+ }
+
+ public virtual string GetFileName(string path) {
+ return Path.GetFileName(path);
+ }
+
+ public virtual string GetDirectoryName(string path) {
+ return Path.GetDirectoryName(path);
+ }
+
+ public virtual string GetExtension(string path) {
+ return Path.GetExtension(path);
+ }
+
+ public virtual string GetFileNameWithoutExtension(string path) {
+ return Path.GetFileNameWithoutExtension(path);
+ }
+
+ /// <exception cref="ArgumentException">Invalid path.</exception>
+ public virtual bool IsAbsolutePath(string path) {
+ if (String.IsNullOrEmpty(path)) {
+ return false;
+ }
+
+ // no drives, no UNC:
+ if (IsSingleRootFileSystem) {
+ return IsDirectorySeparator(path[0]);
+ }
+
+ if (IsDirectorySeparator(path[0])) {
+ // UNC path
+ return path.Length > 1 && IsDirectorySeparator(path[1]);
+ }
+
+ if (path.Length > 2 && path[1] == ':' && IsDirectorySeparator(path[2])) {
+ return true;
+ }
+
+ return false;
+ }
+
+#if FEATURE_FILESYSTEM
+ private bool IsDirectorySeparator(char c) {
+ return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
+ }
+#else
+ private bool IsDirectorySeparator(char c) {
+ return c == '\\' || c == '/';
+ }
+#endif
+
+ public virtual string CurrentDirectory {
+ get {
+#if FEATURE_FILESYSTEM
+ return Directory.GetCurrentDirectory();
+#else
+ throw new NotImplementedException();
+#endif
+ }
+ set {
+#if FEATURE_FILESYSTEM
+ Directory.SetCurrentDirectory(value);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+ }
+
+ public virtual void CreateDirectory(string path) {
+#if FEATURE_FILESYSTEM
+ Directory.CreateDirectory(path);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ public virtual void DeleteDirectory(string path, bool recursive) {
+#if FEATURE_FILESYSTEM
+ Directory.Delete(path, recursive);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ public virtual void MoveFileSystemEntry(string sourcePath, string destinationPath) {
+#if FEATURE_FILESYSTEM
+ Directory.Move(sourcePath, destinationPath);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ #endregion
+
+ #region Environmental Variables
+
+ public virtual string GetEnvironmentVariable(string key) {
+#if FEATURE_PROCESS
+ return Environment.GetEnvironmentVariable(key);
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ public virtual void SetEnvironmentVariable(string key, string value) {
+#if FEATURE_PROCESS
+ if (value != null && value.Length == 0) {
+ SetEmptyEnvironmentVariable(key);
+ } else {
+ Environment.SetEnvironmentVariable(key, value);
+ }
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+#if FEATURE_PROCESS
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2149:TransparentMethodsMustNotCallNativeCodeFxCopRule")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2140:TransparentMethodsMustNotReferenceCriticalCodeFxCopRule")]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void SetEmptyEnvironmentVariable(string key) {
+ // System.Environment.SetEnvironmentVariable interprets an empty value string as
+ // deleting the environment variable. So we use the native SetEnvironmentVariable
+ // function here which allows setting of the value to an empty string.
+ // This will require high trust and will fail in sandboxed environments
+ if (!NativeMethods.SetEnvironmentVariable(key, String.Empty)) {
+ throw new ExternalException("SetEnvironmentVariable failed", Marshal.GetLastWin32Error());
+ }
+ }
+#endif
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ public virtual Dictionary<string, string> GetEnvironmentVariables() {
+#if FEATURE_PROCESS
+ var result = new Dictionary<string, string>();
+
+ foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
+ {
+ result.Add((string)entry.Key, (string)entry.Value);
+ }
+
+ return result;
+#else
+ throw new NotImplementedException();
+#endif
+ }
+
+ #endregion
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/NotNullAttribute.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/NotNullAttribute.cs
new file mode 100644
index 00000000000..43cc1af4653
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/NotNullAttribute.cs
@@ -0,0 +1,40 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+
+namespace Microsoft.Scripting.Runtime {
+ /// <summary>
+ /// This attribute marks a parameter that is not allowed to be null.
+ /// It is used by the method binding infrastructure to generate better error
+ /// messages and method selection.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ public sealed class NotNullAttribute : Attribute {
+ public NotNullAttribute() {
+ }
+ }
+
+ /// <summary>
+ /// This attribute marks a parameter whose type is an array that is not allowed to have null items.
+ /// It is used by the method binding infrastructure to generate better error
+ /// messages and method selection.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ public sealed class NotNullItemsAttribute : Attribute {
+ public NotNullItemsAttribute() {
+ }
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/ParamDictionaryAttribute.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/ParamDictionaryAttribute.cs
new file mode 100644
index 00000000000..3f0a081ea1c
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting/Runtime/ParamDictionaryAttribute.cs
@@ -0,0 +1,55 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using System;
+
+namespace Microsoft.Scripting {
+ /// <summary>
+ /// This attribute is used to mark a parameter that can accept any keyword parameters that
+ /// are not bound to normal arguments. The extra keyword parameters will be
+ /// passed in a dictionary which is created for the call.
+ ///
+ /// Most languages which support params dictionaries will support the following types:
+ /// IDictionary&lt;string, anything&gt;
+ /// IDictionary&lt;object, anything&gt;
+ /// Dictionary&lt;string, anything&gt;
+ /// Dictionary&lt;object, anything&gt;
+ /// IDictionary
+ /// IAttributesCollection (deprecated)
+ ///
+ /// For languages which don't have language level support the user will be required to
+ /// create and populate the dictionary by hand.
+ ///
+ /// This attribute is the dictionary equivalent of the System.ParamArrayAttribute.
+ /// </summary>
+ /// <example>
+ /// public static void KeywordArgFunction([ParamsDictionary]IDictionary&lt;string, object&gt; dict) {
+ /// foreach (var v in dict) {
+ /// Console.WriteLine("Key: {0} Value: {1}", v.Key, v.Value);
+ /// }
+ /// }
+ ///
+ /// Called from Python:
+ ///
+ /// KeywordArgFunction(a = 2, b = "abc")
+ ///
+ /// will print:
+ /// Key: a Value = 2
+ /// Key: b Value = abc
+ /// </example>
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ public sealed class ParamDictionaryAttribute : Attribute {
+ }
+}
diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting/Stubs.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting/Stubs.cs
new file mode 100644
index 00000000000..5719fd93043
--- /dev/null
+++ b/mcs/class/dlr/Runtime/Microsoft.Scripting/Stubs.cs
@@ -0,0 +1,116 @@
+/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
+ * copy of the license can be found in the License.html file at the root of this distribution. If
+ * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+#if WIN8
+
+// When compiled with Dev10 VS CSC reports errors if this is not defined
+// error CS0656: Missing compiler required member 'System.Threading.Thread.get_ManagedThreadId'
+// error CS0656: Missing compiler required member 'System.Threading.Thread.get_CurrentThread'
+namespace System.Threading {
+ internal class Thread {
+ public int ManagedThreadId { get { throw new NotImplementedException(); } }
+ public static Thread CurrentThread { get { throw new NotImplementedException(); } }
+ }
+}
+
+namespace System.IO {
+ [Serializable]
+ public enum FileMode {
+ CreateNew = 1,
+ Create,
+ Open,
+ OpenOrCreate,
+ Truncate,
+ Append
+ }
+
+ [Serializable]
+ public enum FileAccess {
+ Read = 1,
+ Write = 2,
+ ReadWrite = 3
+ }
+
+ [Serializable]
+ public enum FileShare {
+ None = 0,
+ Read = 1,
+ Write = 2,
+ ReadWrite = 3,
+ Delete = 4,
+ Inheritable = 16
+ }
+}
+#else
+namespace System {
+ public static class TypeExtensions {
+#if !FEATURE_GET_TYPE_INFO
+ public static Type GetTypeInfo(this Type type) {
+ return type;
+ }
+#endif
+
+ public static Type AsType(this Type type) {
+ return type;
+ }
+ }
+}
+#endif
+
+#if !FEATURE_SERIALIZATION
+
+namespace System {
+ using System.Diagnostics;
+
+ [Conditional("STUB")]
+ public class SerializableAttribute : Attribute {
+ }
+
+ [Conditional("STUB")]
+ public class NonSerializedAttribute : Attribute {
+ }
+
+ namespace Runtime.Serialization {
+ public interface ISerializable {
+ }
+
+ public interface IDeserializationCallback {
+ }
+ }
+
+ public class SerializationException : Exception {
+ }
+}
+
+#endif
+
+#if SILVERLIGHT && !CLR2
+
+namespace System {
+ 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) { }
+ }
+ }
+}
+
+#endif \ No newline at end of file