edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C615513
File: RubyTests.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C615513  (server)    10/28/2008 4:32 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;LexicalScopes2
@@ -402,6 +402,7 @@
                 // eval, binding:
                 Eval1,
                 Eval2,
+                Eval3,
                 EvalReturn1,
                 EvalReturn2,
                 LocalNames1,
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/EvalTests.cs;C597872
File: EvalTests.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/EvalTests.cs;C597872  (server)    10/28/2008 3:59 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/EvalTests.cs;LexicalScopes2
@@ -13,6 +13,7 @@
  *
  * ***************************************************************************/
 
+using System;
 namespace IronRuby.Tests {
     public partial class Tests {
         public void Eval1() {
@@ -50,6 +51,50 @@
 undefined");
         }
 
+        public void Eval3() {
+            string body = @"
+1.times {
+  a = 1
+  
+  eval <<-END
+    b = a + 1
+    eval <<-END2
+      c = b + 1
+    END2
+  END
+  
+  puts b rescue p $!
+  
+  eval <<-END
+    puts b, c
+  END
+}
+
+puts a rescue p $!
+puts b rescue p $!
+  
+eval <<-END
+  puts a rescue p $!
+  puts b rescue p $!
+END
+";
+            string output = @"
+#<NoMethodError: * `b' *>
+2
+3
+#<NoMethodError: * `a' *>
+#<NoMethodError: * `b' *>
+#<NoMethodError: * `a' *>
+#<NoMethodError: * `b' *>
+";
+
+            AssertOutput(() => CompilerTest(String.Format(@"def foo; {0}; end; foo", body)), output, OutputFlags.Match);
+            AssertOutput(() => CompilerTest(String.Format(@"module M; {0}; end", body)), output, OutputFlags.Match);
+            AssertOutput(() => CompilerTest(String.Format(@"class C; {0}; end", body)), output, OutputFlags.Match);
+            AssertOutput(() => CompilerTest(String.Format(@"class << Object.new; {0}; end", body)), output, OutputFlags.Match);
+            AssertOutput(() => CompilerTest(body), output, OutputFlags.Match);
+        }
+
         public void EvalReturn1() {
             AssertOutput(delegate() {
                 CompilerTest(@"
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs;C618547
File: BlockDefinition.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs;C618547  (server)    10/28/2008 8:12 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/BlockDefinition.cs;LexicalScopes2
@@ -118,7 +118,7 @@
             );
 
             if (_definedScope != null) {
-                _definedScope.TransformLocals(scope, gen);
+                _definedScope.TransformLocals(scope);
             }
 
             int firstStatementLine = _body.Count > 0 ? _body[0].Location.Start.Line : Location.End.Line;
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/ScopeBuilder.cs;C618762
File: ScopeBuilder.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/ScopeBuilder.cs;C618762  (server)    10/28/2008 6:20 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/ScopeBuilder.cs;LexicalScopes2
@@ -27,7 +27,10 @@
     internal sealed class ScopeBuilder {
         private static readonly List<MSA.ParameterExpression> _FinishedVariables = new List<MSA.ParameterExpression>(0);
 
+        // local variables and parameters exposed at runtime via dictionary:
         private List<MSA.ParameterExpression> _visibleLocals;
+
+        // all local variables except for parameters that are used in the scope:
         private List<MSA.ParameterExpression> _allLocals;
         
 #if DEBUG
@@ -55,8 +58,9 @@
             return AddHidden(Ast.Variable(type, name));
         }
 
-        public MSA.ParameterExpression/*!*/ DefineVariable(string/*!*/ name, Type/*!*/ type) {
-            return AddVisible(Ast.Variable(type, name));
+        // Defines visible user variable (of object type).
+        public MSA.ParameterExpression/*!*/ DefineVariable(string/*!*/ name) {
+            return AddVisible(Ast.Variable(typeof(object), name));
         }
         
         public MSA.ParameterExpression/*!*/ AddVisible(MSA.ParameterExpression/*!*/ variable) {
@@ -64,12 +68,13 @@
             Debug.Assert(!AllFinished);
 
             if (_visibleLocals == null) {
-                _visibleLocals = new List<MSA.ParameterExpression>();
-                if (_allLocals == null) {
-                    _allLocals = new List<MSA.ParameterExpression>();
-                }
+                _visibleLocals = new List<MSA.ParameterExpression>();                
             }
 
+            if (_allLocals == null) {
+                _allLocals = new List<MSA.ParameterExpression>();
+            }
+
             _visibleLocals.Add(variable);
             _allLocals.Add(variable);
             return variable;
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C610287
File: SourceUnitTree.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;C610287  (server)    10/28/2008 7:07 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/SourceUnitTree.cs;LexicalScopes2
@@ -119,7 +119,7 @@
                 null                                    // parameters
             );
 
-            _definedScope.TransformLocals(scope, gen);
+            _definedScope.TransformLocals(scope);
 
             MSA.Expression scopeFactoryCall;
 
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs;C618547
File: MethodDeclaration.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs;C618547  (server)    10/28/2008 6:08 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/MethodDeclaration.cs;LexicalScopes2
@@ -70,8 +70,7 @@
 
             if (_parameters.Block != null) {
                 // map user defined proc parameter to the special param #1:
-                parameters[1] = Ast.Parameter(typeof(Proc), _parameters.Block.Name);
-                DefinedScope.SetTransformedParameter(_parameters.Block.Name, parameters[1]);
+                parameters[1] = _parameters.Block.TransformBlockParameterDefinition();
             } else {
                 parameters[1] = Ast.Parameter(typeof(Proc), "#block");
             }
@@ -103,7 +102,7 @@
                 _parameters
             );
 
-            DefinedScope.TransformLocals(scope, gen);
+            DefinedScope.TransformLocals(scope);
 
             MSA.ParameterExpression unwinder = scope.DefineHiddenVariable("#unwinder", typeof(MethodUnwinder));
 
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/ModuleDeclaration.cs;C618547
File: ModuleDeclaration.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/ModuleDeclaration.cs;C618547  (server)    10/28/2008 8:12 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/Declarations/ModuleDeclaration.cs;LexicalScopes2
@@ -89,7 +89,7 @@
             );
 
             // first, transform locals defined within the module body:
-            DefinedScope.TransformLocals(scope, gen);
+            DefinedScope.TransformLocals(scope);
 
             // second, transform body:
             MSA.Expression transformedBody = Body.TransformRead(gen);
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/LeftValues/LocalVariable.cs;C601093
File: LocalVariable.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/LeftValues/LocalVariable.cs;C601093  (server)    10/28/2008 3:15 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Ast/LeftValues/LocalVariable.cs;LexicalScopes2
@@ -18,25 +18,38 @@
 using Microsoft.Scripting;
 using MSA = System.Linq.Expressions;
 using AstUtils = Microsoft.Scripting.Ast.Utils;
+using IronRuby.Builtins;
 
 namespace IronRuby.Compiler.Ast {
     using Ast = System.Linq.Expressions.Expression;
 
     public partial class LocalVariable : Variable {
-        private readonly LexicalScope/*!*/ _containingScope;
+        private MSA.ParameterExpression _transformed;
 
-        public LocalVariable(LexicalScope/*!*/ containingScope, string/*!*/ name, SourceSpan location)
+        public LocalVariable(string/*!*/ name, SourceSpan location)
             : base(name, location) {
-            Debug.Assert(containingScope != null);
+        }
 
-            _containingScope = containingScope;
+        internal void TransformDefinition(ScopeBuilder/*!*/ locals) {
+            if (_transformed == null) {
+                _transformed = locals.DefineVariable(Name);
+            }
         }
 
+        internal MSA.ParameterExpression/*!*/ TransformParameterDefinition() {
+            Debug.Assert(_transformed == null);
+            return _transformed = Ast.Parameter(typeof(object), Name);
+        }
+
+        internal MSA.ParameterExpression/*!*/ TransformBlockParameterDefinition() {
+            Debug.Assert(_transformed == null);
+            return _transformed = Ast.Parameter(typeof(Proc), Name);
+        }
+
         internal override MSA.Expression/*!*/ TransformReadVariable(AstGenerator/*!*/ gen, bool tryRead) {
-            VariableInfo var = _containingScope.ResolveVariable(Name);
-            if (var.TransformedVariable != null) {
+            if (_transformed != null) {
                 // static lookup:
-                return var.TransformedVariable;
+                return _transformed;
             } else {
                 // dynamic lookup:
                 return Methods.GetLocalVariable.OpCall(gen.CurrentScopeVariable, AstUtils.Constant(Name));
@@ -44,10 +57,9 @@
         }
 
         internal override MSA.Expression/*!*/ TransformWriteVariable(AstGenerator/*!*/ gen, MSA.Expression/*!*/ rightValue) {
-            VariableInfo var = _containingScope.ResolveVariable(Name);
-            if (var.TransformedVariable != null) {
+            if (_transformed != null) {
                 // static lookup:
-                return Ast.Assign(var.TransformedVariable, Ast.ConvertHelper(rightValue, var.TransformedVariable.Type));
+                return Ast.Assign(_transformed, Ast.ConvertHelper(rightValue, _transformed.Type));
             } else {
                 // dynamic lookup:
                 return Methods.SetLocalVariable.OpCall(AstFactory.Box(rightValue), gen.CurrentScopeVariable, AstUtils.Constant(Name));
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/LexicalScope.cs;C587646
File: LexicalScope.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/LexicalScope.cs;C587646  (server)    10/28/2008 11:30 AM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/LexicalScope.cs;LexicalScopes2
@@ -22,132 +22,85 @@
 using Microsoft.Scripting.Utils;
 using IronRuby.Compiler.Ast;
 using MSA = System.Linq.Expressions;
+using IronRuby.Runtime;
 
 namespace IronRuby.Compiler {
-    public enum ScopeKind {
-        TopLevel,
-        Method,
-        Module,
-        Block,
-        Initializer,
-        RuntimeScope
-    }
 
-    public enum VariableKind {
-        Local,
-        Parameter,
-        Runtime,
-    }
+    // Scope contains variables defined outside of the current compilation unit. Used for assertion checks only.
+    // (e.g. created for variables in the runtime scope of eval).
+    internal sealed class RuntimeLexicalScope : LexicalScope {
+        public RuntimeLexicalScope(List<string>/*!*/ names) 
+            : base(null) {
 
-    public sealed class VariableInfo {
-        private MSA.Expression _transformedVariable;
-        private VariableKind _kind;
-
-        public VariableKind Kind {
-            get { return _kind; }
-            set { _kind = value; }
+            for (int i = 0; i < names.Count; i++) {
+                AddVariable(names[i], SourceSpan.None);
+            }
         }
-        
-        public MSA.Expression TransformedVariable {
-            get { return _transformedVariable; }
-            set { _transformedVariable = value; }
-        }
 
-        public VariableInfo(VariableKind kind) {
-            _kind = kind;
+        protected override bool IsRuntimeScope {
+            get { return true; }
         }
     }
 
-    [Serializable]
-    public sealed class LexicalScope {
-        private readonly Dictionary<string/*!*/, VariableInfo>/*!*/ _locals;
-        private readonly LexicalScope _parentScope;
-        private readonly ScopeKind _kind;
+    public class LexicalScope : HybridStringDictionary<LocalVariable> {
+        private readonly LexicalScope _outerScope;
 
-        public ScopeKind Kind { get { return _kind; } }
-        public LexicalScope ParentScope { get { return _parentScope; } }
-        public Dictionary<string/*!*/, VariableInfo>/*!*/ LocalVariables { get { return _locals; } }
-
-        public LexicalScope(LexicalScope parentScope, ScopeKind kind)
-            : this(parentScope, kind, new Dictionary<string, VariableInfo>()) {
+        internal LexicalScope(LexicalScope outerScope) {
+            _outerScope = outerScope;
         }
 
-        public LexicalScope(LexicalScope parentScope, ScopeKind kind, Dictionary<string/*!*/, VariableInfo>/*!*/ locals) {
-            Debug.Assert(locals != null);
-
-            _parentScope = parentScope;
-            _kind = kind;
-            _locals = locals;
+        public LexicalScope OuterScope {
+            get { return _outerScope; }
         }
 
-        // returns true if id already exists here or in an outer scope
-        public bool HasLocal(string name) {
-            if (DefinedStatically(name)) // || DefinedDynamically(id))
-                return true;
-            else if (_kind == ScopeKind.Block)
-                return _parentScope.HasLocal(name);
-            else
-                return false;
+        protected virtual bool IsRuntimeScope {
+            get { return false; }
         }
 
-        public LocalVariable AddParameter(string/*!*/ name, SourceSpan location) {
-            Debug.Assert(!HasLocal(name));
-            return CreateLocalHere(name, VariableKind.Parameter, location);
+        public LocalVariable/*!*/ AddVariable(string/*!*/ name, SourceSpan location) {
+            var var = new LocalVariable(name, location);
+            Add(name, var);
+            return var;
         }
 
-        public Variable AddLocal(string/*!*/ name, SourceSpan location) {
-            if (DefinedStatically(name))
-                return new LocalVariable(this, name, location);
-            //else if (DefinedDynamically(id))
-            //    return new DynamicLocalVar(id, this, location);
-            else if (HasLocal(name))
-                return GetOuterLocal(name, this, 0, location);
-            else
-                return CreateLocalHere(name, VariableKind.Local, location);
-        }
+        public LocalVariable/*!*/ ResolveOrAddVariable(string/*!*/ name, SourceSpan location) {
+            var result = ResolveVariable(name);
+            
+            if (result != null) {
+                return result;
+            }
 
-        private LocalVariable CreateLocalHere(string/*!*/ name, VariableKind kind, SourceSpan location) {
-            _locals.Add(name, new VariableInfo(kind));
-            return new LocalVariable(this, name, location);
+            return AddVariable(name, location);
         }
 
-        private Variable GetOuterLocal(string/*!*/ name, LexicalScope blockScope, int depth, SourceSpan location) {
-            if (DefinedStatically(name))
-                return new LocalVariable(blockScope, name, /*depth, */location);
-            //else if (DefinedDynamically(id))
-            //    return new DynamicLocalVar(id, blockScope, /*depth, */location);
-            else {
-                Debug.Assert(_kind == ScopeKind.Block);
-                return _parentScope.GetOuterLocal(name, blockScope, depth + 1, location);
-            }
+        public LocalVariable ResolveVariable(string/*!*/ name) {
+            LexicalScope scope = this;
+            do {
+                LocalVariable result;
+                if (scope.TryGetValue(name, out result)) {
+                    return result;
+                }
+                scope = scope.OuterScope;
+            } while (scope != null);
+            return null;
         }
 
-        private bool DefinedStatically(string/*!*/ id) {
-            return _locals.ContainsKey(id);
-        }
+        #region Transformation
 
-        //public Variable add_locally(string id, SourceSpan location) {
-        //    if (defined_statically(id))
-        //        return new StaticLocalVar(this, id, location);
-        //    else
-        //        return create_local_here(id, location);
-        //}
+        internal void TransformLocals(ScopeBuilder/*!*/ locals) {
+            Assert.NotNull(locals);
+            Debug.Assert(!IsRuntimeScope);
 
-        //public bool DefinedDynamically(SymbolId id) {
-        //    return false;
-        //}
-
-        internal void TransformLocals(ScopeBuilder/*!*/ locals, AstGenerator/*!*/ gen) {
-            Assert.NotNull(gen);
-
-            foreach (var entry in _locals) {
-                if (entry.Value.TransformedVariable == null) {
-                    if (entry.Value.Kind != VariableKind.Runtime && !gen.CompilerOptions.IsEval) {
-                        Debug.Assert(entry.Value.Kind == VariableKind.Local);
-                        entry.Value.TransformedVariable = locals.DefineVariable(entry.Key, typeof(object));
-                    }
-                } else {
-                    Debug.Assert(entry.Value.Kind == VariableKind.Parameter);
+            // Do not statically define variables defined in top-level eval'd code:
+            //
+            // eval('x = 1')   <-- this variable needs to be defined in containing runtime scope, not in top-level eval scope
+            // eval('puts x')
+            // 
+            // eval('1.times { x = 1 }')  <-- x could be statically defined in the block since it is not visible outside the block
+            //
+            if (_outerScope == null || !_outerScope.IsRuntimeScope) {
+                foreach (var entry in this) {
+                    entry.Value.TransformDefinition(locals);
                 }
             }
         }
@@ -158,12 +111,12 @@
         internal MSA.ParameterExpression[]/*!*/ TransformParameters(Parameters parameters, int hiddenParameterCount) {
 
             int paramCount = hiddenParameterCount;
-            
+
             if (parameters == null) {
                 return new MSA.ParameterExpression[0];
             }
 
-            if (parameters.Mandatory != null) { 
+            if (parameters.Mandatory != null) {
                 paramCount += parameters.Mandatory.Count;
             }
 
@@ -175,43 +128,26 @@
                 paramCount += 1;
             }
 
-            MSA.ParameterExpression[] result = new MSA.ParameterExpression[paramCount];
+            var result = new MSA.ParameterExpression[paramCount];
 
             int dlrParamIndex = hiddenParameterCount;
 
             if (parameters.Mandatory != null) {
                 for (int i = 0; i < parameters.Mandatory.Count; i++) {
-                    string paramName = parameters.Mandatory[i].Name;
-                    MSA.ParameterExpression paramVar = MSA.Expression.Parameter(typeof(object), paramName);
-
-                    SetTransformedParameter(paramName, paramVar);
-
-                    result[dlrParamIndex++] = paramVar;
+                    result[dlrParamIndex++] = parameters.Mandatory[i].TransformParameterDefinition();
                 }
             }
 
             if (parameters.Optional != null) {
                 for (int i = 0; i < parameters.Optional.Count; i++) {
-                    SimpleAssignmentExpression p = parameters.Optional[i];
-
-                    string paramName = ((LocalVariable)p.Left).Name;
-                    MSA.ParameterExpression paramVar = MSA.Expression.Parameter(typeof(object), paramName);
-
-                    SetTransformedParameter(paramName, paramVar);
-
-                    result[dlrParamIndex++] = paramVar;
+                    result[dlrParamIndex++] = ((LocalVariable)parameters.Optional[i].Left).TransformParameterDefinition();
                 }
             }
 
             if (parameters.Array != null) {
-                string paramName = parameters.Array.Name;
-                MSA.ParameterExpression paramVar = MSA.Expression.Parameter(typeof(object), paramName);
+                result[dlrParamIndex++] = parameters.Array.TransformParameterDefinition();
+            }
 
-                SetTransformedParameter(paramName, paramVar);
-
-                result[dlrParamIndex++] = paramVar;
-            }
-            
             Debug.Assert(dlrParamIndex == result.Length);
 
             return result;
@@ -239,24 +175,80 @@
             }
         }
 
-        internal void SetTransformedParameter(string/*!*/ name, MSA.Expression/*!*/ variable) {
-            Debug.Assert(_locals[name].Kind == VariableKind.Parameter && variable != null);
-            _locals[name].TransformedVariable = variable;
+        #endregion
+    }
+
+    #region HybridStringDictionary
+
+    public class HybridStringDictionary<TValue> : IEnumerable<KeyValuePair<string, TValue>> {
+        // Number of variables in scopes during Rails startup:
+        // #variables    0     1     2    3    4    5   6+
+        // #scopes    4587  3814  1994  794  608  220  295
+        private const int ListLength = 4;
+
+        private Dictionary<string, TValue> _dict;
+        private KeyValuePair<string, TValue>[] _list;
+        private int _size;
+
+        public bool TryGetValue(string key, out TValue value) {
+            for (int i = 0; i < _size; i++) {
+                var entry = _list[i];
+                if (entry.Key == key) {
+                    value = entry.Value;
+                    return true;
+                }
+            }
+
+            if (_dict != null) {
+                return _dict.TryGetValue(key, out value);
+            }
+
+            value = default(TValue);
+            return false;
         }
 
-        internal VariableInfo/*!*/ ResolveVariable(string/*!*/ name) {
-            LexicalScope scope = this;
-            do {
-                VariableInfo var;
-                if (scope.LocalVariables.TryGetValue(name, out var)) {
-                    return var;
+        public void Add(string key, TValue value) {
+            if (_size > 0) {
+                if (_size < _list.Length) {
+                    _list[_size++] = new KeyValuePair<string, TValue>(key, value);
+                } else {
+                    _dict = new Dictionary<string, TValue>();
+                    for (int i = 0; i < _list.Length; i++) {
+                        var entry = _list[i];
+                        _dict.Add(entry.Key, entry.Value);
+                    }
+                    _dict.Add(key, value);
+                    _list = null;
+                    _size = -1;
                 }
-                scope = scope.ParentScope; 
-            } while (scope != null);
+            } else if (_size == 0) {
+                Debug.Assert(_list == null);
+                _list = new KeyValuePair<string, TValue>[ListLength];
+                _list[0] = new KeyValuePair<string, TValue>(key, value);
+                _size = 1;
+            } else {
+                Debug.Assert(_size == -1 && _dict != null);
+                _dict.Add(key, value);
+            }
+        }
 
-            // TODO: soft error
-            throw new NotImplementedException("undefined variable");
+        IEnumerator<KeyValuePair<string, TValue>>/*!*/ IEnumerable<KeyValuePair<string, TValue>>.GetEnumerator() {
+            for (int i = 0; i < _size; i++) {
+                yield return _list[i];
+            }
+
+            if (_dict != null) {
+                foreach (var entry in _dict) {
+                    yield return entry;
+                }
+            }
         }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+            return ((IEnumerable<KeyValuePair<string, TValue>>)this).GetEnumerator();
+        }
     }
+
+    #endregion
 }
 
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.cs;C615166
File: Parser.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.cs;C615166  (server)    10/28/2008 1:52 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.cs;LexicalScopes2
@@ -135,18 +135,8 @@
 
             _lexicalScopes.Clear();
 
-            LexicalScope lexicalScope;
-            if (options.LocalNames != null) {
-                lexicalScope = new LexicalScope(null, ScopeKind.RuntimeScope);
-                for (int i = 0; i < options.LocalNames.Count; i++) {
-                    lexicalScope.LocalVariables.Add(options.LocalNames[i], new VariableInfo(VariableKind.Runtime));
-                }
-            } else {
-                lexicalScope = new LexicalScope(null, ScopeKind.TopLevel);
-            }
+            EnterScope(CreateTopScope(options.LocalNames));
 
-            EnterScope(lexicalScope);
-
             using (SourceCodeReader reader = sourceUnit.GetReader()) {
                 _sourceUnit = sourceUnit;
                 _tokenizer.Initialize(null, reader, sourceUnit, options.InitialLocation);
@@ -184,15 +174,31 @@
             }
         }
 
-        // ------------------------------------------------------------------------
+        // Top level scope is created for top level code. 
+        // Variables defined outside of compilation unit (we are compiling eval) are stored in "outer scope", 
+        // to which the top level scope is nested in such case.
+        private static LexicalScope/*!*/ CreateTopScope(List<string> localVariableNames) {
+            LexicalScope outer;
+            if (localVariableNames != null) {
+                outer = new RuntimeLexicalScope(localVariableNames);
+            } else {
+                outer = null;
+            }
 
+            return new LexicalScope(outer);
+        }
+
         private LocalVariable/*!*/ DefineParameter(string/*!*/ name, SourceSpan location) {
-            if (CurrentScope.HasLocal(name)) {
+            // we are in a method:
+            Debug.Assert(CurrentScope.OuterScope == null);
+
+            LocalVariable variable;
+            if (CurrentScope.TryGetValue(name, out variable)) {
                 _tokenizer.ReportError(Errors.DuplicateParameterName);
-                return new LocalVariable(CurrentScope, name, location);
-            } 
+                return variable;
+            }
 
-            return CurrentScope.AddParameter(name, location);
+            return CurrentScope.AddVariable(name, location);
         }
 
         private Initializer/*!*/ AddInitializer(Initializer/*!*/ initializer) {
@@ -216,13 +222,19 @@
             _lexicalScopes.Push(scope);
             return scope;
         }
-        
-        private LexicalScope EnterNewScope(ScopeKind kind) {
-            LexicalScope result = new LexicalScope(CurrentScope, kind);
+
+        private LexicalScope EnterNestedScope() {
+            LexicalScope result = new LexicalScope(CurrentScope);
             _lexicalScopes.Push(result);
             return result;
         }
 
+        private LexicalScope EnterTopScope() {
+            LexicalScope result = new LexicalScope(null);
+            _lexicalScopes.Push(result);
+            return result;
+        }
+
         private LexicalScope LeaveScope() {
             return _lexicalScopes.Pop();
         }
@@ -245,7 +257,7 @@
 
         internal LeftValue/*!*/ CannotAssignError(string/*!*/ constantName, SourceSpan location) {
             Tokenizer.ReportError(Errors.CannotAssignTo, constantName);
-            return CurrentScope.AddLocal(GenerateErrorLocalName(), location);
+            return CurrentScope.ResolveOrAddVariable(GenerateErrorLocalName(), location);
         }
 
         private void MatchReferenceReadOnlyError(RegexMatchReference/*!*/ matchRef) {
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.Generated.cs;C615166
File: Parser.Generated.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.Generated.cs;C615166  (server)    10/28/2008 4:39 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.Generated.cs;LexicalScopes2
@@ -1992,7 +1992,7 @@
                     _tokenizer.ReportError(Errors.FileInitializerInMethod);
                 }
                             
-                EnterNewScope(ScopeKind.Initializer);
+                EnterTopScope();
             }
   }
 
@@ -2015,7 +2015,7 @@
                     _tokenizer.ReportError(Errors.FileFinalizerInMethod);
                 }
                 
-                EnterNewScope(ScopeKind.Block);
+                EnterTopScope();
             }
   }
 
@@ -2497,7 +2497,7 @@
       // @5 -> 
 #line 469 "Parser.y"
 			{
-            EnterNewScope(ScopeKind.Block);
+            EnterNestedScope();
         }
   }
 
@@ -4324,7 +4324,7 @@
       // @17 -> 
 #line 1340 "Parser.y"
 			{                
-            EnterNewScope(ScopeKind.Module);
+            EnterTopScope();
         }
   }
 
@@ -4358,7 +4358,7 @@
 			{
             yyval.Integer = _inSingletonMethodDefinition;
             _inSingletonMethodDefinition = 0;
-            EnterNewScope(ScopeKind.Module);
+            EnterTopScope();
         }
   }
 
@@ -4378,7 +4378,7 @@
       // @20 -> 
 #line 1369 "Parser.y"
 			{
-            EnterNewScope(ScopeKind.Module);
+            EnterTopScope();
         }
   }
 
@@ -4401,7 +4401,7 @@
 #line 1381 "Parser.y"
 			{
             _inInstanceMethodDefinition++;
-            EnterNewScope(ScopeKind.Method);
+            EnterTopScope();
         }
   }
 
@@ -4432,7 +4432,7 @@
 			{
             _inSingletonMethodDefinition++;
             _tokenizer.SetState(LexicalState.EXPR_END);
-            EnterNewScope(ScopeKind.Method);
+            EnterTopScope();
         }
   }
 
@@ -4595,7 +4595,7 @@
       // @24 -> 
 #line 1509 "Parser.y"
 			{
-            EnterNewScope(ScopeKind.Block);
+            EnterNestedScope();
         }
   }
 
@@ -4696,7 +4696,7 @@
       // @25 -> 
 #line 1564 "Parser.y"
 			{
-            EnterNewScope(ScopeKind.Block);
+            EnterNestedScope();
         }
   }
 
@@ -4715,7 +4715,7 @@
       // @26 -> 
 #line 1573 "Parser.y"
 			{
-            EnterNewScope(ScopeKind.Block);    
+            EnterNestedScope();    
         }
   }
 
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y;C615166
File: Parser.y
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y;C615166  (server)    10/28/2008 4:38 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Parser.y;LexicalScopes2
@@ -202,7 +202,7 @@
                     _tokenizer.ReportError(Errors.FileInitializerInMethod);
                 }
                             
-                EnterNewScope(ScopeKind.Initializer);
+                EnterTopScope();
             }
           '{' compstmt '}'
             {
@@ -215,7 +215,7 @@
                     _tokenizer.ReportError(Errors.FileFinalizerInMethod);
                 }
                 
-                EnterNewScope(ScopeKind.Block);
+                EnterTopScope();
             } 
           '{' compstmt '}'
             {                    
@@ -467,7 +467,7 @@
 cmd_brace_block:
       LBRACE_ARG
         {
-            EnterNewScope(ScopeKind.Block);
+            EnterNestedScope();
         }
       block_parameters_opt compstmt '}'
         {
@@ -1338,7 +1338,7 @@
 declaration_expression:
       CLASS qualified_module_name superclass
         {                
-            EnterNewScope(ScopeKind.Module);
+            EnterTopScope();
         }
       body END
         {
@@ -1357,7 +1357,7 @@
         {
             $<Integer>$ = _inSingletonMethodDefinition;
             _inSingletonMethodDefinition = 0;
-            EnterNewScope(ScopeKind.Module);
+            EnterTopScope();
         }
       body END
         {
@@ -1367,7 +1367,7 @@
         }
     | MODULE qualified_module_name
         {
-            EnterNewScope(ScopeKind.Module);
+            EnterTopScope();
         }
       body END
         {
@@ -1380,7 +1380,7 @@
     | DEF method_name
         {
             _inInstanceMethodDefinition++;
-            EnterNewScope(ScopeKind.Method);
+            EnterTopScope();
         }
       parameters_declaration body END
         {
@@ -1396,7 +1396,7 @@
         {
             _inSingletonMethodDefinition++;
             _tokenizer.SetState(LexicalState.EXPR_END);
-            EnterNewScope(ScopeKind.Method);
+            EnterTopScope();
         }
       parameters_declaration body END
         {
@@ -1507,7 +1507,7 @@
 do_block: 
       BLOCK_DO
         {
-            EnterNewScope(ScopeKind.Block);
+            EnterNestedScope();
         }
       block_parameters_opt compstmt END
         {
@@ -1562,7 +1562,7 @@
 brace_block: 
       '{'
         {
-            EnterNewScope(ScopeKind.Block);
+            EnterNestedScope();
         }
       block_parameters_opt compstmt '}'
         {
@@ -1571,7 +1571,7 @@
         }
     | DO
         {
-            EnterNewScope(ScopeKind.Block);    
+            EnterNestedScope();    
         }
       block_parameters_opt compstmt END
         {
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Tokenizer.cs;C615166
File: Tokenizer.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Tokenizer.cs;C615166  (server)    10/28/2008 3:50 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/Tokenizer.cs;LexicalScopes2
@@ -217,7 +217,7 @@
         /// Unbound tokenizer considers any identifier a local variable.
         /// </summary>
         private bool IsLocalVariable(string/*!*/ identifier) {
-            return _parser == null || _parser.CurrentScope.HasLocal(identifier);
+            return _parser == null || _parser.CurrentScope.ResolveVariable(identifier) != null;
         }
 
         private string GetTokenString() {
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/VariableFactory.cs;C607786
File: VariableFactory.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/VariableFactory.cs;C607786  (server)    10/28/2008 1:57 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Compiler/Parser/VariableFactory.cs;LexicalScopes2
@@ -36,11 +36,7 @@
         internal static Expression/*!*/ MakeRead(int kind, Parser/*!*/ parser, string name, SourceSpan location) {
             switch (kind) {
                 case Identifier:
-                    if (parser.CurrentScope.HasLocal(name)) {
-                        return parser.CurrentScope.AddLocal(name, location);
-                    } else {
-                        return new MethodCall(null, name, null, null, location);
-                    }
+                    return (Expression)parser.CurrentScope.ResolveVariable(name) ?? new MethodCall(null, name, null, null, location);
 
                 case Instance:
                     return new InstanceVariable(name, location);
@@ -82,7 +78,7 @@
         internal static LeftValue/*!*/ MakeLeftValue(int kind, Parser/*!*/ parser, string name, SourceSpan location) {
             switch (kind) {
                 case Identifier:
-                    return parser.CurrentScope.AddLocal(name, location);
+                    return parser.CurrentScope.ResolveOrAddVariable(name, location);
 
                 case Instance:
                     return new InstanceVariable(name, location);
===================================================================
edit: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyScope.cs;C618762
File: RubyScope.cs
===================================================================
--- $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyScope.cs;C618762  (server)    10/28/2008 8:37 PM
+++ Shelved Change: $/Dev10/feature/vsl_dynamic/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyScope.cs;LexicalScopes2
@@ -30,6 +30,13 @@
 
 namespace IronRuby.Runtime {
 
+    public enum ScopeKind {
+        TopLevel,
+        Method,
+        Module,
+        Block
+    }
+        
 #if SILVERLIGHT
     public abstract class RubyScope : CodeContext {
 #else
===================================================================
