? .ecore.cs.swp
? 1.cs
? 1.objtmp
? 2.cs
? 3.cs
? PLAN
? PROFILE
? a.cs
? a.objtmp
? a1.cs
? a1.il
? a10.cs
? a11.cs
? a12.cs
? a13.cs
? a14.cs
? a15.cs
? a2.cs
? a3.cs
? a4.cs
? a5.cs
? a6.cs
? a6.il
? a7.cs
? a8.cs
? a9.cs
? aa.cs
? aaa.cs
? anonymous-2.patch
? anonymous-5.patch
? anonymous.patch
? args
? b.cs
? b1.cs
? b1.il
? bb.cs
? bug.cs
? c.cs
? ch.cs
? co.cs
? cs.cs
? cs1628.cs
? d.cs
? de.cs
? de2.cs
? delegate.cs-orig
? delegate.cs.new
? e.cs
? e1.cs
? e2.cs
? e3.cs
? e4.cs
? e5.cs
? e6.cs
? emcs.cs
? en.cs
? f.cs
? fo.cs
? fu.cs
? g.cs
? h.cs
? i.cs
? ic.cs
? ii.cs
? j.cs
? jj.cs
? l-2
? l.cs
? log
? log2
? m.cs
? mcs-parser-bash-more-qi.patch
? old-statement.cs
? p
? patch-declspace-double-hash.diff
? r.cs
? res
? revert
? sa.cs
? split-lookup.patch
? ss.cs
? sss.cs
? t.cs
? te.cs
? test
? tt.cs
? tu.cs
? u.cs
? w.cs
? x
? x-decl.cs
? x.cs
? xx
? xx.cs
? xx.dll
? xy.cs
? y.cs
? z.cs
Index: ChangeLog
===================================================================
RCS file: /cvs/public/mcs/mcs/ChangeLog,v
retrieving revision 1.1424
diff -u -u -r1.1424 ChangeLog
--- ChangeLog	15 Apr 2004 03:13:00 -0000	1.1424
+++ ChangeLog	15 Apr 2004 22:35:25 -0000
@@ -1,3 +1,80 @@
+<<<<<<< ChangeLog
+2004-04-04  Miguel de Icaza  <miguel@ximian.com>
+
+	* expression.cs (ParameterReference): Use a byte flag to encode
+	status (IsOut, IsRef) and the new IsCaptured.
+
+	(DoResolveBase): If in an anonymous method, capturing a parameter,
+	capture it.
+
+2004-03-17  Miguel de Icaza  <miguel@ximian.com>
+
+	* codegen.cs (ResolveTopBlock): Thanks to Martin, we pass now an
+	EmitContext to ResolveTopBlock, and then we create the
+	current_flow_branching correctly, to perform flow analysis on the
+	anonymous method.
+
+2004-03-09  Miguel de Icaza  <miguel@ximian.com>
+
+	* codegen.cs (EmitContext.GetAnonymousMethodHost): Returns the
+	TypeBuilder that will host the anonymous method.
+
+	* anonymous.cs: (AnonymousDelegate.DoResolve): Set the eclass
+
+	(AnonymousMethod.Compatible): Call Resolve on the new
+	AnonymousMethod to get the instance method in place.
+
+	(AnonymousMethod.CreateMethodHost): use the method host for
+	storing this one.  Use a hack that sets the TypeBuilder in the
+	TypeContainer of the EmitContext to point to the method host
+	temporarily, so the method we define with 'new Method' is the
+	right one.
+
+	This depends on the implementation specifics of Method and
+	Method.Define which is slightly ugly.
+
+	(CaptureInfo.EmitHelperClasses): Store the last type as the
+	TypeBuilder for the method host.
+
+2004-02-23  Miguel de Icaza  <miguel@ximian.com>
+
+	* codegen.cs (EmitContext.EmitTopBlock): If we have an EmitContext
+	container, use the container capture_info, so we can propagate the
+	information about variables captured (otherwise they were only
+	being flagged as "captured" on the inner anonymous method block,
+	not the parent).
+	
+	(EmitContext.CaptureField, EmitContext.CaptureVariable): hook up
+	the parent capture_info if we have to initialize it.
+
+2004-02-15  Miguel de Icaza  <miguel@ximian.com>
+
+	* statement.cs (Switch): Do not allocate labels during the resolve
+	phase, as "ig" might be null (reverted temporarily, due to the
+	crash). 
+	
+	* assign.cs (LocalTemporary): Allocate the LocalBuilder during the
+	Emit phase, not the resolve phase.
+
+	* statement.cs (ResolveMeta): Do not generate a local_map for the
+	parent if we are a toplevel block.
+
+	* cs-parser.jay: In anonymous methods, we link the `Parent' of a
+	Toplevel for the anonymous block to its container, so we can
+	resolve local variable references to the container.
+
+	* anonymous.cs (CaptureInfo, BlockCaptureInfo): New classes that
+	encapsulate the captured variables and emit the helper classes
+	that track the captured/lifted values.
+
+	* statement.cs (TopLevel), codegen.cs (EmitContext): Moved the
+	code to capture variables from TopLevel to the EmitContext which
+	proxies to a CaptureInfo class most of the requests.
+
+	* codegen.cs: New API entry points for capturing locals and fields
+	and querying their state. 
+	
+=======
 2004-04-14  Miguel de Icaza  <miguel@ximian.com>
 
 	* iterators.cs: Avoid creating temporaries if there is no work to
@@ -44,6 +121,7 @@
 	* typemanager.cs, rootcontext.cs: Add System.Marshalbyrefobject as
 	another compiler type.
 
+>>>>>>> 1.1423
 2004-04-06 Ben Maurer  <bmaurer@users.sourceforge.net>
 
 	* class.cs (Indexer.Define): use the new name checking method.
@@ -673,6 +751,40 @@
 
         * delegate.cs (Define): Fixed crash when delegate type is undefined.
         
+2004-02-11  Miguel de Icaza  <miguel@ximian.com>
+
+	* expression.cs (LocalVariableReference): drop `is_readonly' use
+	the ReadOnly property from the LocalInfo instead.
+
+	* codegen.cs: Split EmitTopBlock into ResolveTopBlock who only
+	does resolution and EmitResolvedTopBlock that does the emission in
+	preparation for having an extra pass that resolves block 
+
+2004-02-08  Miguel de Icaza  <miguel@ximian.com>
+
+	* codegen.cs: remove RemapLocalLValue, now the caller code calls
+	the proper DoResolve/DoResolveLValue on the return.
+
+	* expression.cs (LocalVariableReference.DoResolveLValue): Perform
+	is_readonly check before the rest, I noticed that we might not do
+	this test for iterators/anonymous methods otherwise.
+	
+	If we are in an anonymous method, return a captured variable.
+
+	Resolve.
+
+	(DoResolve): If we are in an anonymous method, return the captured
+	variable. 
+
+2004-01-24  Miguel de Icaza  <miguel@ximian.com>
+
+	* convert.cs (Error_CannotChangeAccessModifiers): Improve error
+	reporting when we have anonymous methods.
+
+	* codegen.cs (EmitContext.EmitTopBlock): Now we require a
+	ToplevelBlock as an argument, the split 
+	
+
 2004-02-11  Miguel de Icaza  <miguel@ximian.com>
 
 	* cs-parser.jay: Fix small regression: we were not testing V2
Index: Makefile
===================================================================
RCS file: /cvs/public/mcs/mcs/Makefile,v
retrieving revision 1.18
diff -u -u -r1.18 Makefile
--- Makefile	25 Mar 2004 20:29:43 -0000	1.18
+++ Makefile	15 Apr 2004 22:35:25 -0000
@@ -69,6 +69,9 @@
 mcs.exe: $(all_sources)
 	$(BOOT_COMPILE) /target:exe /out:$@ $^
 
+args: $(all_sources)
+	echo $(BOOT_COMPILE) /target:exe /out:$@ $^ > args
+
 cs-parser.cs: cs-parser.jay $(topdir)/jay/skeleton.cs
 	$(topdir)/jay/jay -ctv < $(topdir)/jay/skeleton.cs $< >$@
 
@@ -83,10 +86,10 @@
 	ls -l mcs2.exe mcs3.exe
 
 mcs2.exe: mcs.exe
-	$(TIME) $(RUNTIME) ./mcs.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
+	$(TIME) $(RUNTIME) --debug ./mcs.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
 
 mcs3.exe: mcs2.exe
-	$(TIME) $(RUNTIME) ./mcs2.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
+	$(TIME) $(RUNTIME) --debug ./mcs2.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
 
 wc:
 	wc -l $(all_sources)
Index: TODO
===================================================================
RCS file: /cvs/public/mcs/mcs/TODO,v
retrieving revision 1.126
diff -u -u -r1.126 TODO
--- TODO	12 Feb 2004 00:08:15 -0000	1.126
+++ TODO	15 Apr 2004 22:35:25 -0000
@@ -1,3 +1,27 @@
+Anonymous methods
+-----------------
+
+	We are flagging 428 when doing anonymous method conversions from
+	a:
+
+		object o = delegate {}
+
+	Check if this is the error code (currently we know that 428 is ok
+	for object var = method_group_assignment case).
+
+	In anonymous.cs, when we create the EmitContext, investigate
+	the implications and the interactions of iterator methods with
+	anonymous method blocks and set the flag accordingly. 
+
+Review:
+	Every use of ToplevelBlock linkage to its parent (due to anon
+	methods).
+
+Clean Up
+--------
+
+	Move MapVariable from CodeGen into Block?
+
 Error Reporting:
 ----------------
 
@@ -5,9 +29,6 @@
 
 Iterators
 ---------
-	* `yield' is no longer a keyword, it only has special
-	  meaning before a return or break keywords.
-
 	* Study side effects with assign
 	* Study TemporaryStorage/LocalStorage -> Merge/rename
 
Index: anonymous.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/anonymous.cs,v
retrieving revision 1.1
diff -u -u -r1.1 anonymous.cs
--- anonymous.cs	28 May 2003 05:00:13 -0000	1.1
+++ anonymous.cs	15 Apr 2004 22:35:25 -0000
@@ -4,7 +4,7 @@
 // Author:
 //   Miguel de Icaza (miguel@ximain.com)
 //
-// (C) 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 
 using System;
@@ -17,13 +17,30 @@
 	public class AnonymousMethod : Expression {
 		// An array list of AnonymousMethodParameter or null
 		Parameters parameters;
-		Block block;
+		public ToplevelBlock Block;
+		static int anonymous_method_count;
+		Method method;
+		MethodInfo invoke_mb;
 		
-		public AnonymousMethod (Parameters parameters, Block block, Location l)
+		// The emit context for the anonymous method
+		public EmitContext aec;
+		public InternalParameters amp;
+		bool unreachable;
+		Block container;
+
+		//
+		// Points to the BlockCaptureInfo that is hosting the method
+		//
+		public BlockCaptureInfo MethodHost;
+		
+		public AnonymousMethod (Parameters parameters, ToplevelBlock container, ToplevelBlock block, Location l)
 		{
 			this.parameters = parameters;
-			this.block = block;
+			this.container = container;
+			Block = block;
 			loc = l;
+
+			container.RegisterAnonymousMethod (this);
 		}
 
 		public override Expression DoResolve (EmitContext ec)
@@ -39,13 +56,737 @@
 			// anywhere', we depend on special conversion
 			// rules.
 			// 
-			type = typeof (AnonymousMethod);
+			type = TypeManager.anonymous_method_type;
 			return this;
 		}
 
 		public override void Emit (EmitContext ec)
 		{
 			// nothing, as we only exist to not do anything.
+		}
+
+		//
+		// Creates the host for the anonymous method
+		//
+		bool CreateMethodHost (EmitContext ec, Type return_type)
+		{
+			int modifiers = Modifiers.INTERNAL;
+
+			//
+			// Crude hack follows: we replace the TypeBuilder during the
+			// definition to get the method hosted in the right class
+			//
+			
+			TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
+			MethodHost = ec.GetAnonymousMethodHost (container);
+			Console.WriteLine ("Assigning the method host: {0}", MethodHost);
+			TypeBuilder type_host = MethodHost == null ? current_type : MethodHost.TypeBuilder;
+				
+			if (current_type == type_host){
+				if (ec.IsStatic)
+					modifiers |= Modifiers.STATIC;
+				current_type = null;
+			} 
+
+			if (method != null)
+				throw new Exception ("Whoa!");
+			
+			method = new Method (ec.DeclSpace, new TypeExpression (return_type, loc),
+					     modifiers, false, "<#AnonymousMethod>" + anonymous_method_count++,
+					     parameters, null, loc);
+			method.Block = Block;
+
+			//
+			// Swap the TypeBuilder while we define the method, then restore
+			//
+			if (current_type != null)
+				ec.TypeContainer.TypeBuilder = type_host;
+			bool res = method.Define ((TypeContainer) ec.TypeContainer);
+			if (current_type != null)
+				ec.TypeContainer.TypeBuilder = current_type;
+			return res;
+		}
+		
+		void Error_ParameterMismatch (Type t)
+		{
+			Report.Error (1661, loc, String.Format ("Anonymous method could not be converted to delegate `" +
+								"{0}' since there is a parameter mismatch", t));
+		}
+		
+		//
+		// Returns true if this anonymous method can be implicitly
+		// converted to the delegate type `delegate_type'
+		//
+		public Expression Compatible (EmitContext ec, Type delegate_type)
+		{
+			//
+			// At this point its the first time we know the return type that is 
+			// needed for the anonymous method.  We create the method here.
+			//
+
+			invoke_mb = (MethodInfo) Delegate.GetInvokeMethod (ec, delegate_type, loc);
+			ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+
+			//
+			// If implicit parameters are set, then we must check for out in the parameters
+			// and flag it accordingly.
+			//
+			bool out_invalid_check = false;
+			
+			if (parameters == null){
+				int i, j;
+				out_invalid_check = true;
+				
+				//
+				// We provide a set of inaccessible parameters
+				//
+				int params_idx = -1;
+				for (i = 0; i < invoke_pd.Count; i++){
+					if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
+						params_idx = i;
+				}
+				int n = invoke_pd.Count - (params_idx != -1 ? 1 : 0);
+				Parameter [] fixedpars = new Parameter [n];
+				
+				for (i =  j = 0; i < invoke_pd.Count; i++){
+					if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
+						continue;
+					fixedpars [j] = new Parameter (
+						new TypeExpression (invoke_pd.ParameterType (i), loc),
+						"+" + j, invoke_pd.ParameterModifier (i), null);
+					j++;
+				}
+				
+				Parameter variable = null;
+				if (params_idx != -1){
+					variable = new Parameter (
+						new TypeExpression (invoke_pd.ParameterType (params_idx), loc),
+						"+" + params_idx, invoke_pd.ParameterModifier (params_idx), null);
+				}
+
+				parameters = new Parameters (fixedpars, variable, loc);
+			}
+			
+			//
+			// First, parameter types of `delegate_type' must be compatible
+			// with the anonymous method.
+			//
+			amp = new InternalParameters (ec.DeclSpace, parameters);
+			
+			if (amp.Count != invoke_pd.Count){
+				Report.Error (1593, loc, String.Format (
+					"Anonymous method has {0} parameters, while delegate requires {1}",
+					amp.Count, invoke_pd.Count));
+				Error_ParameterMismatch (delegate_type);
+				return null;
+			}
+			
+			for (int i = 0; i < amp.Count; i++){
+				Parameter.Modifier amp_mod = amp.ParameterModifier (i);
+				if (amp_mod != invoke_pd.ParameterModifier (i)){
+					Report.Error (1676, loc, String.Format (
+						"Signature mismatch in parameter modifier for parameter #{0}", i + 1));
+					Error_ParameterMismatch (delegate_type);
+					return null;
+				}
+				
+				if (amp.ParameterType (i) != invoke_pd.ParameterType (i)){
+					Report.Error (1678, loc, String.Format (
+						"Signature mismatch in parameter {0}: need `{1}' got `{2}'", i + 1,
+						TypeManager.CSharpName (invoke_pd.ParameterType (i)),
+						TypeManager.CSharpName (amp.ParameterType (i))));
+					Error_ParameterMismatch (delegate_type);
+					return null;
+				}
+				
+				if (out_invalid_check && (invoke_pd.ParameterModifier (i) & Parameter.Modifier.OUT) != 0){
+					Report.Error (1676, loc, String.Format (
+						"Parameter {0} must include the `out' modifier ", i+1));
+					Error_ParameterMismatch (delegate_type);
+					return null;
+				}
+			}
+
+			//
+			// Second: the return type of the delegate must be compatible with 
+			// the anonymous type.   Instead of doing a pass to examine the block
+			// we satisfy the rule by setting the return type on the EmitContext
+			// to be the delegate type return type.
+			//
+
+			//MethodBuilder builder = method_data.MethodBuilder;
+			//ILGenerator ig = builder.GetILGenerator ();
+			
+			aec = new EmitContext (
+				ec.TypeContainer, ec.DeclSpace, ec.loc, null,
+				invoke_mb.ReturnType,
+				(ec.IsStatic ? Modifiers.STATIC : 0) |
+				/* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
+				(ec.InUnsafe ? Modifiers.UNSAFE : 0),
+				/* No constructor */ false);
+
+			aec.CurrentAnonymousMethod = this;
+			aec.EmitContainer = ec;
+			bool res = aec.ResolveTopBlock (ec, Block, amp, loc, out unreachable);
+			
+			if (res){
+				return new AnonymousDelegate (this, delegate_type, loc).Resolve (ec);
+			}
+			return null;
+		}
+
+		public MethodBuilder GetMethodBuilder ()
+		{
+			return method.MethodData.MethodBuilder;
+		}
+		
+		public void EmitMethod (EmitContext ec)
+		{
+			Console.WriteLine ("Emitting method at " + loc);
+			if (!CreateMethodHost (ec, invoke_mb.ReturnType))
+				return;
+
+			MethodBuilder builder = GetMethodBuilder ();
+			ILGenerator ig = builder.GetILGenerator ();
+			aec.ig = ig;
+			
+			MethodCore.LabelParameters (aec, builder, parameters, null, loc);
+
+			aec.EmitMeta (Block, amp);
+			aec.EmitResolvedTopBlock (Block, unreachable);
+		}
+	}
+
+	//
+	// This will emit the code for the delegate, as well delegate creation on the host
+	//
+	public class AnonymousDelegate : DelegateCreation {
+		AnonymousMethod am;
+
+		public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
+		{
+			type = target_type;
+			loc = l;
+			this.am = am;
+		}
+
+		public override Expression DoResolve (EmitContext ec)
+		{
+			delegate_instance_expr = new AnonymousInstance (this);
+			eclass = ExprClass.Value;
+			return this;
+		}
+		
+		public override void Emit (EmitContext ec)
+		{
+			am.EmitMethod (ec);
+
+			//
+			// Now emit the delegate creation.
+			//
+			Expression ml = Expression.MemberLookup (ec, type, ".ctor", loc);
+			constructor_method = ((MethodGroupExpr) ml).Methods [0];
+			delegate_method = am.GetMethodBuilder ();
+			base.Emit (ec);
+		}
+
+		class AnonymousInstance : Expression {
+			public bool had_instance;
+			AnonymousDelegate ad;
+			
+			public AnonymousInstance (AnonymousDelegate ad)
+			{
+				this.ad = ad;
+				eclass = ExprClass.Value;
+				type = null;
+			}
+
+			public override Expression DoResolve (EmitContext ec)
+			{
+				return this;
+			}
+			
+			public override void Emit (EmitContext ec)
+			{
+				ad.am.aec.EmitMethodHostInstance (ec, ad.am);
+			}
+		}
+	}
+
+	class CapturedParameter {
+		public Type Type;
+		public string Name;
+		public FieldBuilder FieldBuilder;
+		public int Idx;
+
+		public CapturedParameter (string name, Type type, int idx)
+		{
+			Name = name;
+			Type = type;
+			Idx = idx;
+		}
+	}
+	
+	//
+	// This tracks all the captured variables, invoked from the ToplevelBlock code.
+	//
+	public class BlockCaptureInfo {
+		public Block Block;
+		public Hashtable variables;
+		public TypeBuilder TypeBuilder;
+		public ConstructorBuilder Constructor;
+		public FieldBuilder THIS;
+
+		public FieldBuilder ParentLink;
+
+		//
+		// The LocalBuilder is used on the method that hosts the anonymous method
+		//
+		public LocalBuilder Local; 
+		public bool Inited;
+		public BlockCaptureInfo Parent;
+
+		public int id;
+		
+		public override string ToString ()
+		{
+			return String.Format ("BlockCaptureInfo #{0}", id);
+		}
+		
+		public BlockCaptureInfo (Block block, BlockCaptureInfo parent, LocalInfo variable)
+		{
+			Block = block;
+			Parent = parent;
+			variables = new Hashtable ();
+
+			if (variable != null){
+				// Any value will do it, as long as variables [variable]
+				variables [variable] = block;
+			}
+			id = count++;
+		}
+
+		static int count;
+
+		public string MakeHelperName ()
+		{
+			return "<>c_DisplayClass" + id;
+		}
+
+		//
+		// Emits a single helper class to proxy the variable uses,
+		// one field per variable;   Optionally generate a `this' pointer
+		// and optionally generate a `link' to the container
+		//
+		// This has a side effect if captured_variables is non-null: it expects
+		// the hashtable to contain name/type pairs, and replaces it with name/fieldbuilders
+		//
+		public void EmitHelperClass (EmitContext ec, bool need_this, Hashtable captured_parameters)
+		{
+			ILGenerator ig = ec.ig;
+			TypeBuilder container = ec.TypeContainer.TypeBuilder;
+
+			TypeBuilder = container.DefineNestedType (
+				MakeHelperName (), TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.NestedPublic,
+				TypeManager.object_type, null);
+
+			if (need_this)
+				THIS = TypeBuilder.DefineField ("THIS", container, FieldAttributes.Assembly);
+
+			if (Parent != null){
+				if (Parent.TypeBuilder == null)
+					throw new Exception ("My parent has not been initialized");
+				
+				ParentLink = TypeBuilder.DefineField ("parent", Parent.TypeBuilder, FieldAttributes.Assembly);
+			}
+			
+			if (need_this && Parent != null){
+				//
+				// Code in EmitLocalCaptureContext also assumes this:
+				//
+				throw new Exception ("I was not expecting THIS && having a parent");
+				
+			}
+
+			foreach (LocalInfo info in variables.Keys){
+				info.FieldBuilder = TypeBuilder.DefineField (
+					"<f:"+ info.Name + ">", info.VariableType, FieldAttributes.Assembly);
+			}
+
+			Type [] constructor_types = TypeManager.NoTypes;
+			Parameters constructor_parameters = Parameters.EmptyReadOnlyParameters;
+			Constructor = TypeBuilder.DefineConstructor (
+				MethodAttributes.Public | MethodAttributes.HideBySig |
+				MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
+				CallingConventions.HasThis, constructor_types);
+			InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
+			TypeManager.RegisterMethod (Constructor, parameter_info, constructor_types);
+
+			ILGenerator cig = Constructor.GetILGenerator ();
+			cig.Emit (OpCodes.Ldarg_0);
+			cig.Emit (OpCodes.Call, TypeManager.object_ctor);
+			cig.Emit (OpCodes.Ret);
+		}
+
+		//
+		// Ensures that the local information has been emitted
+		//
+		public void EnsureLocalEmitted (EmitContext ec, CaptureInfo capture_info)
+		{
+			if (Inited)
+				return;
+
+			Inited = true;
+
+			ILGenerator ig = ec.ig;
+
+			ig.Emit (OpCodes.Newobj, (ConstructorInfo) Constructor);
+			if (Local == null)
+				Local = ec.ig.DeclareLocal (TypeBuilder);
+
+			ig.Emit (OpCodes.Stloc, Local);
+
+			if (THIS != null){
+				ig.Emit (OpCodes.Ldloc, Local);
+				ig.Emit (OpCodes.Ldarg_0);
+				ig.Emit (OpCodes.Stfld, THIS);
+			}
+		}
+		
+	}
+
+	public class CaptureInfo {
+		public bool Inited;
+		ArrayList block_list;
+		Hashtable captured_fields;
+		Hashtable captured_parameters;
+		bool closed;
+		
+		public CaptureInfo ()
+		{
+			block_list = new ArrayList ();
+			captured_fields = new Hashtable ();
+		}
+
+		public void AddLocal (LocalInfo li)
+		{
+			Block variable_block = li.Block;
+			int top = block_list.Count;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+				if (bci.Block == variable_block){
+					if (bci.variables.Contains (li))
+						return;
+					bci.variables [li] = true;
+					return;
+				}
+			}
+
+			//
+			// Find out whether this block has a captured parent, we start
+			// at the end, to get the closest container block
+			//
+			BlockCaptureInfo parent = null;
+			for (int i = top-1; i >= 0; i--){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				if (variable_block.IsChildOf (bci.Block)){
+					parent = bci;
+					break;
+				}
+			}
+
+			block_list.Add (new BlockCaptureInfo (variable_block, parent, li));
+		}
+
+		public void AddParameter (Block block, string name, Type t, int idx)
+		{
+			if (captured_parameters == null)
+				captured_parameters = new Hashtable ();
+			captured_parameters [name] = new CapturedParameter (name, t, idx);
+
+			// Ensure there is at least one block
+			if (block_list.Count == 0)
+				block_list.Add (new BlockCaptureInfo (block, null, null));
+		}
+		
+		public bool HaveCapturedVariables ()
+		{
+			return block_list.Count > 0;
+		}
+
+		public bool HaveCapturedFields ()
+		{
+			return captured_fields.Count > 0;
+		}
+		
+		public bool IsCaptured (LocalInfo li)
+		{
+			Block variable_block = li.Block;
+			int top = block_list.Count;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+				if (bci.Block == variable_block)
+					return (bci.variables [li] != null);
+			}
+			return false;
+		}
+
+		public bool IsParameterCaptured (string name)
+		{
+			if (captured_parameters != null)
+				return captured_parameters [name] != null;
+			return false;
+		}
+
+		//
+		// Registers the field as captured
+		//
+		public void AddField (FieldExpr fe)
+		{
+			if (fe.IsStatic){
+				Console.WriteLine ("Warning: Compiler tried to capture a static field");
+				return;
+			}
+			
+			captured_fields [fe] = true;
+		}
+
+		//
+		// Whether we need to generate a `THIS' field on the toplevel helper class
+		//
+		public bool NeedThis ()
+		{
+			return HaveCapturedFields ();
+		}
+
+		//
+		// Emits all the classes that track state for the anonymous methods
+		// 
+		public void EmitHelperClasses (EmitContext ec)
+		{
+			//
+			// We are called twice: one in the container class, and once
+			// for each AnonymousMethod, we only need to be called in the
+			// parent
+			//
+			if (Inited)
+				return;
+
+			Inited = true;
+			    
+			int top = block_list.Count;
+			bool need_this = NeedThis ();
+
+			Hashtable parameters = captured_parameters;
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				bci.EmitHelperClass (ec, need_this, parameters);
+				need_this = false;
+				parameters = null;
+				
+				if (i != 0)
+					continue;
+
+				//
+				// For the first block, copy the parameters into fields
+				//
+				bci.EnsureLocalEmitted (ec, this);
+
+				if (captured_parameters == null)
+					continue;
+				
+				ILGenerator ig = ec.ig;
+				int idx = ec.IsStatic ? 0 : 1;
+				
+				foreach (string name in captured_parameters.Keys){
+					FieldBuilder fb;
+					
+					CapturedParameter cp = (CapturedParameter) captured_parameters [name];
+					
+					fb = bci.TypeBuilder.DefineField (
+						"<p:" + name + ">", cp.Type, FieldAttributes.Assembly);
+					
+					cp.FieldBuilder = fb;
+					
+					ig.Emit (OpCodes.Ldloc, bci.Local);
+					ParameterReference.EmitLdArg (ig, cp.Idx);
+					ig.Emit (OpCodes.Stfld, fb);
+				}
+			}
+		}
+
+		BlockCaptureInfo GetBlockCaptureInfo (Block b)
+		{
+			int top = block_list.Count;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				if (bci.Block == b)
+					return bci;
+			}
+			throw new Exception ("Internal error: can not find capture information for block: " + b.ID);
+		}
+		
+		//
+		// Informs reflection that we are done with the classes
+		//
+		public void CloseHelperClasses ()
+		{
+			if (closed)
+				return;
+
+			int top = block_list.Count;
+			
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				bci.TypeBuilder.CreateType ();
+			}
+			closed = true;
+		}
+
+		void DoInit (EmitContext ec, BlockCaptureInfo bci)
+		{
+			bci.EnsureLocalEmitted (ec, this);
+			BlockCaptureInfo parent = bci.Parent;
+
+			ILGenerator ig = ec.ig;
+
+			if (parent != null){
+				ig.Emit (OpCodes.Ldloc, bci.Local);
+				ig.Emit (OpCodes.Ldloc, parent.Local);
+				ig.Emit (OpCodes.Stfld, bci.ParentLink);
+			}
+		}
+		
+		//
+		// Emits the instance pointer for the host method
+		//
+		public void EmitMethodHostInstance (EmitContext ec, AnonymousMethod am)
+		{
+			ILGenerator ig = ec.ig;
+
+			BlockCaptureInfo bci = am.MethodHost;
+			if (!bci.Inited)
+				DoInit (ec, bci);
+			
+			ig.Emit (OpCodes.Ldloc, bci.Local);
+		}
+
+		//
+		// Emits the proper temporary variable that is appropriate for this
+		// captured variable for calls in the host of the anonymous method.
+		//
+		// If needed, initializes the value
+		//
+		public void EmitHostCapturedContext (EmitContext ec, LocalInfo li)
+		{
+			ILGenerator ig = ec.ig;
+
+			BlockCaptureInfo bci = GetBlockCaptureInfo (li.Block);
+
+			if (!bci.Inited)
+				DoInit (ec, bci);
+			
+			ig.Emit (OpCodes.Ldloc, bci.Local);
+		}
+
+		//
+		// Emits the variable context while invoked inside the anonymous
+		// method.
+		//
+		public void EmitVariableContext (EmitContext ec, LocalInfo li, AnonymousMethod am)
+		{
+			int top = block_list.Count;
+			BlockCaptureInfo b, host_block = am.MethodHost;
+			ILGenerator ig = ec.ig;
+
+			if (host_block == null){
+				Console.WriteLine ("In big trouble: null method host");
+				return;
+			}
+			
+			ig.Emit (OpCodes.Ldarg_0);
+			b = host_block;
+			while (b.Block != li.Block){
+				Console.WriteLine ("At block: " + b.Block.ID);
+				ig.Emit (OpCodes.Ldfld, b.ParentLink);
+				b = b.Parent;
+				if (b == null)
+					throw new Exception ("Did not find block in hierarchy for variable");
+			}
+		}
+
+		//
+		// Emits the equivalent to Expression.Emit for the parameter
+		//
+		public void EmitParameter (EmitContext ec, string name)
+		{
+			ILGenerator ig = ec.ig;
+
+			ig.Emit (OpCodes.Ldarg_0);
+			CapturedParameter cp = (CapturedParameter) captured_parameters [name];
+			ig.Emit (OpCodes.Ldfld, cp.FieldBuilder);
+		}
+
+		//
+		// Emits the equivalent to Expression.EmitAssign for the parameter
+		//
+		public void EmitAssignParameter (EmitContext ec, string name, Expression source)
+		{
+			ILGenerator ig = ec.ig;
+
+			ig.Emit (OpCodes.Ldarg_0);
+			source.Emit (ec);
+			CapturedParameter cp = (CapturedParameter) captured_parameters [name];
+			ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
+		}
+
+		//
+		// Emits the equivalent to Expression.AddressOf for the parameter
+		//
+		public void EmitAddressOfParameter (EmitContext ec, string name)
+		{
+			ILGenerator ig = ec.ig;
+
+			ig.Emit (OpCodes.Ldarg_0);
+			CapturedParameter cp = (CapturedParameter) captured_parameters [name];
+			ig.Emit (OpCodes.Ldflda, cp.FieldBuilder);
+		}
+		
+		public void EmitContext (EmitContext ec, LocalInfo li)
+		{
+			int top = block_list.Count;
+			Block variable_block = li.Block;
+			
+			ILGenerator ig = ec.ig;
+			ig.Emit (OpCodes.Ldarg_0);
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				if (bci.Block == variable_block)
+					break;
+
+				ig.Emit (OpCodes.Ldfld, bci.ParentLink);
+			}
+		}
+
+		public BlockCaptureInfo GetMethodHost (Block container)
+		{
+			int top = block_list.Count;
+
+			for (int i = top-1; i >= 0; i--){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				if (container == bci.Block || bci.Block.IsChildOf (container))
+					return bci;
+			}
+			return null;
 		}
 	}
 }
Index: assign.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/assign.cs,v
retrieving revision 1.75
diff -u -u -r1.75 assign.cs
--- assign.cs	7 Feb 2004 05:54:15 -0000	1.75
+++ assign.cs	15 Apr 2004 22:35:25 -0000
@@ -64,7 +64,6 @@
 			type = t;
 			eclass = ExprClass.Value;
 			loc = Location.Null;
-			builder = ec.GetTemporaryLocal (t);
 		}
 
 		public void Release (EmitContext ec)
@@ -88,16 +87,22 @@
 
 		public override void Emit (EmitContext ec)
 		{
+			if (builder == null)
+				builder = ec.GetTemporaryLocal (type);
 			ec.ig.Emit (OpCodes.Ldloc, builder); 
 		}
 
 		public void Store (EmitContext ec)
 		{
+			if (builder == null)
+				builder = ec.GetTemporaryLocal (type);
 			ec.ig.Emit (OpCodes.Stloc, builder);
 		}
 
 		public void AddressOf (EmitContext ec, AddressOp mode)
 		{
+			if (builder == null)
+				builder = ec.GetTemporaryLocal (type);
 			ec.ig.Emit (OpCodes.Ldloca, builder);
 		}
 	}
Index: class.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/class.cs,v
retrieving revision 1.420
diff -u -u -r1.420 class.cs
--- class.cs	10 Apr 2004 18:56:55 -0000	1.420
+++ class.cs	15 Apr 2004 22:35:25 -0000
@@ -2424,7 +2424,7 @@
 
 	public abstract class MethodCore : MemberBase {
 		public readonly Parameters Parameters;
-		protected Block block;
+		protected ToplevelBlock block;
 		protected DeclSpace ds;
 		
 		//
@@ -2467,7 +2467,7 @@
 			}
 		}
 		
-		public Block Block {
+		public ToplevelBlock Block {
 			get {
 				return block;
 			}
@@ -2872,7 +2872,7 @@
 					    ParameterTypes, ParameterInfo,
 					    ModFlags, Location);
 
-				Block new_block = ih.Setup (block);
+				ToplevelBlock new_block = ih.Setup (block);
 				if (new_block == null)
 					return false;
 				block = new_block;
@@ -3741,7 +3741,7 @@
 		//
 		// Emits the code
 		// 
-		public virtual void Emit (TypeContainer container, Block block, object kind)
+		public virtual void Emit (TypeContainer container, ToplevelBlock block, object kind)
 		{
 			ILGenerator ig;
 			EmitContext ec;
@@ -3833,7 +3833,7 @@
 			}
 		}
 
-		void EmitDestructor (EmitContext ec, Block block)
+		void EmitDestructor (EmitContext ec, ToplevelBlock block)
 		{
 			ILGenerator ig = ec.ig;
 			
@@ -4268,7 +4268,10 @@
 		public Status status;
 
 		[Flags]
-		public enum Status : byte { ASSIGNED = 1, USED = 2 }
+		public enum Status : byte {
+			ASSIGNED = 1,
+			USED = 2
+		}
 
 		//
 		// The constructor is only exposed to our children
@@ -4290,6 +4293,7 @@
 		}
 
 		protected readonly Object init;
+
 		// Private.
 		Expression init_expr;
 		bool init_expr_initialized = false;
@@ -4477,10 +4481,10 @@
 		//
 		// Null if the accessor is empty, or a Block if not
 		//
-		public Block Block;
+		public ToplevelBlock Block;
 		public Attributes OptAttributes;
 		
-		public Accessor (Block b, Attributes attrs)
+		public Accessor (ToplevelBlock b, Attributes attrs)
 		{
 			Block = b;
 			OptAttributes = attrs;
@@ -4749,7 +4753,7 @@
 										   "get", container, MemberType,
 										   parameters, ip, ModFlags, Location);
 					
-					Block new_block = ih.Setup (block);
+					ToplevelBlock new_block = ih.Setup (block);
 					if (new_block == null)
 						return false;
 					block = new_block;
@@ -5444,7 +5448,7 @@
 		public readonly Expression ReturnType;
 		public readonly Expression FirstArgType, SecondArgType;
 		public readonly string FirstArgName, SecondArgName;
-		public Block           Block;
+		public ToplevelBlock   Block;
 		public MethodBuilder   OperatorMethodBuilder;
 		
 		public string MethodName;
@@ -5453,7 +5457,7 @@
 		public Operator (OpType type, Expression ret_type, int mod_flags,
 				 Expression arg1type, string arg1name,
 				 Expression arg2type, string arg2name,
-				 Block block, Attributes attrs, Location loc)
+				 ToplevelBlock block, Attributes attrs, Location loc)
 			: base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
 		{
 			OperatorType = type;
Index: codegen.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/codegen.cs,v
retrieving revision 1.147
diff -u -u -r1.147 codegen.cs
--- codegen.cs	14 Apr 2004 23:32:01 -0000	1.147
+++ codegen.cs	15 Apr 2004 22:35:25 -0000
@@ -4,9 +4,10 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //
-// (C) 2001 Ximian, Inc.
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2004 Novell, Inc.
 //
-
+//#define PRODUCTION
 using System;
 using System.IO;
 using System.Collections;
@@ -342,7 +343,7 @@
 		/// <summary>
 		///  Whether we are inside an anonymous method.
 		/// </summary>
-		public bool InAnonymousMethod;
+		public AnonymousMethod CurrentAnonymousMethod;
 		
 		/// <summary>
 		///   Location for this EmitContext
@@ -366,8 +367,20 @@
 		/// </summary>
 		public bool InEnumContext;
 
+		/// <summary>
+		///   Anonymous methods can capture local variables and fields,
+		///   this object tracks it.
+		/// </summary>
+		public CaptureInfo capture_info;
+
 		FlowBranching current_flow_branching;
-		
+
+		/// <summary>
+		///   In anonymous methods, points to the parent, so
+		///   capture information about variables can be tracked
+		/// </summary>
+		public EmitContext emit_container;
+
 		public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
 				    Type return_type, int code_flags, bool is_constructor)
 		{
@@ -395,7 +408,7 @@
 					InUnsafe = (code_flags & Modifiers.UNSAFE) != 0;
 			}
 			loc = l;
-			
+
 			if (ReturnType == TypeManager.void_type)
 				ReturnType = null;
 		}
@@ -418,6 +431,11 @@
 			}
 		}
 
+		public bool HaveCaptureInfo ()
+		{
+			return capture_info != null;
+		}
+
 		// <summary>
 		//   Starts a new code branching.  This inherits the state of all local
 		//   variables and parameters from the current branching.
@@ -476,30 +494,171 @@
 			current_flow_branching = current_flow_branching.Parent;
 		}
 
-		public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
+		public void CaptureVariable (LocalInfo li)
+		{
+			if (capture_info == null){
+				capture_info = new CaptureInfo ();
+				if (emit_container != null){
+					if (emit_container.capture_info != null)
+						throw new Exception ("we should have propagated capture_info");
+					emit_container.capture_info = capture_info;
+				}
+			}
+			capture_info.AddLocal (li);
+			li.IsCaptured = true;
+		}
+
+		public void CaptureParameter (string name, Type t, int idx)
+		{
+			if (capture_info == null){
+				capture_info = new CaptureInfo ();
+				if (emit_container != null){
+					if (emit_container.capture_info != null)
+						throw new Exception ("we should have propagated capture_info");
+					emit_container.capture_info = capture_info;
+				}
+			}
+			capture_info.AddParameter (CurrentBlock, name, t, idx);
+		}
+		
+		//
+		// Whether anonymous methods have captured variables
+		//
+		public bool HaveCapturedVariables ()
+		{
+			if (capture_info != null)
+				return capture_info.HaveCapturedVariables ();
+			return false;
+		}
+
+		//
+		// Whether anonymous methods have captured fields or this.
+		//
+		public bool HaveCapturedFields ()
+		{
+			if (capture_info != null)
+				return capture_info.HaveCapturedFields ();
+			return false;
+		}
+
+		//
+		// Emits the instance pointer for the host method
+		//
+		public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
+		{
+			if (capture_info != null)
+				capture_info.EmitMethodHostInstance (target, am);
+			else if (IsStatic)
+				target.ig.Emit (OpCodes.Ldnull);
+			else
+				target.ig.Emit (OpCodes.Ldarg_0);
+		}
+
+		//
+		// Returns whether the `local' variable has been captured by an anonymous
+		// method
+		//
+		public bool IsCaptured (LocalInfo local)
+		{
+			return capture_info.IsCaptured (local);
+		}
+
+		public bool IsParameterCaptured (string name)
 		{
-			bool unreachable = false;
+			return capture_info.IsParameterCaptured (name);
+		}
+		
+		//
+		// Use to register a field as captured
+		//
+		public void CaptureField (FieldExpr fe)
+		{
+			if (capture_info == null){
+				capture_info = new CaptureInfo ();
+				if (emit_container != null){
+					if (emit_container.capture_info != null)
+						throw new Exception ("we should have propagated capture_info");
+					emit_container.capture_info = capture_info;
+				}
+			}
+			capture_info.AddField (fe);
+		}
+
+		public void EmitMeta (ToplevelBlock b, InternalParameters ip)
+		{
+			if (capture_info != null)
+				capture_info.EmitHelperClasses (this);
+			b.EmitMeta (this);
+		}
+
+		public EmitContext EmitContainer {
+			get {
+				return emit_container;
+			}
+
+			set {
+				emit_container = value;
+				capture_info = emit_container.capture_info;
+			}
+		}
 
+		//
+		// Here until we can fix the problem with Mono.CSharp.Switch, which
+		// currently can not cope with ig == null during resolve (which must
+		// be fixed for switch statements to work on anonymous methods).
+		//
+		ILGenerator cheat;
+
+		public void EmitTopBlock (ToplevelBlock block, InternalParameters ip, Location loc)
+		{
+			bool unreachable;
+
+			if (EmitContainer != null)
+				capture_info = EmitContainer.capture_info;
+
+			cheat = ig;
+			//ig = null;
+			if (ResolveTopBlock (null, block, ip, loc, out unreachable)){
+				ig = cheat;
+				EmitMeta (block, ip);
+
+				EmitResolvedTopBlock (block, unreachable);
+			}
+		}
+
+		public bool ResolveTopBlock (EmitContext anonymous_method_host,
+					     ToplevelBlock block, InternalParameters ip, Location loc, out bool unreachable)
+		{
+			unreachable = false;
+			
 			if (!Location.IsNull (loc))
 				CurrentFile = loc.File;
 
 			if (block != null){
+#if PRODUCTION
 			    try {
+#endif
 				int errors = Report.Errors;
 
-				block.EmitMeta (this, ip);
+				block.ResolveMeta (block, this, ip);
 
+				
 				if (Report.Errors == errors){
 					bool old_do_flow_analysis = DoFlowAnalysis;
 					DoFlowAnalysis = true;
 
-					current_flow_branching = FlowBranching.CreateBranching (
-						null, FlowBranching.BranchingType.Block, block, loc);
+					if (anonymous_method_host != null)
+						current_flow_branching = FlowBranching.CreateBranching (
+						anonymous_method_host.CurrentBranching, FlowBranching.BranchingType.Block,
+						block, loc);
+					else 
+						current_flow_branching = FlowBranching.CreateBranching (
+							null, FlowBranching.BranchingType.Block, block, loc);
 
 					if (!block.Resolve (this)) {
 						current_flow_branching = null;
 						DoFlowAnalysis = old_do_flow_analysis;
-						return;
+						return false;
 					}
 
 					FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
@@ -507,13 +666,12 @@
 					
 					DoFlowAnalysis = old_do_flow_analysis;
 
-					block.Emit (this);
-
 					if (reachability.AlwaysReturns ||
 					    reachability.AlwaysThrows ||
 					    reachability.IsUnreachable)
 						unreachable = true;
 				}
+#if PRODUCTION
 			    } catch (Exception e) {
 					Console.WriteLine ("Exception caught by the compiler while compiling:");
 					Console.WriteLine ("   Block that caused the problem begin at: " + loc);
@@ -523,19 +681,26 @@
 								   CurrentBlock.StartLocation, CurrentBlock.EndLocation);
 					}
 					Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
-					Console.WriteLine (Report.FriendlyStackTrace (e));
-					
-					Environment.Exit (1);
+					throw;
 			    }
+#endif
 			}
 
 			if (ReturnType != null && !unreachable){
 				if (!InIterator){
 					Report.Error (161, loc, "Not all code paths return a value");
-					return;
+					return false;
 				}
 			}
+			return true;
+		}
 
+		public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
+		{
+			if (block != null){
+				block.Emit (this);
+			}
+			
 			if (HasReturnLabel)
 				ig.MarkLabel (ReturnLabel);
 			if (return_value != null){
@@ -563,6 +728,12 @@
 					ig.Emit (OpCodes.Ret);
 				}
 			}
+
+			//
+			// Close pending helper classes if we are the toplevel
+			//
+			if (capture_info != null && emit_container == null)
+				capture_info.CloseHelperClasses ();
 		}
 
 		/// <summary>
@@ -701,14 +872,7 @@
 		{
 			FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
 			fe.InstanceExpression = new ProxyInstance ();
-			return fe.DoResolve (this);
-		}
-
-		public Expression RemapLocalLValue (LocalInfo local_info, Expression right_side)
-		{
-			FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
-			fe.InstanceExpression = new ProxyInstance ();
-			return fe.DoResolveLValue (this, right_side);
+			return fe;
 		}
 
 		public Expression RemapParameter (int idx)
@@ -740,10 +904,67 @@
 					else
 						ig.Emit (OpCodes.Ldfld, this_field);
 				} 
-			} else
+			} else if (capture_info != null && CurrentAnonymousMethod != null){
+				BlockCaptureInfo bci = CurrentAnonymousMethod.MethodHost;
+				
+				ig.Emit (OpCodes.Ldarg_0);
+				
+				while (bci != null){
+					ig.Emit (OpCodes.Ldfld, bci.ParentLink);
+					bci = bci.Parent;
+				}
+			} else 
 				ig.Emit (OpCodes.Ldarg_0);
 		}
 
+		public void EmitCapturedContext (LocalInfo li)
+		{
+			if (capture_info != null){
+				if (CurrentAnonymousMethod != null)
+					capture_info.EmitVariableContext (this, li, CurrentAnonymousMethod);
+				else
+					capture_info.EmitHostCapturedContext (this, li);
+			} 
+		}
+
+		public void EmitParameter (string name)
+		{
+			capture_info.EmitParameter (this, name);
+		}
+
+		public void EmitAssignParameter (string name, Expression source)
+		{
+			capture_info.EmitAssignParameter (this, name, source);
+		}
+
+		public void EmitAddressOfParameter (string name)
+		{
+			capture_info.EmitAddressOfParameter (this, name);
+		}
+		
+		//
+		// Returns the TypeBuilder that hosts the anonymous method:
+		// it can be the current one (no captured locals for example),
+		// or it can be the same type.
+		//
+		public BlockCaptureInfo GetAnonymousMethodHost (Block container)
+		{
+			//
+			// If we have captured information, the anonymous method will be
+			// nested in the helper class
+			//
+			if (capture_info != null){
+				BlockCaptureInfo bci = capture_info.GetMethodHost (container);
+				if (bci != null)
+					return bci;
+			}
+
+			//
+			// Otherwise it is compiled in the same type
+			//
+			return null;
+		}
+		
 		public Expression GetThis (Location loc)
 		{
 			This my_this;
Index: convert.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/convert.cs,v
retrieving revision 1.21
diff -u -u -r1.21 convert.cs
--- convert.cs	16 Mar 2004 03:41:00 -0000	1.21
+++ convert.cs	15 Apr 2004 22:35:25 -0000
@@ -1026,18 +1026,21 @@
 			Type expr_type = expr.Type;
 			Expression e;
 
-			if (expr.eclass == ExprClass.MethodGroup){
-				if (!TypeManager.IsDelegateType (target_type)){
-					Report.Error (428, loc,
-						      String.Format (
-							   "Cannot convert method group to `{0}', since it is not a delegate",
-							   TypeManager.CSharpName (target_type)));
-					return null;
-				}
+			if (RootContext.V2){
+				if (expr.eclass == ExprClass.MethodGroup){
+					if (!TypeManager.IsDelegateType (target_type)){
+						Report.Error (428, loc,
+							String.Format (
+								"Cannot convert method group to `{0}', since it is not a delegate",
+								TypeManager.CSharpName (target_type)));
+						return null;
+					}
 
-				return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+					Console.WriteLine ("Triggering");
+					return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+				}
 			}
-			
+
 			if (expr_type == target_type && !(expr is NullLiteral))
 				return expr;
 
@@ -1053,7 +1056,7 @@
 			     target_type.IsSubclassOf (TypeManager.enum_type)) &&
 			    expr is IntLiteral){
 				IntLiteral i = (IntLiteral) expr;
-
+				
 				if (i.Value == 0)
 					return new EnumConstant ((Constant) expr, target_type);
 			}
@@ -1082,6 +1085,31 @@
 				}
 			}
 
+			if (expr_type == TypeManager.anonymous_method_type){
+				if (!TypeManager.IsDelegateType (target_type)){
+					Report.Error (428, loc,
+						      String.Format (
+							      "Cannot convert anonymous method to `{0}', since it is not a delegate",
+							      TypeManager.CSharpName (target_type)));
+					return null;
+				}
+
+				AnonymousMethod am = (AnonymousMethod) expr;
+				int errors = Report.Errors;
+
+				Expression conv = am.Compatible (ec, target_type);
+				if (conv != null)
+					return conv;
+				
+				//
+				// We return something instead of null, to avoid
+				// the duplicate error, since am.Compatible would have
+				// reported that already
+				//
+				if (errors != Report.Errors)
+					return new EmptyCast (expr, target_type);
+			}
+			
 			return null;
 		}
 
@@ -1142,9 +1170,10 @@
 
 		static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
 		{
-			string msg = "Cannot convert implicitly from `"+
-				TypeManager.CSharpName (source) + "' to `" +
-				TypeManager.CSharpName (target) + "'";
+			string msg = String.Format ("Cannot convert implicitly from {0} to `{1}'",
+						    source == TypeManager.anonymous_method_type ?
+						    "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
+						    TypeManager.CSharpName (target));
 
 			Report.Error (29, loc, msg);
 		}
Index: cs-parser.jay
===================================================================
RCS file: /cvs/public/mcs/mcs/cs-parser.jay,v
retrieving revision 1.289
diff -u -u -r1.289 cs-parser.jay
--- cs-parser.jay	30 Mar 2004 16:58:56 -0000	1.289
+++ cs-parser.jay	15 Apr 2004 22:35:25 -0000
@@ -40,14 +40,8 @@
 		///   Current block is used to add statements as we find
 		///   them.  
 		/// </summary>
-		Block      current_block;
+		Block      current_block, top_current_block;
 
-		/// <summary>
-                ///   If true, creates a toplevel block in the block production
-                ///   This is flagged by the delegate creation
-                /// </summary>
-                bool       create_toplevel_block;
-	
                 /// <summary>
 		/// <summary>
 		///   Current interface is used by the various declaration
@@ -872,7 +866,7 @@
 			}
 		}
 
-		method.Block = (Block) $3;
+		method.Block = (ToplevelBlock) $3;
 		CheckDef (current_container.AddMethod (method), method.Name, method.Location);
 
 		current_local_parameters = null;
@@ -1110,7 +1104,7 @@
 	  }
           accessor_body
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		current_local_parameters = null;
 		lexer.PropertyParsing = true;
 	  }
@@ -1147,7 +1141,7 @@
 	  }
 	  accessor_body
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		current_local_parameters = null;
 		lexer.PropertyParsing = true;
 	  }
@@ -1346,7 +1340,7 @@
 		OperatorDeclaration decl = (OperatorDeclaration) $3;
 		
 		Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
-					    decl.arg2type, decl.arg2name, (Block) $5, (Attributes) $1, decl.location);
+					    decl.arg2type, decl.arg2name, (ToplevelBlock) $5, (Attributes) $1, decl.location);
 
 		if (SimpleIteratorContainer.Simple.Yields)
 			op.SetYields ();
@@ -1475,7 +1469,7 @@
 	  constructor_body
 	  { 
 		Constructor c = (Constructor) $3;
-		c.Block = (Block) $4;
+		c.Block = (ToplevelBlock) $4;
 		c.OptAttributes = (Attributes) $1;
 		c.ModFlags = (int) $2;
 	
@@ -1590,7 +1584,7 @@
 				current_container, TypeManager.system_void_expr, m, "Finalize", 
 				new Parameters (null, null, l), (Attributes) $1, l);
 		  
-			d.Block = (Block) $7;
+			d.Block = (ToplevelBlock) $7;
 			CheckDef (current_container.AddMethod (d), d.Name, d.Location);
 		}
 	  }
@@ -1687,7 +1681,7 @@
 	  }
           block
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		lexer.EventParsing = true;
 	  }
 	| opt_attributes ADD error {
@@ -1711,7 +1705,7 @@
 	  }
           block
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		lexer.EventParsing = true;
 	  }
 	| opt_attributes REMOVE error {
@@ -2444,20 +2438,30 @@
 	: DELEGATE opt_anonymous_method_signature {
 		oob_stack.Push (current_local_parameters);
 		current_local_parameters = (Parameters)$2;
-		create_toplevel_block = true;
+
+		// Force the next block to be created as a ToplevelBlock
+		oob_stack.Push (current_block);
+		oob_stack.Push (top_current_block);
+		current_block = null;
 	  } block {
-		create_toplevel_block = false;
+		top_current_block = (Block) oob_stack.Pop ();
+		current_block = (Block) oob_stack.Pop ();
 		if (!RootContext.V2){
 			Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
 			$$ = null;
-		} else 
-			$$ = new AnonymousMethod ((Parameters) $2, (Block) $4, lexer.Location);
+		} else  {
+			ToplevelBlock anon_block = (ToplevelBlock) $4;
+
+			anon_block.Parent = current_block;
+			$$ = new AnonymousMethod ((Parameters) $2, (ToplevelBlock) top_current_block, 
+				anon_block, lexer.Location);
+		}
 		current_local_parameters = (Parameters) oob_stack.Pop ();
 	  }
 	;
 
 opt_anonymous_method_signature
-	: /* empty */			{ $$ = Parameters.EmptyReadOnlyParameters; }
+	: /* empty */			{ $$ = null; } 
 	| anonymous_method_signature
 	;
 
@@ -2476,7 +2480,7 @@
 	;
 
 opt_anonymous_method_parameter_list
-	: /* empty */	{ $$ = null; } 
+	: /* empty */	                   { $$ = null; } 
 	| anonymous_method_parameter_list  { $$ = $1; }
 	;
 
@@ -2497,7 +2501,11 @@
 
 anonymous_method_parameter
 	: opt_parameter_modifier type IDENTIFIER {
-		$$ = new Parameter ((Expression) $2, (string) $2, (Parameter.Modifier) $1, null);
+		$$ = new Parameter ((Expression) $2, (string) $3, (Parameter.Modifier) $1, null);
+	  }
+	| PARAMS type IDENTIFIER {
+		Report.Error (-221, lexer.Location, "params modifier not allowed in anonymous method declaration");
+		$$ = null;
 	  }
 	;
 
@@ -2919,8 +2927,9 @@
 block
 	: OPEN_BRACE 
 	  {
-		if (current_block == null || create_toplevel_block){
+		if (current_block == null){
 			current_block = new ToplevelBlock (current_local_parameters, lexer.Location);
+			top_current_block = current_block;
 		} else {
 			current_block = new Block (current_block, current_local_parameters,
 				lexer.Location, Location.Null);
@@ -2933,6 +2942,8 @@
 		$$ = current_block;
 		current_block.SetEndLocation (lexer.Location);
 		current_block = current_block.Parent;
+		if (current_block == null)
+			top_current_block = null;
 	  }
 	;
 
Index: delegate.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/delegate.cs,v
retrieving revision 1.97
diff -u -u -r1.97 delegate.cs
--- delegate.cs	1 Apr 2004 18:32:01 -0000	1.97
+++ delegate.cs	15 Apr 2004 22:35:25 -0000
@@ -379,6 +379,23 @@
 			return true;
 		}
 
+		//
+		// Returns the MethodBase for "Invoke" from a delegate type, this is used
+		// to extract the signature of a delegate.
+		//
+		public static MethodInfo GetInvokeMethod (EmitContext ec, Type delegate_type, Location loc)
+		{
+			Expression ml = Expression.MemberLookup (
+				ec, delegate_type, "Invoke", loc);
+
+			if (!(ml is MethodGroupExpr)) {
+				Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+				return null;
+			}
+
+			return (MethodInfo) (((MethodGroupExpr) ml).Methods [0]);
+		}
+		
 		/// <summary>
 		///  Verifies whether the method in question is compatible with the delegate
 		///  Returns the method itself if okay and null if not.
@@ -735,7 +752,7 @@
 				return null;
 		}
 	}
-	
+
 	//
 	// A delegate-creation-expression, invoked from the `New' class 
 	//
Index: ecore.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/ecore.cs,v
retrieving revision 1.266
diff -u -u -r1.266 ecore.cs
--- ecore.cs	14 Apr 2004 23:32:01 -0000	1.266
+++ ecore.cs	15 Apr 2004 22:35:25 -0000
@@ -2676,7 +2676,7 @@
 				ig.Emit (OpCodes.Ldsfld, FieldInfo);
 				return;
 			}
-			
+
 			if (instance_expr.Type.IsValueType){
 				IMemoryLocation ml;
 				LocalTemporary tempo = null;
@@ -2684,7 +2684,7 @@
 				if (!(instance_expr is IMemoryLocation)){
 					tempo = new LocalTemporary (ec, instance_expr.Type);
 					
-					InstanceExpression.Emit (ec);
+					instance_expr.Emit (ec);
 					tempo.Store (ec);
 					ml = tempo;
 				} else
Index: expression.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/expression.cs,v
retrieving revision 1.543
diff -u -u -r1.543 expression.cs
--- expression.cs	15 Apr 2004 03:13:00 -0000	1.543
+++ expression.cs	15 Apr 2004 22:35:25 -0000
@@ -991,7 +991,9 @@
 				// For now: only localvariables when not remapped
 				//
 
-				if (method == null &&
+				if (false &&
+
+				    method == null &&
 				    ((expr is LocalVariableReference) ||(expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic))){
 					if (empty_expr == null)
 						empty_expr = new EmptyExpression ();
@@ -3361,16 +3363,12 @@
 			Label false_target = ig.DefineLabel ();
 			Label end_target = ig.DefineLabel ();
 
-			ig.Emit (OpCodes.Nop);
-
 			(is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
 			left.Emit (ec);
 			ig.Emit (OpCodes.Br, end_target);
 			ig.MarkLabel (false_target);
 			op.Emit (ec);
 			ig.MarkLabel (end_target);
-
-			ig.Emit (OpCodes.Nop);
 		}
 	}
 
@@ -3594,8 +3592,10 @@
 			eclass = ExprClass.Variable;
 		}
 
+		//
 		// Setting `is_readonly' to false will allow you to create a writable
 		// reference to a read-only variable.  This is used by foreach and using.
+		//
 		public LocalVariableReference (Block block, string name, Location l,
 					       LocalInfo local_info, bool is_readonly)
 			: this (block, name, l)
@@ -3605,7 +3605,9 @@
 		}
 
 		public VariableInfo VariableInfo {
-			get { return local_info.VariableInfo; }
+			get {
+				return local_info.VariableInfo;
+			}
 		}
 
 		public bool IsReadOnly {
@@ -3614,7 +3616,7 @@
 			}
 		}
 
-		protected void DoResolveBase (EmitContext ec)
+		protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side)
 		{
 			if (local_info == null) {
 				local_info = Block.GetLocalInfo (Name);
@@ -3622,14 +3624,18 @@
 			}
 
 			type = local_info.VariableType;
-#if false
-			if (ec.InAnonymousMethod)
-				Block.LiftVariable (local_info);
-#endif
-		}
 
-		protected Expression DoResolve (EmitContext ec, bool is_lvalue)
-		{
+			VariableInfo variable_info = local_info.VariableInfo;
+			if (lvalue_right_side != null){
+				if (is_readonly){
+					Error (1604, "cannot assign to `" + Name + "' because it is readonly");
+					return null;
+				}
+				
+				if (variable_info != null)
+					variable_info.SetAssigned (ec);
+			}
+			
 			Expression e = Block.GetConstantExpression (Name);
 			if (e != null) {
 				local_info.Used = true;
@@ -3637,48 +3643,40 @@
 				return e;
 			}
 
-			VariableInfo variable_info = local_info.VariableInfo; 
 			if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
 				return null;
 
-			if (!is_lvalue)
+			if (lvalue_right_side == null)
 				local_info.Used = true;
 
-			if (local_info.LocalBuilder == null)
-				return ec.RemapLocal (local_info);
+			if (ec.CurrentAnonymousMethod != null){
+				//
+				// If we are referencing a variable from the external block
+				// flag it for capturing
+				//
+				if (local_info.Block.Toplevel != ec.CurrentBlock.Toplevel)
+					ec.CaptureVariable (local_info);
+			}
+			
+			if (ec.RemapToProxy){
+				Expression new_local = ec.RemapLocal (local_info);
+				if (lvalue_right_side == null)
+					return new_local.DoResolve (ec);
+				else
+					return new_local.DoResolveLValue (ec, lvalue_right_side);
+			}
 			
 			return this;
 		}
 		
 		public override Expression DoResolve (EmitContext ec)
 		{
-			DoResolveBase (ec);
-
-			return DoResolve (ec, false);
+			return DoResolveBase (ec, null);
 		}
 
 		override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
 		{
-			DoResolveBase (ec);
-
-			VariableInfo variable_info = local_info.VariableInfo; 
-			if (variable_info != null)
-				variable_info.SetAssigned (ec);
-
-			Expression e = DoResolve (ec, true);
-
-			if (e == null)
-				return null;
-
-			if (is_readonly){
-				Error (1604, "cannot assign to `" + Name + "' because it is readonly");
-				return null;
-			}
-
-			if (local_info.LocalBuilder == null)
-				return ec.RemapLocalLValue (local_info, right_side);
-			
-			return this;
+			return DoResolveBase (ec, right_side);
 		}
 
 		public bool VerifyFixed (bool is_expression)
@@ -3690,15 +3688,26 @@
 		{
 			ILGenerator ig = ec.ig;
 
-			ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+			if (local_info.FieldBuilder == null){
+				ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+			} else {
+				ec.EmitCapturedContext (local_info);
+				ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
+			}
 		}
 		
 		public void EmitAssign (EmitContext ec, Expression source)
 		{
 			ILGenerator ig = ec.ig;
 
-			source.Emit (ec);
-			ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+			if (local_info.FieldBuilder == null){
+				source.Emit (ec);
+				ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+			} else {
+				ec.EmitCapturedContext (local_info);
+				source.Emit (ec);
+				ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
+			}
 		}
 		
 		public void AddressOf (EmitContext ec, AddressOp mode)
@@ -3725,7 +3734,25 @@
 		Block block;
 		VariableInfo vi;
 		public Parameter.Modifier mod;
-		public bool is_ref, is_out;
+
+		[Flags]
+		enum Flags : byte {
+			IsRef = 1,
+			IsOut = 2,
+		}
+		Flags flags;
+
+		public bool IsOut {
+			get {
+				return (flags & Flags.IsOut) != 0;
+			}
+		}
+
+		public bool IsRef {
+			get {
+				return (flags & Flags.IsRef) != 0;
+			}
+		}
 		
 		public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc)
 		{
@@ -3748,8 +3775,7 @@
 
 		public bool IsAssigned (EmitContext ec, Location loc)
 		{
-			if (!ec.DoFlowAnalysis || !is_out ||
-			    ec.CurrentBranching.IsAssigned (vi))
+			if (!ec.DoFlowAnalysis || !IsOut || ec.CurrentBranching.IsAssigned (vi))
 				return true;
 
 			Report.Error (165, loc,
@@ -3759,8 +3785,7 @@
 
 		public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
 		{
-			if (!ec.DoFlowAnalysis || !is_out ||
-			    ec.CurrentBranching.IsFieldAssigned (vi, field_name))
+			if (!ec.DoFlowAnalysis || !IsOut || ec.CurrentBranching.IsFieldAssigned (vi, field_name))
 				return true;
 
 			Report.Error (170, loc,
@@ -3770,18 +3795,19 @@
 
 		public void SetAssigned (EmitContext ec)
 		{
-			if (is_out && ec.DoFlowAnalysis)
+			if (IsOut && ec.DoFlowAnalysis)
 				ec.CurrentBranching.SetAssigned (vi);
 		}
 
-		public void SetFieldAssigned (EmitContext ec, string field_name)
+		public void SetFieldAssigned (EmitContext ec, string field_name)	
 		{
-			if (is_out && ec.DoFlowAnalysis)
+			if (IsOut && ec.DoFlowAnalysis)
 				ec.CurrentBranching.SetFieldAssigned (vi, field_name);
 		}
 
 		protected void DoResolveBase (EmitContext ec)
 		{
+			bool is_ref, is_out, is_captured;
 			type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
 			is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
 			is_out = (mod & Parameter.Modifier.OUT) != 0;
@@ -3789,6 +3815,27 @@
 
 			if (is_out)
 				vi = block.ParameterMap [idx];
+
+			Console.WriteLine ("I got: {0}", mod);
+			
+			if (ec.CurrentAnonymousMethod != null){
+				Console.WriteLine ("here");
+				if (is_ref){
+					Report.Error (1628, Location,
+						      "Can not reference a ref or out parameter in an anonymous method");
+					return;
+				}
+				
+				//
+				// If we are referencing the parameter from the external block
+				// flag it for capturing
+				//
+				ec.CaptureParameter (name, type, idx);
+
+			       
+			}
+
+			flags = (is_ref ? Flags.IsRef : 0) | (is_out ? Flags.IsOut : 0);
 		}
 
 		//
@@ -3799,7 +3846,7 @@
 		//   externally we expose "int&"
 		//   here we expose       "int".
 		//
-		// We record this in "is_ref".  This means that the type system can treat
+		// We record this in "IsRef".  This means that the type system can treat
 		// the type as it is expected, but when we generate the code, we generate
 		// the alternate kind of code.
 		//
@@ -3807,7 +3854,7 @@
 		{
 			DoResolveBase (ec);
 
-			if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
+			if (IsOut && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
 				return null;
 
 			if (ec.RemapToProxy)
@@ -3857,12 +3904,20 @@
 				arg_idx++;
 
 			EmitLdArg (ig, arg_idx);
+
+			//
+			// FIXME: Review for anonymous methods
+			//
 		}
 		
 		public override void Emit (EmitContext ec)
 		{
-			ILGenerator ig = ec.ig;
+			if (ec.HaveCaptureInfo () && ec.IsParameterCaptured (name)){
+				ec.EmitParameter (name);
+				return;
+			}
 			
+			ILGenerator ig = ec.ig;
 			int arg_idx = idx;
 
 			if (!ec.IsStatic)
@@ -3870,7 +3925,7 @@
 
 			EmitLdArg (ig, arg_idx);
 
-			if (!is_ref)
+			if (!IsRef)
 				return;
 
 			//
@@ -3882,6 +3937,11 @@
 
 		public void EmitAssign (EmitContext ec, Expression source)
 		{
+			if (ec.HaveCaptureInfo () && ec.IsParameterCaptured (name)){
+				ec.EmitAssignParameter (name, source);
+				return;
+			}
+
 			ILGenerator ig = ec.ig;
 			
 			int arg_idx = idx;
@@ -3889,12 +3949,12 @@
 			if (!ec.IsStatic)
 				arg_idx++;
 
-			if (is_ref)
+			if (IsRef)
 				EmitLdArg (ig, arg_idx);
 			
 			source.Emit (ec);
 
-			if (is_ref)
+			if (IsRef)
 				StoreFromPtr (ig, type);
 			else {
 				if (arg_idx <= 255)
@@ -3906,12 +3966,17 @@
 
 		public void AddressOf (EmitContext ec, AddressOp mode)
 		{
+			if (ec.HaveCaptureInfo () && ec.IsParameterCaptured (name)){
+				ec.EmitAddressOfParameter (name);
+				return;
+			}
+			
 			int arg_idx = idx;
 
 			if (!ec.IsStatic)
 				arg_idx++;
 
-			if (is_ref){
+			if (IsRef){
 				if (arg_idx <= 255)
 					ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
 				else
@@ -4061,7 +4126,7 @@
 				if (Expr is ParameterReference){
 					ParameterReference pr = (ParameterReference) Expr;
 
-					if (pr.is_ref)
+					if (pr.IsRef)
 						pr.EmitLoad (ec);
 					else {
 						
Index: iterators.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/iterators.cs,v
retrieving revision 1.18
diff -u -u -r1.18 iterators.cs
--- iterators.cs	15 Apr 2004 03:13:00 -0000	1.18
+++ iterators.cs	15 Apr 2004 22:35:25 -0000
@@ -48,7 +48,7 @@
 				Report.Error (-209, loc, "yield statement can not appear in the catch clause");
 				return false;
 			}
-			if (ec.InAnonymousMethod){
+			if (ec.CurrentAnonymousMethod != null){
 				Report.Error (-209, loc, "yield statement can not appear inside an anonymoud method");
 				return false;
 			}
@@ -172,7 +172,7 @@
 		Type return_type;
 		Type [] param_types;
 		InternalParameters parameters;
-		Block original_block;
+		ToplevelBlock original_block;
 		Location loc;
 		int modifiers;
 
@@ -644,7 +644,7 @@
 		//
 		// Returns the new block for the method, or null on failure
 		//
-		public Block Setup (Block block)
+		public ToplevelBlock Setup (ToplevelBlock block)
 		{
 			if (!(IsIEnumerator (return_type) || IsIEnumerable (return_type))){
 				Report.Error (
@@ -665,7 +665,7 @@
 			}
 
 			original_block = block;
-			Block b = new Block (null);
+			ToplevelBlock b = new ToplevelBlock (loc);
 
 			// return new InnerClass ()
 			b.AddStatement (new NoCheckReturn (new NewInnerType (this, loc), loc));
Index: parameter.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/parameter.cs,v
retrieving revision 1.49
diff -u -u -r1.49 parameter.cs
--- parameter.cs	7 Apr 2004 05:36:16 -0000	1.49
+++ parameter.cs	15 Apr 2004 22:35:25 -0000
@@ -141,6 +141,7 @@
 		Location loc;
 		
 		static Parameters empty_parameters;
+		static Hashtable captured_parameters;
 		
 		public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
 		{
Index: report.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/report.cs,v
retrieving revision 1.41
diff -u -u -r1.41 report.cs
--- report.cs	1 Apr 2004 18:32:01 -0000	1.41
+++ report.cs	15 Apr 2004 22:35:25 -0000
@@ -168,9 +168,6 @@
 			Errors++;
 			Console.WriteLine (msg);
 
-			if (Stacktrace)
-				Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
-			
 			if (Fatal)
 				throw new Exception (msg);
 		}
Index: statement.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/statement.cs,v
retrieving revision 1.242
diff -u -u -r1.242 statement.cs
--- statement.cs	24 Mar 2004 03:35:19 -0000	1.242
+++ statement.cs	15 Apr 2004 22:35:25 -0000
@@ -6,6 +6,7 @@
 //   Martin Baulig (martin@gnome.org)
 //
 // (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 
 using System;
@@ -550,6 +551,11 @@
 		{
 			if (ec.ReturnType == null){
 				if (Expr != null){
+					if (ec.CurrentAnonymousMethod != null){
+						Report.Error (1662, loc, String.Format (
+							"Anonymous method could not be converted to delegate " +
+							"since the return value does not match the delegate value"));
+					}
 					Error (127, "Return with a value not allowed here");
 					return false;
 				}
@@ -944,13 +950,17 @@
 		}
 	}
 
+	//
+	// The information about a user-perceived local variable
+	//
 	public class LocalInfo {
 		public Expression Type;
 
 		//
 		// Most of the time a variable will be stored in a LocalBuilder
 		//
-		// But sometimes, it will be stored in a field.  The context of the field will
+		// But sometimes, it will be stored in a field (variables that have been
+		// hoisted by iterators or by anonymous methods).  The context of the field will
 		// be stored in the EmitContext
 		//
 		//
@@ -967,7 +977,8 @@
 		enum Flags : byte {
 			Used = 1,
 			ReadOnly = 2,
-			Fixed = 4
+			Fixed = 4,
+			Captured = 8
 		}
 
 		Flags flags;
@@ -1032,6 +1043,16 @@
 			}
 		}
 
+		public bool IsCaptured {
+			get {
+				return (flags & Flags.Captured) != 0;
+			}
+
+			set {
+				flags |= Flags.Captured;
+			}
+		}
+
 		public override string ToString ()
 		{
 			return String.Format ("LocalInfo ({0},{1},{2},{3})",
@@ -1075,9 +1096,9 @@
 	///   they contain extra information that is not necessary on normal blocks.
 	/// </remarks>
 	public class Block : Statement {
-		public readonly Block     Parent;
+		public Block    Parent;
 		public readonly Location  StartLocation;
-		public Location           EndLocation = Location.Null;
+		public Location EndLocation = Location.Null;
 
 		[Flags]
 		public enum Flags : byte {
@@ -1086,7 +1107,8 @@
 			BlockUsed = 4,
 			VariablesInitialized = 8,
 			HasRet = 16,
-			IsDestructor = 32	
+			IsDestructor = 32,
+			IsToplevel = 64
 		}
 		Flags flags;
 
@@ -1543,7 +1565,7 @@
 		public VariableMap ParameterMap {
 			get {
 				if ((flags & Flags.VariablesInitialized) == 0)
-					throw new Exception ();
+					throw new Exception ("Variables have not been initialized yet");
 
 				return param_map;
 			}
@@ -1552,17 +1574,12 @@
 		public VariableMap LocalMap {
 			get {
 				if ((flags & Flags.VariablesInitialized) == 0)
-					throw new Exception ();
+					throw new Exception ("Variables have not been initialized yet");
 
 				return local_map;
 			}
 		}
 
-		public bool LiftVariable (LocalInfo local_info)
-		{
-			return false;
-		}
-		
 		/// <summary>
 		///   Emits the variable declarations and labels.
 		/// </summary>
@@ -1570,7 +1587,7 @@
 		///   tc: is our typecontainer (to resolve type references)
 		///   ig: is the code generator:
 		/// </remarks>
-		public void EmitMeta (EmitContext ec, InternalParameters ip)
+		public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)
 		{
 			ILGenerator ig = ec.ig;
 
@@ -1601,8 +1618,7 @@
 
 			bool old_check_state = ec.ConstantCheckState;
 			ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
-			bool remap_locals = ec.RemapToProxy;
-				
+			
 			//
 			// Process this block variables
 			//
@@ -1627,11 +1643,6 @@
 							continue;
 					}
 
-					if (remap_locals)
-						vi.FieldBuilder = ec.MapVariable (name, vi.VariableType);
-					else
-						vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
-
 					if (constants == null)
 						continue;
 
@@ -1669,7 +1680,33 @@
 			//
 			if (children != null){
 				foreach (Block b in children)
-					b.EmitMeta (ec, ip);
+					b.ResolveMeta (toplevel, ec, ip);
+			}
+		}
+
+		//
+		// Emits the local variable declarations for a block
+		//
+		public void EmitMeta (EmitContext ec)
+		{
+			ILGenerator ig = ec.ig;
+			
+			if (variables != null){
+				bool have_captured_vars = ec.HaveCapturedVariables ();
+				
+				foreach (DictionaryEntry de in variables){
+					LocalInfo vi = (LocalInfo) de.Value;
+					
+					if (have_captured_vars && ec.IsCaptured (vi))
+						continue;
+
+					vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+				}
+			}
+
+			if (children != null){
+				foreach (Block b in children)
+					b.EmitMeta (ec);
 			}
 		}
 
@@ -1832,20 +1869,101 @@
 
 			ec.CurrentBlock = prev_block;
 		}
+
+		//
+		// Invoked during parsing to register all anonymous methods,
+		// it registers the method with the topmost block.
+		//
+		public void RegisterAnonymousMethod (AnonymousMethod m)
+		{
+			Block b = this;
+			while (b.Parent != null)
+				b = b.Parent;
+			ToplevelBlock tl = (ToplevelBlock) b;
+			
+			tl.DoRegisterAnonymousMethod (m);
+		}
+
+		public ToplevelBlock Toplevel {
+			get {
+				Block b = this;
+				while (b.Parent != null){
+					if ((b.flags & Flags.IsToplevel) != 0)
+						break;
+					b = b.Parent;
+				}
+
+				return (ToplevelBlock) b;
+			}
+		}
+
+		//
+		// Returns true if we ar ea child of `b'.
+		//
+		public bool IsChildOf (Block b)
+		{
+			Block current = this;
+			
+			do {
+				if (current.Parent == b)
+					return true;
+				current = current.Parent;
+			} while (current != null);
+			return false;
+		}
 	}
 
 	//
+	// A toplevel block contains extra information, the split is done
+	// only to separate information that would otherwise bloat the more
+	// lightweight Block.
+	//
+	// In particular, this was introduced when the support for Anonymous
+	// Methods was implemented. 
 	// 
 	public class ToplevelBlock : Block {
+		public ArrayList AnonymousMethods;
+		CaptureInfo capture_info;
+
+		//
+		// Parent is only used by anonymous blocks to link back to their
+		// parents
+		//
 		public ToplevelBlock (Parameters parameters, Location start) :
-			base (null, parameters, start, Location.Null)
+			base (null, Flags.IsToplevel, parameters, start, Location.Null)
 		{
 		}
 
 		public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
-			base (null, flags, parameters, start, Location.Null)
+			base (null, Flags.IsToplevel, parameters, start, Location.Null)
+		{
+		}
+
+		public ToplevelBlock (Location loc) : base (null, Flags.IsToplevel, loc, loc)
+		{
+		}
+
+		public bool HaveAnonymousMethods {
+			get {
+				return AnonymousMethods != null;
+			}
+		}
+		
+		//
+		// Invoked by Block.RegisterAnonymousMethod
+		//
+		public void DoRegisterAnonymousMethod (AnonymousMethod m)
 		{
+			if (AnonymousMethods == null)
+				AnonymousMethods = new ArrayList ();
+			AnonymousMethods.Add (m);
 		}
+
+		public FieldBuilder GetCapturedField (LocalInfo local_info)
+		{
+			return null;
+		}
+		
 	}
 	
 	public class SwitchLabel {
Index: typemanager.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/typemanager.cs,v
retrieving revision 1.278
diff -u -u -r1.278 typemanager.cs
--- typemanager.cs	11 Apr 2004 05:02:19 -0000	1.278
+++ typemanager.cs	15 Apr 2004 22:35:25 -0000
@@ -84,6 +84,7 @@
 	static public object obsolete_attribute_type;
 	static public object conditional_attribute_type;
 	static public Type in_attribute_type;
+	static public Type anonymous_method_type;
 	static public Type cls_compliant_attribute_type;
 	static public Type typed_reference_type;
 	static public Type arg_iterator_type;
@@ -1155,6 +1156,11 @@
 		system_asynccallback_expr.Type = asynccallback_type;
 		system_iasyncresult_expr.Type = iasyncresult_type;
 		system_valuetype_expr.Type = value_type;
+
+		//
+		// These are only used for compare purposes
+		//
+		anonymous_method_type = typeof (AnonymousMethod);
 	}
 
 	//

