diff options
Diffstat (limited to 'mcs/class/System.Core/System.Linq.jvm/ExpressionInterpreter.cs')
-rw-r--r-- | mcs/class/System.Core/System.Linq.jvm/ExpressionInterpreter.cs | 937 |
1 files changed, 0 insertions, 937 deletions
diff --git a/mcs/class/System.Core/System.Linq.jvm/ExpressionInterpreter.cs b/mcs/class/System.Core/System.Linq.jvm/ExpressionInterpreter.cs deleted file mode 100644 index 4d550d1ac5..0000000000 --- a/mcs/class/System.Core/System.Linq.jvm/ExpressionInterpreter.cs +++ /dev/null @@ -1,937 +0,0 @@ -// -// ExpressionInterpreter.cs -// -// (C) 2008 Mainsoft, Inc. (http://www.mainsoft.com) -// (C) 2008 db4objects, Inc. (http://www.db4o.com) -// (C) 2010 Novell, Inc. (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq.Expressions; -using System.Reflection; - -namespace System.Linq.jvm { - - struct LambdaInfo { - public readonly LambdaExpression Lambda; - public readonly object [] Arguments; - - public LambdaInfo (LambdaExpression lambda, object [] arguments) - { - this.Lambda = lambda; - this.Arguments = arguments; - } - } - - class HoistedVariableDetector : ExpressionVisitor { - - readonly Dictionary<ParameterExpression, LambdaExpression> parameter_to_lambda = - new Dictionary<ParameterExpression, LambdaExpression> (); - - Dictionary<LambdaExpression, List<ParameterExpression>> hoisted_map; - - LambdaExpression lambda; - - public Dictionary<LambdaExpression, List<ParameterExpression>> Process (LambdaExpression lambda) - { - Visit (lambda); - return hoisted_map; - } - - protected override void VisitLambda (LambdaExpression lambda) - { - this.lambda = lambda; - foreach (var parameter in lambda.Parameters) - parameter_to_lambda [parameter] = lambda; - base.VisitLambda (lambda); - } - - protected override void VisitParameter (ParameterExpression parameter) - { - if (lambda.Parameters.Contains (parameter)) - return; - - Hoist (parameter); - } - - void Hoist (ParameterExpression parameter) - { - LambdaExpression lambda; - if (!parameter_to_lambda.TryGetValue (parameter, out lambda)) - return; - - if (hoisted_map == null) - hoisted_map = new Dictionary<LambdaExpression, List<ParameterExpression>> (); - - List<ParameterExpression> hoisted; - if (!hoisted_map.TryGetValue (lambda, out hoisted)) { - hoisted = new List<ParameterExpression> (); - hoisted_map [lambda] = hoisted; - } - - hoisted.Add (parameter); - } - } - - - class ExpressionInterpreter : ExpressionVisitor { - - readonly Stack<LambdaInfo> lambdas = new Stack<LambdaInfo> (); - readonly Stack<object> stack = new Stack<object> (); - - readonly Dictionary<LambdaExpression, List<ParameterExpression>> hoisted_map; - readonly Dictionary<ParameterExpression, object> hoisted_values; - - void Push (object value) - { - stack.Push (value); - } - - object Pop () - { - return stack.Pop (); - } - - public ExpressionInterpreter (LambdaExpression lambda) - { - hoisted_map = new HoistedVariableDetector ().Process (lambda); - - if (hoisted_map != null) - hoisted_values = new Dictionary<ParameterExpression, object> (); - } - - private void VisitCoalesce (BinaryExpression binary) - { - Visit (binary.Left); - - var left = Pop (); - - if (left == null) { - Visit (binary.Right); - return; - } - - if (binary.Conversion == null) { - Push (left); - return; - } - - Push (Invoke (binary.Conversion.Compile (this), new [] { left })); - } - - void VisitAndAlso (BinaryExpression binary) - { - object left = null; - object right = null; - - Visit (binary.Left); - - left = Pop (); - - if (left == null || ((bool) left)) { - Visit (binary.Right); - right = Pop (); - } - - Push (Math.And (left, right)); - } - - void VisitUserDefinedAndAlso (BinaryExpression binary) - { - object left = null; - object right = null; - - Visit (binary.Left); - - left = Pop (); - - if (InvokeFalseOperator (binary, left)) { - Push (left); - return; - } - - Visit (binary.Right); - right = Pop (); - - if (binary.IsLiftedToNull && right == null) { - Push (null); - return; - } - - Push (InvokeMethod (binary.Method, null, new [] { left, right })); - } - - static bool InvokeTrueOperator (BinaryExpression binary, object target) - { - return (bool) InvokeMethod (GetTrueOperator (binary), null, new [] { target }); - } - - static bool InvokeFalseOperator (BinaryExpression binary, object target) - { - return (bool) InvokeMethod (GetFalseOperator (binary), null, new [] { target }); - } - - static MethodInfo GetFalseOperator (BinaryExpression binary) - { - return Expression.GetFalseOperator (binary.Left.Type.GetNotNullableType ()); - } - - static MethodInfo GetTrueOperator (BinaryExpression binary) - { - return Expression.GetTrueOperator (binary.Left.Type.GetNotNullableType ()); - } - - void VisitOrElse (BinaryExpression binary) - { - object left = null; - object right = null; - - Visit (binary.Left); - left = Pop (); - - if (left == null || !((bool) left)) { - Visit (binary.Right); - right = Pop (); - } - - Push (Math.Or (left, right)); - } - - void VisitUserDefinedOrElse (BinaryExpression binary) - { - object left = null; - object right = null; - - Visit (binary.Left); - left = Pop (); - - if (InvokeTrueOperator (binary, left)) { - Push (left); - return; - } - - Visit (binary.Right); - right = Pop (); - - if (binary.IsLiftedToNull && right == null) { - Push (null); - return; - } - - Push (InvokeMethod (binary.Method, null, new [] { left, right })); - } - - void VisitLogicalBinary (BinaryExpression binary) - { - Visit (binary.Left); - Visit (binary.Right); - - var right = Pop (); - var left = Pop (); - - Push (Math.Evaluate (left, right, binary.Type, binary.NodeType)); - } - - void VisitArithmeticBinary (BinaryExpression binary) - { - Visit (binary.Left); - Visit (binary.Right); - - if (IsNullBinaryLifting (binary)) - return; - - var right = Pop (); - var left = Pop (); - - switch (binary.NodeType) { - case ExpressionType.RightShift: - Push (Math.RightShift (left, Convert.ToInt32 (right), Type.GetTypeCode (binary.Type.GetNotNullableType ()))); - return; - case ExpressionType.LeftShift: - Push (Math.LeftShift (left, Convert.ToInt32 (right), Type.GetTypeCode (binary.Type.GetNotNullableType ()))); - return; - default: - Push (Math.Evaluate (left, right, binary.Type, binary.NodeType)); - break; - } - } - - bool IsNullRelationalBinaryLifting (BinaryExpression binary) - { - var right = Pop (); - var left = Pop (); - - if (binary.IsLifted && (left == null || right == null)) { - if (binary.IsLiftedToNull) { - Push (null); - return true; - } - - switch (binary.NodeType) { - case ExpressionType.Equal: - Push (BinaryEqual (binary, left, right)); - break; - case ExpressionType.NotEqual: - Push (BinaryNotEqual (binary, left, right)); - break; - default: - Push (false); - break; - } - - return true; - } - - Push (left); - Push (right); - - return false; - } - - void VisitRelationalBinary (BinaryExpression binary) - { - Visit (binary.Left); - Visit (binary.Right); - - if (IsNullRelationalBinaryLifting (binary)) - return; - - var right = Pop (); - var left = Pop (); - - switch (binary.NodeType) { - case ExpressionType.Equal: - Push (BinaryEqual (binary, left, right)); - return; - case ExpressionType.NotEqual: - Push (BinaryNotEqual (binary, left, right)); - return; - case ExpressionType.LessThan: - Push (Comparer<object>.Default.Compare (left, right) < 0); - return; - case ExpressionType.LessThanOrEqual: - Push (Comparer<object>.Default.Compare (left, right) <= 0); - return; - case ExpressionType.GreaterThan: - Push (Comparer<object>.Default.Compare (left, right) > 0); - return; - case ExpressionType.GreaterThanOrEqual: - Push (Comparer<object>.Default.Compare (left, right) >= 0); - return; - } - } - - void VisitLogicalShortCircuitBinary (BinaryExpression binary) - { - switch (binary.NodeType) { - case ExpressionType.AndAlso: - VisitAndAlso (binary); - return; - case ExpressionType.OrElse: - VisitOrElse (binary); - return; - } - } - - void VisitArrayIndex (BinaryExpression binary) - { - Visit (binary.Left); - var left = Pop (); - Visit (binary.Right); - var right = Pop (); - - Push (((Array) left).GetValue ((int) right)); - } - - bool IsNullBinaryLifting (BinaryExpression binary) - { - var right = Pop (); - var left = Pop (); - - if (binary.IsLifted && (right == null || left == null)) { - if (binary.IsLiftedToNull) - Push (null); - else - Push (GetDefaultValue (binary.Type)); - - return true; - } - - Push (left); - Push (right); - - return false; - } - - static object GetDefaultValue (Type type) - { - var array = (Array) Array.CreateInstance (type, 1); - return array.GetValue (0); - } - - void VisitUserDefinedBinary (BinaryExpression binary) - { - switch (binary.NodeType) { - case ExpressionType.AndAlso: - case ExpressionType.OrElse: - VisitUserDefinedLogicalShortCircuitBinary (binary); - return; - case ExpressionType.Equal: - case ExpressionType.NotEqual: - VisitUserDefinedRelationalBinary (binary); - return; - default: - VisitUserDefinedCommonBinary (binary); - return; - } - } - - void VisitUserDefinedLogicalShortCircuitBinary (BinaryExpression binary) - { - switch (binary.NodeType) { - case ExpressionType.AndAlso: - VisitUserDefinedAndAlso (binary); - return; - case ExpressionType.OrElse: - VisitUserDefinedOrElse (binary); - return; - } - } - - void VisitUserDefinedRelationalBinary (BinaryExpression binary) - { - Visit (binary.Left); - Visit (binary.Right); - - if (IsNullRelationalBinaryLifting (binary)) - return; - - var right = Pop (); - var left = Pop (); - - Push (InvokeBinary (binary, left, right)); - } - - void VisitUserDefinedCommonBinary (BinaryExpression binary) - { - Visit (binary.Left); - Visit (binary.Right); - - if (IsNullBinaryLifting (binary)) - return; - - var right = Pop (); - var left = Pop (); - - Push (InvokeBinary (binary, left, right)); - } - - object InvokeBinary (BinaryExpression binary, object left, object right) - { - return InvokeMethod (binary.Method, null, new [] { left, right }); - } - - bool BinaryEqual (BinaryExpression binary, object left, object right) - { - if (typeof (ValueType).IsAssignableFrom (binary.Right.Type)) - return ValueType.Equals (left, right); - else - return left == right; - } - - bool BinaryNotEqual (BinaryExpression binary, object left, object right) - { - if (typeof (ValueType).IsAssignableFrom (binary.Right.Type)) - return !ValueType.Equals (left, right); - else - return left != right; - } - - protected override void VisitBinary (BinaryExpression binary) - { - if (binary.Method != null) { - VisitUserDefinedBinary (binary); - return; - } - - switch (binary.NodeType) { - case ExpressionType.ArrayIndex: - VisitArrayIndex (binary); - return; - case ExpressionType.Coalesce: - VisitCoalesce (binary); - return; - case ExpressionType.AndAlso: - case ExpressionType.OrElse: - VisitLogicalShortCircuitBinary (binary); - return; - case ExpressionType.Equal: - case ExpressionType.NotEqual: - case ExpressionType.GreaterThan: - case ExpressionType.GreaterThanOrEqual: - case ExpressionType.LessThan: - case ExpressionType.LessThanOrEqual: - VisitRelationalBinary (binary); - return; - case ExpressionType.And: - case ExpressionType.Or: - VisitLogicalBinary (binary); - return; - case ExpressionType.Power: - case ExpressionType.Add: - case ExpressionType.AddChecked: - case ExpressionType.Divide: - case ExpressionType.ExclusiveOr: - case ExpressionType.LeftShift: - case ExpressionType.Modulo: - case ExpressionType.Multiply: - case ExpressionType.MultiplyChecked: - case ExpressionType.RightShift: - case ExpressionType.Subtract: - case ExpressionType.SubtractChecked: - VisitArithmeticBinary (binary); - return; - } - } - - void VisitTypeAs (UnaryExpression unary) - { - Visit (unary.Operand); - - var value = Pop (); - if (value == null || !Math.IsType (unary.Type, value)) - Push (null); - else - Push (value); - } - - void VisitArrayLength (UnaryExpression unary) - { - Visit (unary.Operand); - - var array = (Array) Pop (); - Push (array.Length); - } - - void VisitConvert (UnaryExpression unary) - { - if (unary.NodeType == ExpressionType.ConvertChecked) - VisitConvertChecked (unary); - else - VisitConvertUnchecked (unary); - } - - void VisitConvertChecked (UnaryExpression unary) - { - VisitConvert (unary, Math.ConvertToTypeChecked); - } - - void VisitConvertUnchecked (UnaryExpression unary) - { - VisitConvert (unary, Math.ConvertToTypeUnchecked); - } - - void VisitConvert (UnaryExpression unary, Func<object, Type, Type, object> converter) - { - Visit (unary.Operand); - Push (converter (Pop (), unary.Operand.Type, unary.Type)); - } - - bool IsNullUnaryLifting (UnaryExpression unary) - { - var value = Pop (); - - if (unary.IsLifted && value == null) { - if (unary.IsLiftedToNull) { - Push (null); - return true; - } else { - throw new InvalidOperationException (); - } - } - - Push (value); - return false; - } - - void VisitQuote (UnaryExpression unary) - { - Push (unary.Operand); - } - - void VisitUserDefinedUnary (UnaryExpression unary) - { - Visit (unary.Operand); - - if (IsNullUnaryLifting (unary)) - return; - - var value = Pop (); - - Push (InvokeUnary (unary, value)); - } - - object InvokeUnary (UnaryExpression unary, object value) - { - return InvokeMethod (unary.Method, null, new [] { value }); - } - - void VisitArithmeticUnary (UnaryExpression unary) - { - Visit (unary.Operand); - - if (IsNullUnaryLifting (unary)) - return; - - var value = Pop (); - - switch (unary.NodeType) { - case ExpressionType.Not: - if (unary.Type.GetNotNullableType () == typeof (bool)) - Push (!Convert.ToBoolean (value)); - else - Push (~Convert.ToInt32 (value)); - return; - case ExpressionType.Negate: - Push (Math.Negate (value, Type.GetTypeCode (unary.Type.GetNotNullableType ()))); - return; - case ExpressionType.NegateChecked: - Push (Math.NegateChecked (value, Type.GetTypeCode (unary.Type.GetNotNullableType ()))); - return; - case ExpressionType.UnaryPlus: - Push (value); - return; - } - } - - protected override void VisitUnary (UnaryExpression unary) - { - if (unary.Method != null) { - VisitUserDefinedUnary (unary); - return; - } - - switch (unary.NodeType) { - case ExpressionType.Quote: - VisitQuote (unary); - return; - case ExpressionType.TypeAs: - VisitTypeAs (unary); - return; - case ExpressionType.ArrayLength: - VisitArrayLength (unary); - return; - case ExpressionType.Convert: - case ExpressionType.ConvertChecked: - VisitConvert (unary); - return; - case ExpressionType.Negate: - case ExpressionType.NegateChecked: - case ExpressionType.Not: - case ExpressionType.UnaryPlus: - VisitArithmeticUnary (unary); - return; - default: - throw new NotImplementedException (unary.NodeType.ToString ()); - } - } - - protected override void VisitNew (NewExpression nex) - { - if (nex.Constructor == null) - Push (Activator.CreateInstance (nex.Type)); - else - Push (InvokeConstructor (nex.Constructor, VisitListExpressions (nex.Arguments))); - } - - static object InvokeConstructor (ConstructorInfo constructor, object [] arguments) - { - try { - return constructor.Invoke (arguments); - } catch (TargetInvocationException e) { - throw e.InnerException; - } - } - - protected override void VisitTypeIs (TypeBinaryExpression type) - { - Visit (type.Expression); - Push (Math.IsType (type.TypeOperand, Pop ())); - } - - void VisitMemberInfo (MemberInfo mi) - { - mi.OnFieldOrProperty ( - field => { - object target = null; - if (!field.IsStatic) - target = Pop (); - - Push (field.GetValue (target)); - }, - property => { - object target = null; - var getter = property.GetGetMethod (true); - if (!getter.IsStatic) - target = Pop (); - - Push (property.GetValue (target, null)); - }); - } - - protected override void VisitMemberAccess (MemberExpression member) - { - Visit (member.Expression); - VisitMemberInfo (member.Member); - } - - protected override void VisitNewArray (NewArrayExpression newArray) - { - switch (newArray.NodeType) { - case ExpressionType.NewArrayInit: - VisitNewArrayInit (newArray); - return; - case ExpressionType.NewArrayBounds: - VisitNewArrayBounds (newArray); - return; - } - - throw new NotSupportedException (); - } - - void VisitNewArrayBounds (NewArrayExpression newArray) - { - var lengths = new int [newArray.Expressions.Count]; - for (int i = 0; i < lengths.Length; i++) { - Visit (newArray.Expressions [i]); - lengths [i] = (int) Pop (); - } - - Push (Array.CreateInstance (newArray.Type.GetElementType (), lengths)); - } - - void VisitNewArrayInit (NewArrayExpression newArray) - { - var array = Array.CreateInstance ( - newArray.Type.GetElementType (), - newArray.Expressions.Count); - - for (int i = 0; i < array.Length; i++) { - Visit (newArray.Expressions [i]); - array.SetValue (Pop (), i); - } - - Push (array); - } - - protected override void VisitConditional (ConditionalExpression conditional) - { - Visit (conditional.Test); - - if ((bool) Pop ()) - Visit (conditional.IfTrue); - else - Visit (conditional.IfFalse); - } - - protected override void VisitMethodCall (MethodCallExpression call) - { - object instance = null; - if (call.Object != null) { - Visit (call.Object); - instance = Pop (); - } - - Push (InvokeMethod (call.Method, instance, VisitListExpressions (call.Arguments))); - } - - protected override void VisitParameter (ParameterExpression parameter) - { - var info = lambdas.Peek (); - - var lambda = info.Lambda; - var arguments = info.Arguments; - - var index = GetParameterIndex (lambda, parameter); - if (index >= 0) { - Push (arguments [index]); - return; - } - - object value; - if (hoisted_values.TryGetValue (parameter, out value)) { - Push (value); - return; - } - - throw new ArgumentException (); - } - - protected override void VisitConstant (ConstantExpression constant) - { - Push (constant.Value); - } - - protected override void VisitInvocation (InvocationExpression invocation) - { - Visit (invocation.Expression); - Push (Invoke ((Delegate) Pop (), VisitListExpressions (invocation.Arguments))); - } - - static object Invoke (Delegate dlg, object [] arguments) - { - return InvokeMethod (dlg.Method, dlg.Target, arguments); - } - - static object InvokeMethod (MethodBase method, object obj, object [] arguments) - { - try { - return method.Invoke (obj, arguments); - } catch (TargetInvocationException e) { - throw e.InnerException; - } - } - - protected override void VisitMemberListBinding (MemberListBinding binding) - { - var value = Pop (); - Push (value); - VisitMemberInfo (binding.Member); - VisitElementInitializerList (binding.Initializers); - Pop (); // pop the member - Push (value); // push the original target - } - - protected override void VisitElementInitializer (ElementInit initializer) - { - object target = null; - if (!initializer.AddMethod.IsStatic) - target = Pop (); - - var arguments = VisitListExpressions (initializer.Arguments); - InvokeMethod (initializer.AddMethod, target, arguments); - - if (!initializer.AddMethod.IsStatic) - Push (target); - } - - protected override void VisitMemberMemberBinding (MemberMemberBinding binding) - { - var value = Pop (); - Push (value); - VisitMemberInfo (binding.Member); - VisitBindingList (binding.Bindings); - Pop (); - Push (value); - } - - protected override void VisitMemberAssignment (MemberAssignment assignment) - { - Visit (assignment.Expression); - - var value = Pop (); - - assignment.Member.OnFieldOrProperty ( - field => { - object target = null; - if (!field.IsStatic) - target = Pop (); - - field.SetValue (target, value); - - if (!field.IsStatic) - Push (target); - }, - property => { - object target = null; - var getter = property.GetGetMethod (true); - if (!getter.IsStatic) - target = Pop (); - - property.SetValue (target, value, null); - - if (!getter.IsStatic) - Push (target); - }); - } - - protected override void VisitLambda (LambdaExpression lambda) - { - Push (lambda.Compile (this)); - } - - private object [] VisitListExpressions (ReadOnlyCollection<Expression> collection) - { - object [] results = new object [collection.Count]; - for (int i = 0; i < results.Length; i++) { - Visit (collection [i]); - results [i] = Pop (); - } - - return results; - } - - void StoreHoistedVariables (LambdaExpression lambda, object [] arguments) - { - if (hoisted_map == null) - return; - - List<ParameterExpression> variables; - if (!hoisted_map.TryGetValue (lambda, out variables)) - return; - - foreach (var variable in variables) - StoreHoistedVariable (variable, lambda, arguments); - } - - void StoreHoistedVariable (ParameterExpression variable, LambdaExpression lambda, object [] arguments) - { - var index = GetParameterIndex (lambda, variable); - if (index < 0) - return; - - hoisted_values [variable] = arguments [index]; - } - - static int GetParameterIndex (LambdaExpression lambda, ParameterExpression parameter) - { - return lambda.Parameters.IndexOf (parameter); - } - - public object Interpret (LambdaExpression lambda, object [] arguments) - { - lambdas.Push (new LambdaInfo (lambda, arguments)); - - StoreHoistedVariables (lambda, arguments); - - Visit (lambda.Body); - - lambdas.Pop (); - - if (lambda.GetReturnType () != typeof (void)) - return Pop (); - - return null; - } - } -} |