Merge pull request #656 from LogosBible/collection_lock
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / LambdaExpression.cs
index edf0dffdb887988ded052cb7ee9cb1d31f4cecef..6e873b0c9b2d8b12c37a7362b4e0aaa9ff7e6620 100644 (file)
@@ -31,156 +31,74 @@ using System;
 using System.Collections.ObjectModel;
 using System.Collections.Generic;
 using System.Reflection;
+#if !FULL_AOT_RUNTIME
 using System.Reflection.Emit;
-using System.Threading;
+#endif
 
-namespace System.Linq.Expressions {
-
-       internal class EmitContext {
-               internal LambdaExpression Owner;
-               internal Type [] ParamTypes;
-               internal DynamicMethod Method;
-               internal ILGenerator ig;
-
-               static object mlock = new object ();
-               internal static int method_count;
-               static string GenName ()
-               {
-                       lock (mlock){
-                               return "<LINQ-" + method_count++ + ">";
-                       }
-               }
-               
-               public EmitContext (LambdaExpression owner)
-               {
-                       Owner = owner;
-
-                       ParamTypes = new Type [Owner.parameters.Count];
-                       for (int i = 0; i < Owner.parameters.Count; i++)
-                               ParamTypes [i] = Owner.parameters [i].Type;
-
-                       //
-                       // We probably want to use the 3.5 new API calls to associate
-                       // the method with the "sandboxed" Assembly, instead am currently
-                       // dumping these types in this class
-                       //
-                       Type owner_of_code = typeof (EmitContext);
-
-
-                       //
-                       // FIXME: Need to force this to be verifiable, see:
-                       // https://bugzilla.novell.com/show_bug.cgi?id=355005
-                       //
-                       string name = GenName ();
-                       Method = new DynamicMethod (name, Owner.Type, ParamTypes, owner_of_code);
-                       
-                       ig = Method.GetILGenerator ();
-               }
-
-               internal Delegate CreateDelegate ()
-               {
-                       return Method.CreateDelegate (Owner.delegate_type);                     
-               }
-
-               internal int GetParameterPosition (ParameterExpression p)
-               {
-                       int position = Owner.Parameters.IndexOf (p);
-                       if (position == -1)
-                               throw new InvalidOperationException ("Parameter not in scope");
 
-                       return position;
-               }
-       }
+namespace System.Linq.Expressions {
 
        public class LambdaExpression : Expression {
 
-               //
-               // LambdaExpression parameters
-               //
                Expression body;
-               internal ReadOnlyCollection<ParameterExpression> parameters;
-               internal Type delegate_type;
+               ReadOnlyCollection<ParameterExpression> parameters;
 
-               // This is set during compilation
-               Delegate lambda_delegate;
+               public Expression Body {
+                       get { return body; }
+               }
 
-               static bool CanAssign (Type target, Type source)
-               {
-                       // This catches object and value type mixage, type compatibility is handled later
-                       if (target.IsValueType ^ source.IsValueType)
-                               return false;
-                       
-                       return target.IsAssignableFrom (source);
+               public ReadOnlyCollection<ParameterExpression> Parameters {
+                       get { return parameters; }
                }
-                               
+
                internal LambdaExpression (Type delegateType, Expression body, ReadOnlyCollection<ParameterExpression> parameters)
-                       : base (ExpressionType.Lambda, body.Type)
+                       : base (ExpressionType.Lambda, delegateType)
                {
-                       if (!delegateType.IsSubclassOf (typeof (System.Delegate)))
-                               throw new ArgumentException ("delegateType");
-
-                       var invoke = delegateType.GetMethod ("Invoke", BindingFlags.Instance | BindingFlags.Public);
-                       if (invoke == null)
-                               throw new ArgumentException ("delegate must contain an Invoke method", "delegateType");
-
-                       var invoke_parameters = invoke.GetParameters ();
-                       if (invoke_parameters.Length != parameters.Count)
-                               throw new ArgumentException ("Different number of arguments in delegate {0}", "delegateType");
-
-                       for (int i = 0; i < invoke_parameters.Length; i++){
-                               if (!CanAssign (parameters [i].Type, invoke_parameters [i].ParameterType))
-                                       throw new ArgumentException (String.Format ("Can not assign a {0} to a {1}", invoke_parameters [i].ParameterType, parameters [i].Type));
-                       }
-
-                       if (!CanAssign (invoke.ReturnType, body.Type))
-                               throw new ArgumentException (String.Format ("body type {0} can not be assigned to {1}", body.Type, invoke.ReturnType));
-                       
                        this.body = body;
                        this.parameters = parameters;
-                       delegate_type = delegateType;
-               }
-               
-               public Expression Body {
-                       get { return body; }
                }
 
-               public ReadOnlyCollection<ParameterExpression> Parameters {
-                       get { return parameters; }
+#if !FULL_AOT_RUNTIME
+               void EmitPopIfNeeded (EmitContext ec)
+               {
+                       if (GetReturnType () == typeof (void) && body.Type != typeof (void))
+                               ec.ig.Emit (OpCodes.Pop);
                }
 
                internal override void Emit (EmitContext ec)
+               {
+                       ec.EmitCreateDelegate (this);
+               }
+
+               internal void EmitBody (EmitContext ec)
                {
                        body.Emit (ec);
+                       EmitPopIfNeeded (ec);
                        ec.ig.Emit (OpCodes.Ret);
                }
+#endif
 
-               public Delegate Compile ()
+               internal Type GetReturnType ()
                {
-                       if (lambda_delegate != null)
-                               return lambda_delegate;
-
-                       var ec = new EmitContext (this);
-
-                       Emit (ec);
-
-                       if (Environment.GetEnvironmentVariable ("LINQ_DBG") != null){
-                               string fname = "linq" + (EmitContext.method_count-1) + ".dll";
-                               AssemblyBuilder ab = Thread.GetDomain ().DefineDynamicAssembly (
-                                       new AssemblyName (fname), AssemblyBuilderAccess.RunAndSave, "/tmp");
-                               
-                               ModuleBuilder b = ab.DefineDynamicModule (fname, fname);
-                               TypeBuilder tb = b.DefineType ("LINQ", TypeAttributes.Public);
-                               MethodBuilder mb = tb.DefineMethod ("GeneratedMethod", MethodAttributes.Static, Type, ec.ParamTypes);
-                               ec.ig = mb.GetILGenerator ();
+                       return this.Type.GetInvokeMethod ().ReturnType;
+               }
 
-                               Emit (ec);
+               public Delegate Compile ()
+               {
+#if FULL_AOT_RUNTIME
+                       return new System.Linq.jvm.Runner (this).CreateDelegate ();
+#else
+                       var context = new CompilationContext ();
+                       context.AddCompilationUnit (this);
+                       return context.CreateDelegate ();
+#endif
+               }
 
-                               tb.CreateType ();
-                               ab.Save (fname);
-                       }
-                       
-                       lambda_delegate = ec.CreateDelegate ();
-                       return lambda_delegate;
+#if FULL_AOT_RUNTIME
+               internal Delegate Compile (System.Linq.jvm.ExpressionInterpreter interpreter)
+               {
+                       return new System.Linq.jvm.Runner (this, interpreter).CreateDelegate ();
                }
+#endif
        }
 }