Index: src/org/jruby/IRuby.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/IRuby.java,v
retrieving revision 1.7.2.3
diff -u -r1.7.2.3 IRuby.java
--- src/org/jruby/IRuby.java	3 Feb 2006 21:00:04 -0000	1.7.2.3
+++ src/org/jruby/IRuby.java	10 Feb 2006 20:08:55 -0000
@@ -247,7 +247,9 @@
 
 	public RubyNumeric newNumeric();
 
-	public RubyProc newProc();
+    public RubyProc newProc();
+
+    public RubyBinding newBinding();
 
 	public RubyString newString(String string);
 
Index: src/org/jruby/Ruby.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/Ruby.java,v
retrieving revision 1.67.2.5
diff -u -r1.67.2.5 Ruby.java
--- src/org/jruby/Ruby.java	3 Feb 2006 21:00:03 -0000	1.67.2.5
+++ src/org/jruby/Ruby.java	10 Feb 2006 20:08:57 -0000
@@ -72,6 +72,7 @@
 import org.jruby.runtime.builtin.IRubyObject;
 import org.jruby.runtime.builtin.meta.ArrayMetaClass;
 import org.jruby.runtime.builtin.meta.BignumMetaClass;
+import org.jruby.runtime.builtin.meta.BindingMetaClass;
 import org.jruby.runtime.builtin.meta.FileMetaClass;
 import org.jruby.runtime.builtin.meta.FixnumMetaClass;
 import org.jruby.runtime.builtin.meta.HashMetaClass;
@@ -365,6 +366,8 @@
         Frame frame = getCurrentContext().getCurrentFrame();
         frame.setSelf(topSelf);
         frame.getEvalState().setSelf(topSelf);
+        
+        getObject().defineConstant("TOPLEVEL_BINDING", newBinding());
 
         initBuiltinClasses();
     }
@@ -433,6 +436,7 @@
         RubyFloat.createFloatClass(this);
         
         new BignumMetaClass(this).initializeClass();
+        new BindingMetaClass(this).initializeClass();
         
         RubyMath.createMathModule(this); // depends on all numeric types
         RubyRegexp.createRegexpClass(this);
@@ -965,6 +969,10 @@
     public RubyProc newProc() {
     	return RubyProc.newProc(this, false);
     }
+    
+    public RubyBinding newBinding() {
+        return RubyBinding.newBinding(this);
+    }
 
     public RubyString newString(String string) {
     	return RubyString.newString(this, string);
Index: src/org/jruby/RubyObject.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyObject.java,v
retrieving revision 1.50.2.3
diff -u -r1.50.2.3 RubyObject.java
--- src/org/jruby/RubyObject.java	3 Feb 2006 21:00:04 -0000	1.50.2.3
+++ src/org/jruby/RubyObject.java	10 Feb 2006 20:08:59 -0000
@@ -630,6 +630,8 @@
             if (threadContext.getPreviousFrame() != null) {
                 threadContext.getCurrentFrame().setIter(threadContext.getPreviousFrame().getIter());
             }
+        } else if (scope instanceof RubyBinding) {
+            threadContext.preEvalWithBinding((RubyBinding)scope);
         }
         IRubyObject result = getRuntime().getNil();
         try {
@@ -638,9 +640,14 @@
         } finally {
             if (scope.isNil()) {
                 threadContext.getCurrentFrame().setIter(iter);
+                threadContext.setPosition(savedPosition);
+                threadContext.popRubyClass();
+            } else if (scope instanceof RubyBinding) {
+                threadContext.postEvalWithBinding();
+            } else {
+                threadContext.setPosition(savedPosition);
+                threadContext.popRubyClass();
             }
-            threadContext.setPosition(savedPosition);
-			threadContext.popRubyClass();
         }
         return result;
     }
Index: src/org/jruby/runtime/Block.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/runtime/Block.java,v
retrieving revision 1.15.2.2
diff -u -r1.15.2.2 Block.java
--- src/org/jruby/runtime/Block.java	3 Feb 2006 21:00:04 -0000	1.15.2.2
+++ src/org/jruby/runtime/Block.java	10 Feb 2006 20:09:00 -0000
@@ -70,7 +70,7 @@
                          context.getCurrentDynamicVars());
     }
 
-    private Block(
+    public Block(
         Node var,
         ICallable method,
         IRubyObject self,
@@ -81,7 +81,7 @@
         Iter iter,
         DynamicVariableSet dynamicVars) {
     	
-        assert method != null;
+        //assert method != null;
 
         this.var = var;
         this.method = method;
@@ -93,6 +93,13 @@
         this.cref = cref;
         this.dynamicVariables = dynamicVars;
     }
+    
+    public static Block createBinding(RubyModule wrapper, Iter iter, Frame frame, DynamicVariableSet dynVars) {
+        ThreadContext context = frame.getSelf().getRuntime().getCurrentContext();
+        
+        // FIXME: Ruby also saves wrapper, which we do not
+        return new Block(null, null, frame.getSelf(), frame, context.peekCRef(), frame.getScope(), context.getRubyClass(), iter, dynVars);
+    }
 
     public IRubyObject call(IRubyObject[] args, IRubyObject replacementSelf) {
         IRuby runtime = self.getRuntime();
Index: src/org/jruby/runtime/ThreadContext.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/runtime/ThreadContext.java,v
retrieving revision 1.44.2.9
diff -u -r1.44.2.9 ThreadContext.java
--- src/org/jruby/runtime/ThreadContext.java	10 Feb 2006 20:02:45 -0000	1.44.2.9
+++ src/org/jruby/runtime/ThreadContext.java	10 Feb 2006 20:09:02 -0000
@@ -39,6 +39,7 @@
 import org.jruby.IRuby;
 import org.jruby.IncludedModuleWrapper;
 import org.jruby.RubyArray;
+import org.jruby.RubyBinding;
 import org.jruby.RubyClass;
 import org.jruby.RubyModule;
 import org.jruby.RubyThread;
@@ -880,4 +881,27 @@
         blockStack.push(currentBlock);
         popRubyClass();
     }
+
+    public void preEvalWithBinding(RubyBinding binding) {
+        Block bindingBlock = binding.getBlock();
+
+        pushFrame(bindingBlock.getFrame());
+
+        getCurrentFrame().setScope(bindingBlock.getScope());
+
+        dynamicVarsStack.push(bindingBlock.getDynamicVariables());
+
+        pushRubyClass(bindingBlock.getKlass()); 
+
+        iterStack.push(bindingBlock.getIter());
+    }
+
+    public void postEvalWithBinding() {
+        iterStack.pop();
+        dynamicVarsStack.pop();
+        frameStack.pop();
+        
+        //blockStack.push(currentBlock);
+        popRubyClass();
+    }
 }
Index: test/org/jruby/test/BaseMockRuby.java
===================================================================
RCS file: /cvsroot/jruby/jruby/test/org/jruby/test/BaseMockRuby.java,v
retrieving revision 1.2.2.3
diff -u -r1.2.2.3 BaseMockRuby.java
--- test/org/jruby/test/BaseMockRuby.java	3 Feb 2006 21:00:05 -0000	1.2.2.3
+++ test/org/jruby/test/BaseMockRuby.java	10 Feb 2006 20:09:03 -0000
@@ -11,6 +11,7 @@
 
 import org.jruby.IRuby;
 import org.jruby.RubyArray;
+import org.jruby.RubyBinding;
 import org.jruby.RubyBoolean;
 import org.jruby.RubyClass;
 import org.jruby.RubyException;
@@ -352,13 +353,18 @@
 
 	public RubyNumeric newNumeric() {
 		throw new MockException();
-		
-	}
 
-	public RubyProc newProc() {
-		throw new MockException();
-		
-	}
+    }
+
+    public RubyProc newProc() {
+        throw new MockException();
+        
+    }
+
+    public RubyBinding newBinding() {
+        throw new MockException();
+        
+    }
 
 	public RubyString newString(String string) {
 		throw new MockException();
Index: src/org/jruby/RubyBinding.java
===================================================================
RCS file: src/org/jruby/RubyBinding.java
diff -N src/org/jruby/RubyBinding.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/jruby/RubyBinding.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,84 @@
+/***** BEGIN LICENSE BLOCK *****
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Common Public
+ * License Version 1.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * Copyright (C) 2001 Chad Fowler <chadfowler@chadfowler.com>
+ * Copyright (C) 2001 Alan Moore <alan_moore@gmx.net>
+ * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
+ * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
+ * Copyright (C) 2002-2005 Thomas E Enebo <enebo@acm.org>
+ * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
+ * Copyright (C) 2005 Charles O Nutter <headius@headius.com>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the CPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the CPL, the GPL or the LGPL.
+ ***** END LICENSE BLOCK *****/
+package org.jruby;
+
+import org.jruby.runtime.Block;
+import org.jruby.runtime.DynamicVariableSet;
+import org.jruby.runtime.Frame;
+import org.jruby.runtime.Iter;
+import org.jruby.runtime.ThreadContext;
+
+/**
+ * @author  jpetersen
+ */
+public class RubyBinding extends RubyObject {
+    private Block block = null;
+    private RubyModule wrapper = null;
+
+    public RubyBinding(IRuby runtime, RubyClass rubyClass, Block block, RubyModule wrapper) {
+        super(runtime, rubyClass);
+        
+        this.block = block;
+        this.wrapper = wrapper;
+    }
+
+    public Block getBlock() {
+        return block;
+    }
+
+    public RubyModule getWrapper() {
+        return wrapper;
+    }
+
+    // Proc class
+
+    public static RubyBinding newBinding(IRuby runtime) {
+        ThreadContext context = runtime.getCurrentContext();
+        
+        // FIXME: We should be cloning, not reusing: frame, scope, dynvars, and potentially iter/block info
+        RubyModule wrapper = context.getWrapper();
+        Iter iter = context.getCurrentIter();
+        Frame frame = context.getPreviousFrame();
+        // for TOPLEVEL_BINDING
+        if (frame == null) {
+            frame = context.getCurrentFrame();
+        }
+        DynamicVariableSet dynVars = context.getCurrentDynamicVars();
+        Block bindingBlock = Block.createBinding(wrapper, iter, frame, dynVars);
+
+        RubyBinding newBinding = new RubyBinding(runtime, runtime.getClass("Binding"), bindingBlock, context.getRubyClass());
+
+        return newBinding;
+    }
+}
Index: src/org/jruby/runtime/builtin/meta/BindingMetaClass.java
===================================================================
RCS file: src/org/jruby/runtime/builtin/meta/BindingMetaClass.java
diff -N src/org/jruby/runtime/builtin/meta/BindingMetaClass.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/jruby/runtime/builtin/meta/BindingMetaClass.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,73 @@
+/***** BEGIN LICENSE BLOCK *****
+ * Version: CPL 1.0/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Common Public
+ * License Version 1.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * Copyright (C) 2005 Thomas E Enebo <enebo@acm.org>
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the CPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the CPL, the GPL or the LGPL.
+ ***** END LICENSE BLOCK *****/
+package org.jruby.runtime.builtin.meta;
+
+import org.jruby.IRuby;
+import org.jruby.RubyBinding;
+import org.jruby.RubyClass;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.util.collections.SinglyLinkedList;
+
+public class BindingMetaClass extends ObjectMetaClass {
+    public BindingMetaClass(IRuby runtime) {
+        super("Binding", RubyBinding.class, runtime.getObject());
+    }
+    
+	public BindingMetaClass(String name, RubyClass superClass, SinglyLinkedList parentCRef) {
+		super(name, RubyBinding.class, superClass, parentCRef);
+	}
+
+	protected class BindingMeta extends Meta {
+		protected void initializeClass() {
+		}
+	};
+	
+	protected Meta getMeta() {
+		return new BindingMeta();
+	}
+	
+	public RubyClass newSubClass(String name, SinglyLinkedList parentCRef) {
+		return new BindingMetaClass(name, this, parentCRef);
+	}
+
+	protected IRubyObject allocateObject() {
+        RubyBinding instance = getRuntime().newBinding();
+        
+		instance.setMetaClass(this);
+		
+		return instance;
+	}
+
+    public IRubyObject newInstance(IRubyObject[] args) {
+        RubyBinding instance = RubyBinding.newBinding(getRuntime());
+        
+        instance.callInit(args);
+       
+        return instance;
+    }
+}
