Index: ext/pcre/php_pcre.c
===================================================================
--- ext/pcre/php_pcre.c	(.../trunk)	(revision 30)
+++ ext/pcre/php_pcre.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -1460,7 +1460,7 @@
 	}
 
 	if (is_callable_replace) {
-		if (Z_TYPE_P(replace) != IS_ARRAY) {
+		if (Z_TYPE_P(replace) != IS_ARRAY && Z_TYPE_P(replace) != IS_OBJECT) {
 			convert_to_text(replace);
 		}
 		if (!zend_is_callable(replace, 0, &callback_name)) {
Index: configure.in
===================================================================
--- configure.in	(.../trunk)	(revision 30)
+++ configure.in	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -1334,7 +1334,7 @@
     zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
     zend_ini.c zend_qsort.c zend_ts_hash.c zend_stream.c \
     zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c \
-    zend_strtol.c zend_gc.c)
+    zend_strtol.c zend_gc.c zend_closures.c)
 
 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
   PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c \
Index: Zend/zend_default_classes.c
===================================================================
--- Zend/zend_default_classes.c	(.../trunk)	(revision 30)
+++ Zend/zend_default_classes.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -24,6 +24,7 @@
 #include "zend_builtin_functions.h"
 #include "zend_interfaces.h"
 #include "zend_exceptions.h"
+#include "zend_closures.h"
 
 ZEND_API void zend_register_default_classes(TSRMLS_D) /* {{{ */
 {
@@ -31,6 +32,7 @@
 	zend_register_default_exception(TSRMLS_C);
 	zend_register_unicode_exceptions(TSRMLS_C);
 	zend_register_iterator_wrapper(TSRMLS_C);
+	zend_register_closure_ce(TSRMLS_C);
 }
 /* }}} */
 
Index: Zend/zend_execute.c
===================================================================
--- Zend/zend_execute.c	(.../trunk)	(revision 30)
+++ Zend/zend_execute.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -34,6 +34,7 @@
 #include "zend_ini.h"
 #include "zend_exceptions.h"
 #include "zend_interfaces.h"
+#include "zend_closures.h"
 #include "zend_vm.h"
 #include "zend_unicode.h"
 
@@ -1366,6 +1367,44 @@
 }
 /* }}} */
 
+static int zval_copy_static_var(zval **p, int num_args, va_list args, zend_hash_key *key) /* {{{ */
+{
+	HashTable *target = va_arg(args, HashTable*);
+	zend_bool is_ref;
+	zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
+
+	if (Z_TYPE_PP(p) == IS_CONSTANT && (Z_UNILEN_PP(p) == 0 || (Z_UNILEN_PP(p) == 1 && (UG(unicode) ? *Z_USTRVAL_PP(p) : *Z_STRVAL_PP(p)) == '\0'))) {
+		TSRMLS_FETCH();
+		is_ref = Z_UNILEN_PP(p) == 0;
+
+		if (!EG(active_symbol_table)) {
+			zend_rebuild_symbol_table(TSRMLS_C);
+		}
+		if (zend_u_hash_quick_find(EG(active_symbol_table), utype, key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) {
+			zval *tmp;
+
+			ALLOC_INIT_ZVAL(tmp);
+			ZVAL_NULL(tmp);
+			zend_u_hash_quick_add(target, utype, key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), NULL);
+
+			zend_error(E_NOTICE,"Undefined variable: %v", key->arKey);
+
+			return ZEND_HASH_APPLY_KEEP;
+		}
+
+		if (is_ref) {
+			SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
+		} else {
+			SEPARATE_ZVAL(p);
+		}
+	}
+	if (zend_u_hash_quick_add(target, utype, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) {
+		Z_ADDREF_PP(p);
+	}
+	return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
 #if ZEND_INTENSIVE_DEBUGGING
 
 #define CHECK_SYMBOL_TABLES()														\
Index: Zend/zend_vm_opcodes.h
===================================================================
--- Zend/zend_vm_opcodes.h	(.../trunk)	(revision 30)
+++ Zend/zend_vm_opcodes.h	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -153,3 +153,4 @@
 #define ZEND_USER_OPCODE                     150
 #define ZEND_U_NORMALIZE                     151
 #define ZEND_JMP_SET                         152
+#define ZEND_DECLARE_LAMBDA_FUNCTION         153
Index: Zend/zend_closures.c
===================================================================
--- Zend/zend_closures.c	(.../trunk)	(revision 0)
+++ Zend/zend_closures.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,137 @@
+/*
+   +----------------------------------------------------------------------+
+   | Zend Engine                                                          |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1998-2008 Zend Technologies Ltd. (http://www.zend.com) |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.00 of the Zend license,     |
+   | that is bundled with this package in the file LICENSE, and is        | 
+   | available through the world-wide-web at the following url:           |
+   | http://www.zend.com/license/2_00.txt.                                |
+   | If you did not receive a copy of the Zend license and are unable to  |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@zend.com so we can mail you a copy immediately.              |
+   +----------------------------------------------------------------------+
+   | Authors: Marcus Boerger <helly@php.net>                              |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id: zend_interfaces.c,v 1.33.2.4.2.6.2.4 2008/01/24 18:07:45 dmitry Exp $ */
+
+#include "zend.h"
+#include "zend_API.h"
+#include "zend_closures.h"
+#include "zend_objects.h"
+#include "zend_objects_API.h"
+#include "zend_globals.h"
+
+ZEND_API zend_class_entry *zend_ce_closure;
+
+static zend_object_handlers closure_handlers;
+
+
+static void zend_closure_free_storage(void *object TSRMLS_DC) /* {{{ */
+{
+	zend_closure *closure = (zend_closure *)object;
+	zend_object_std_dtor(&closure->std TSRMLS_CC);
+	efree(object);
+}
+/* }}} */
+
+
+static zend_object_value zend_closure_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
+{
+	zend_closure *closure;
+	zend_object_value object;
+	zval *tmp;
+
+	closure = emalloc(sizeof(zend_closure));
+	memset(closure, 0, sizeof(zend_closure));
+
+	zend_object_std_init(&closure->std, class_type TSRMLS_CC);
+	zend_hash_copy(closure->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+	
+	object.handle = zend_objects_store_put(closure, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_closure_free_storage, NULL TSRMLS_CC);
+	object.handlers = &closure_handlers;
+	
+	return object;
+}
+/* }}} */
+
+
+/* {{{ proto string Closure::__destruct()
+   Destroy the Closure object */
+ZEND_METHOD(closure, __destruct)
+{
+	zval *this = getThis ();
+	zend_closure *closure = (zend_closure *)zend_object_store_get_object(this);
+	zend_execute_data *ex = EG(current_execute_data);
+
+	if (!closure->initialized) return;
+
+	while (ex) {
+		if (ex->op_array == &closure->op_array) {
+			zend_error(E_ERROR, "Cannot destroy active lambda function");
+		}
+		ex = ex->prev_execute_data;
+	}
+	destroy_op_array(&closure->op_array TSRMLS_CC);
+	if (closure->This) {
+		zval_ptr_dtor(&closure->This);
+	}
+
+	closure->initialized = 0;
+}
+/* }}} */
+
+
+/* {{{ proto string Closure::__toString()
+   Obtain the string representation of the Closure object */
+ZEND_METHOD(closure, __toString)
+{
+	// FIXME: To be implemented
+	RETURN_STRINGL("Closure object", sizeof("Closure object"), 1);
+}
+/* }}} */
+
+
+const static zend_function_entry closure_functions[] = {
+	ZEND_ME(closure, __destruct, NULL, ZEND_ACC_DTOR|ZEND_ACC_PUBLIC)
+	ZEND_ME(closure, __toString, NULL, 0)
+	{NULL, NULL, NULL}
+};
+
+
+ZEND_API void zend_register_closure_ce(TSRMLS_D) /* {{{ */
+{
+	zend_class_entry ce;
+
+	INIT_CLASS_ENTRY(ce, "Closure", closure_functions);
+	zend_ce_closure = zend_register_internal_class(&ce TSRMLS_CC);
+	zend_ce_closure->create_object = zend_closure_new;
+	memcpy(&closure_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+	closure_handlers.clone_obj = NULL;
+}
+/* }}} */
+
+
+ZEND_API zend_closure *zend_get_closure(zval *obj TSRMLS_DC) /* {{{ */
+{
+	zend_class_entry *ce = Z_OBJCE_P(obj);
+	if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
+		zend_closure *closure = (zend_closure *)zend_object_store_get_object(obj);
+		if (!closure->initialized) return NULL;
+		return closure;
+	}
+	return NULL;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
Index: Zend/zend_closures.h
===================================================================
--- Zend/zend_closures.h	(.../trunk)	(revision 0)
+++ Zend/zend_closures.h	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,51 @@
+/*
+   +----------------------------------------------------------------------+
+   | Zend Engine                                                          |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1998-2008 Zend Technologies Ltd. (http://www.zend.com) |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 2.00 of the Zend license,     |
+   | that is bundled with this package in the file LICENSE, and is        | 
+   | available through the world-wide-web at the following url:           |
+   | http://www.zend.com/license/2_00.txt.                                |
+   | If you did not receive a copy of the Zend license and are unable to  |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@zend.com so we can mail you a copy immediately.              |
+   +----------------------------------------------------------------------+
+   | Authors: Andi Gutmans <andi@zend.com>                                |
+   |          Marcus Boerger <helly@php.net>                              |
+   |          Sterling Hughes <sterling@php.net>                          |
+   |          Zeev Suraski <zeev@zend.com>                                |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef ZEND_CLOSURES_H
+#define ZEND_CLOSURES_H
+
+BEGIN_EXTERN_C()
+
+typedef struct _zend_closure {
+	zend_object      std;
+	zend_bool        initialized;
+	zend_op_array    op_array;
+	zval             *This;
+} zend_closure;
+
+extern ZEND_API zend_class_entry *zend_ce_closure;
+
+ZEND_API void zend_register_closure_ce(TSRMLS_D);
+ZEND_API zend_closure *zend_get_closure(zval *obj TSRMLS_DC);
+
+END_EXTERN_C()
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
Index: Zend/zend_vm_execute.h
===================================================================
--- Zend/zend_vm_execute.h	(.../trunk)	(revision 30)
+++ Zend/zend_vm_execute.h	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -754,8 +754,22 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
 		}
 	} else {
+		zend_closure *closure;
 		function_name = &opline->op2.u.constant;
 
+		if (Z_TYPE_P(function_name) == IS_OBJECT &&
+		    (closure = (zend_closure*) zend_get_closure(function_name TSRMLS_CC)) != NULL) {
+			EX(fbc) = (zend_function*)&closure->op_array;
+			if ((EX(object) = closure->This) != NULL) {
+				Z_ADDREF_P(EX(object));
+				EX(called_scope) = Z_OBJCE_P(EX(object));
+			} else {
+				EX(called_scope) = closure->op_array.scope;
+			}
+
+			ZEND_VM_NEXT_OPCODE();
+		}
+
 		if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
 			zend_error_noreturn(E_ERROR, "Function name must be a string");
 		}
@@ -944,8 +958,22 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
 		}
 	} else {
+		zend_closure *closure;
 		function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
+		if (Z_TYPE_P(function_name) == IS_OBJECT &&
+		    (closure = (zend_closure*) zend_get_closure(function_name TSRMLS_CC)) != NULL) {
+			EX(fbc) = (zend_function*)&closure->op_array;
+			if ((EX(object) = closure->This) != NULL) {
+				Z_ADDREF_P(EX(object));
+				EX(called_scope) = Z_OBJCE_P(EX(object));
+			} else {
+				EX(called_scope) = closure->op_array.scope;
+			}
+			zval_dtor(free_op2.var);
+			ZEND_VM_NEXT_OPCODE();
+		}
+
 		if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
 			zend_error_noreturn(E_ERROR, "Function name must be a string");
 		}
@@ -1022,8 +1050,22 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
 		}
 	} else {
+		zend_closure *closure;
 		function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
+		if (Z_TYPE_P(function_name) == IS_OBJECT &&
+		    (closure = (zend_closure*) zend_get_closure(function_name TSRMLS_CC)) != NULL) {
+			EX(fbc) = (zend_function*)&closure->op_array;
+			if ((EX(object) = closure->This) != NULL) {
+				Z_ADDREF_P(EX(object));
+				EX(called_scope) = Z_OBJCE_P(EX(object));
+			} else {
+				EX(called_scope) = closure->op_array.scope;
+			}
+			if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+			ZEND_VM_NEXT_OPCODE();
+		}
+
 		if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
 			zend_error_noreturn(E_ERROR, "Function name must be a string");
 		}
@@ -1129,8 +1171,22 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
 		}
 	} else {
+		zend_closure *closure;
 		function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
 
+		if (Z_TYPE_P(function_name) == IS_OBJECT &&
+		    (closure = (zend_closure*) zend_get_closure(function_name TSRMLS_CC)) != NULL) {
+			EX(fbc) = (zend_function*)&closure->op_array;
+			if ((EX(object) = closure->This) != NULL) {
+				Z_ADDREF_P(EX(object));
+				EX(called_scope) = Z_OBJCE_P(EX(object));
+			} else {
+				EX(called_scope) = closure->op_array.scope;
+			}
+
+			ZEND_VM_NEXT_OPCODE();
+		}
+
 		if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
 			zend_error_noreturn(E_ERROR, "Function name must be a string");
 		}
@@ -2960,6 +3016,47 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+	zend_op_array *op_array;
+	zend_closure  *closure;
+
+	if (zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), Z_LVAL(opline->op2.u.constant), (void *) &op_array) == FAILURE ||
+	    op_array->type != ZEND_USER_FUNCTION) {
+		zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+	}
+
+	object_init_ex(&EX_T(opline->result.u.var).tmp_var, zend_ce_closure);
+	/* don't use zend_get_closure() since the initialized property is yet 0 */
+	closure = (zend_closure *)zend_object_store_get_object(&EX_T(opline->result.u.var).tmp_var);
+
+	closure->initialized = 1;
+	closure->op_array = *op_array;
+
+	if (closure->op_array.static_variables) {
+		HashTable *static_variables = closure->op_array.static_variables;
+
+		ALLOC_HASHTABLE(closure->op_array.static_variables);
+		zend_u_hash_init(closure->op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
+		zend_hash_apply_with_arguments(static_variables, (apply_func_args_t)zval_copy_static_var, 1, closure->op_array.static_variables);
+	}
+
+	if ((closure->op_array.scope = EG(scope)) != NULL) {
+		closure->op_array.fn_flags |= ZEND_ACC_PUBLIC;
+		if (closure->op_array.this_used && (closure->This = EG(This)) != NULL) {
+			Z_ADDREF_P(closure->This);
+		} else {
+			closure->op_array.fn_flags |= ZEND_ACC_STATIC;
+		}
+	} else {
+		closure->This = NULL;
+	}
+	(*closure->op_array.refcount)++;
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -34712,6 +34809,31 @@
   	ZEND_JMP_SET_SPEC_CV_HANDLER,
   	ZEND_JMP_SET_SPEC_CV_HANDLER,
   	ZEND_JMP_SET_SPEC_CV_HANDLER,
+  	ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_CONST_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER
   };
   zend_opcode_handlers = (opcode_handler_t*)labels;
Index: Zend/zend_compile.c
===================================================================
--- Zend/zend_compile.c	(.../trunk)	(revision 30)
+++ Zend/zend_compile.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -1006,6 +1006,7 @@
 	if (le) {
 		opline_ptr = (zend_op *)le->data;
 		if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
+			CG(active_op_array)->this_used = 1;
 			/* convert to FETCH_?(this) into IS_CV */
 			if (CG(active_op_array)->last == 0 ||
 			    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
@@ -1474,6 +1475,40 @@
 }
 /* }}} */
 
+void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC) /* {{{ */
+{
+	znode          function_name;
+	zend_op_array *current_op_array = CG(active_op_array);
+	int            current_op_number = get_next_op_number(CG(active_op_array));
+	zend_op       *current_op;
+
+	function_name.op_type = IS_CONST;
+	ZVAL_ASCII_STRING(&function_name.u.constant, "lambda", ZSTR_DUPLICATE);
+
+	zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
+
+	result->op_type = IS_TMP_VAR;
+	result->u.var = get_temporary_variable(current_op_array);;
+
+	current_op = &current_op_array->opcodes[current_op_number];
+	current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
+	zval_dtor(&current_op->op2.u.constant);
+	ZVAL_LONG(&current_op->op2.u.constant, zend_u_hash_func(Z_TYPE(current_op->op1.u.constant), Z_UNIVAL(current_op->op1.u.constant), Z_UNILEN(current_op->op1.u.constant)));
+	current_op->result = *result;
+}
+/* }}} */
+
+void zend_do_end_lambda_function_declaration(znode *function_token TSRMLS_DC) /* {{{ */
+{
+	zend_op_array *current_op_array = CG(active_op_array);
+
+	zend_do_end_function_declaration(function_token TSRMLS_CC);
+	if (current_op_array->this_used) {
+		CG(active_op_array)->this_used = 1;
+	}
+}
+/* }}} */
+
 void zend_do_handle_exception(TSRMLS_D) /* {{{ */
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -3811,6 +3846,7 @@
 
 	if (object->op_type == IS_CV) {
 		if (object->u.var == CG(active_op_array)->this_var) {
+			CG(active_op_array)->this_used = 1;
 		    SET_UNUSED(*object); /* this means $this for objects */
 	    }
 	} else if (fetch_list_ptr->count == 1) {
@@ -3818,6 +3854,7 @@
 		zend_op *opline_ptr = (zend_op *) le->data;
 
 		if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
+			CG(active_op_array)->this_used = 1;
 			efree(Z_STRVAL(opline_ptr->op1.u.constant));
 			SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
 			opline_ptr->op2 = *property;
@@ -4395,6 +4432,36 @@
 }
 /* }}} */
 
+void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
+{
+	znode value;
+
+	/* Empty constant has a special meaning of lexical variable.
+	 * It is substituted by real value in ZEND_DECLARE_LAMBDA_FUNCTION */
+	value.op_type = IS_CONST;
+	if (is_ref) {
+		if (UG(unicode)) {
+			ZVAL_EMPTY_UNICODE(&value.u.constant);
+		} else {
+			ZVAL_EMPTY_STRING(&value.u.constant);
+		}
+	} else {
+		if (UG(unicode)) {
+			/* string of length 1 containing only 0-bytes */
+			UChar zero[2] = { 0, 0 };
+			ZVAL_UNICODEL(&value.u.constant, zero, 1, 1);
+		} else {
+			ZVAL_STRINGL(&value.u.constant, "\0", 1, 1);
+		}
+	}
+	Z_TYPE(value.u.constant) = IS_CONSTANT;
+	Z_SET_REFCOUNT_P(&value.u.constant, 1);
+	Z_UNSET_ISREF_P(&value.u.constant);
+	
+	zend_do_fetch_static_variable(varname, &value, ZEND_FETCH_STATIC TSRMLS_CC);
+}
+/* }}} */
+
 void zend_do_fetch_global_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
 {
 	zend_op *opline;
Index: Zend/ZendTS.dsp
===================================================================
--- Zend/ZendTS.dsp	(.../trunk)	(revision 30)
+++ Zend/ZendTS.dsp	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -148,6 +148,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\zend_closures.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\zend_compile.c
 # End Source File
 # Begin Source File
Index: Zend/zend_compile.h
===================================================================
--- Zend/zend_compile.h	(.../trunk)	(revision 30)
+++ Zend/zend_compile.h	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -233,6 +233,8 @@
 	zend_uint doc_comment_len;
 	zend_uint early_binding; /* the linked list of delayed declarations */
 
+	zend_bool this_used;
+
 	void *reserved[ZEND_MAX_RESERVED_RESOURCES];
 };
 
@@ -438,6 +440,10 @@
 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
 void zend_do_handle_exception(TSRMLS_D);
 
+void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC);
+void zend_do_end_lambda_function_declaration(znode *function_token TSRMLS_DC);
+void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC);
+
 void zend_do_try(znode *try_token TSRMLS_DC);
 void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC);
 void zend_do_end_catch(znode *try_token TSRMLS_DC);
Index: Zend/tests/closure_003.phpt
===================================================================
--- Zend/tests/closure_003.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_003.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,37 @@
+--TEST--
+Closure test: Lambda with lexical variables (local scope)
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+function run () {
+	$x = 4;
+
+	$lambda1 = function () use ($x) {
+		echo "$x\n";
+	};
+
+	$lambda2 = function () use (&$x) {
+		echo "$x\n";
+	};
+
+	$lambda1();
+	$lambda2();
+	$x++;
+	$lambda1();
+	$lambda2();
+}
+
+run();
+
+echo "Done\n";
+?>
+--EXPECTF--
+4
+4
+4
+5
+Done
Index: Zend/tests/closure_005a.phpt
===================================================================
--- Zend/tests/closure_005a.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_005a.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,36 @@
+--TEST--
+Closure test: Lambda inside class, lifetime of $this [no reference to $this]
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+class A {
+	function __destruct() {
+		echo "Destroyed\n";
+	}
+
+	function getClosure() {
+		return function() {
+			echo "Hello World!\n";
+		};
+	}
+}
+
+$a = new A;
+
+$lambda = $a->getClosure();
+
+$lambda();
+unset($a);
+$lambda();
+
+echo "Done\n";
+?>
+--EXPECTF--
+Hello World!
+Destroyed
+Hello World!
+Done
Index: Zend/tests/closure_004.phpt
===================================================================
--- Zend/tests/closure_004.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_004.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,39 @@
+--TEST--
+Closure test: Lambda with lexical variables (scope lifetime)
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+function run () {
+	$x = 4;
+
+	$lambda1 = function () use ($x) {
+		echo "$x\n";
+	};
+
+	$lambda2 = function () use (&$x) {
+		echo "$x\n";
+		$x++;
+	};
+
+	return array($lambda1, $lambda2);
+}
+
+list ($lambda1, $lambda2) = run();
+
+$lambda1();
+$lambda2();
+$lambda1();
+$lambda2();
+
+echo "Done\n";
+?>
+--EXPECTF--
+4
+4
+4
+5
+Done
Index: Zend/tests/closure_005.phpt
===================================================================
--- Zend/tests/closure_005.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_005.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,68 @@
+--TEST--
+Closure test: Lambda inside class, lifetime of $this
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+class A {
+	private $x;
+
+	function __construct($x) {
+		$this->x = $x;
+	}
+
+	function __destruct() {
+		echo "Destroyed\n";
+	}
+
+	function getIncer($val) {
+		return function() use ($val) {
+			$this->x += $val;
+		};
+	}
+
+	function getPrinter() {
+		return function() {
+			echo $this->x."\n";
+		};
+	}
+	
+	function printX() {
+		echo $this->x."\n";
+	}
+}
+
+$a = new A(3);
+$incer = $a->getIncer(2);
+$printer = $a->getPrinter();
+
+$a->printX();
+$printer();
+$incer();
+$a->printX();
+$printer();
+
+unset($a);
+
+$incer();
+$printer();
+
+unset($incer);
+$printer();
+
+unset($printer);
+
+echo "Done\n";
+?>
+--EXPECTF--
+3
+3
+5
+5
+7
+7
+Destroyed
+Done
Index: Zend/tests/closure_006.phpt
===================================================================
--- Zend/tests/closure_006.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_006.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,23 @@
+--TEST--
+Closure test: Nested lambdas
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+$getClosure = function ($v) {
+	return function () use ($v) {
+		echo "Hello World: $v!\n";
+	};
+};
+
+$closure = $getClosure (2);
+$closure ();
+
+echo "Done\n";
+?>
+--EXPECTF--
+Hello World: 2!
+Done
Index: Zend/tests/closure_007.phpt
===================================================================
--- Zend/tests/closure_007.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_007.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,42 @@
+--TEST--
+Closure test: Nested lambdas in classes
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+class A {
+	private $x = 0;
+
+	function getClosureGetter () {
+		return function () {
+			return function () {
+				$this->x++;
+			};
+		};
+	}
+
+	function printX () {
+		echo $this->x."\n";
+	}
+}
+
+$a = new A;
+$a->printX();
+$getClosure = $a->getClosureGetter();
+$a->printX();
+$closure = $getClosure();
+$a->printX();
+$closure();
+$a->printX();
+
+echo "Done\n";
+?>
+--EXPECTF--
+0
+0
+0
+1
+Done
Index: Zend/tests/closure_001.phpt
===================================================================
--- Zend/tests/closure_001.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_001.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,34 @@
+--TEST--
+Closure test: Lambda without lexical variables
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+$lambda1 = function () {
+	echo "Hello World!\n";
+};
+
+$lambda2 = function ($x) {
+	echo "Hello $x!\n";
+};
+
+var_dump(is_callable($lambda1));
+var_dump(is_callable($lambda2));
+$lambda1();
+$lambda2("Universe");
+call_user_func($lambda1);
+call_user_func($lambda2, "Universe");
+
+echo "Done\n";
+?>
+--EXPECTF--	
+bool(true)
+bool(true)
+Hello World!
+Hello Universe!
+Hello World!
+Hello Universe!
+Done
Index: Zend/tests/closure_008.phpt
===================================================================
--- Zend/tests/closure_008.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_008.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,26 @@
+--TEST--
+Closure test: Use in preg_replace()
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+function replace_spaces($text) {
+	$lambda = function ($matches) {
+		return str_replace(' ', '&nbsp;', $matches[1]).' ';
+	};
+	return preg_replace_callback('/( +) /', $lambda, $text);
+}
+
+echo replace_spaces("1 2 3\n");
+echo replace_spaces("1  2  3\n");
+echo replace_spaces("1   2   3\n");
+echo "Done\n";
+?>
+--EXPECTF--
+1 2 3
+1&nbsp; 2&nbsp; 3
+1&nbsp;&nbsp; 2&nbsp;&nbsp; 3
+Done
Index: Zend/tests/closure_002.phpt
===================================================================
--- Zend/tests/closure_002.phpt	(.../trunk)	(revision 0)
+++ Zend/tests/closure_002.phpt	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -0,0 +1,33 @@
+--TEST--
+Closure test: Lambda with lexical variables (global scope)
+--SKIPIF--
+<?php 
+	if (!class_exists('Closure')) die('skip Closure support is needed');
+?>
+--FILE--
+<?php
+
+$x = 4;
+
+$lambda1 = function () use ($x) {
+	echo "$x\n";
+};
+
+$lambda2 = function () use (&$x) {
+	echo "$x\n";
+};
+
+$lambda1();
+$lambda2();
+$x++;
+$lambda1();
+$lambda2();
+
+echo "Done\n";
+?>
+--EXPECTF--
+4
+4
+4
+5
+Done
Index: Zend/zend_API.c
===================================================================
--- Zend/zend_API.c	(.../trunk)	(revision 30)
+++ Zend/zend_API.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -25,6 +25,7 @@
 #include "zend_API.h"
 #include "zend_modules.h"
 #include "zend_constants.h"
+#include "zend_closures.h"
 #include "zend_exceptions.h"
 
 #ifdef HAVE_STDARG_H
@@ -3093,6 +3094,27 @@
 			}
 			return 0;
 
+		case IS_OBJECT:
+			{
+				zend_closure *closure = zend_get_closure(callable TSRMLS_CC);
+
+				if (closure) {
+					*fptr_ptr = (zend_function*)&closure->op_array;
+					if (closure->This) {
+						*zobj_ptr_ptr = &closure->This;
+						*ce_ptr = Z_OBJCE_P(closure->This);
+					} else {
+						*zobj_ptr_ptr = NULL;
+						*ce_ptr = closure->op_array.scope;
+					}
+					if (callable_name) {
+						ZVAL_ZSTR(callable_name, UG(unicode), closure->op_array.function_name, 1);
+					}
+					return 1;
+				}
+			}
+			/* break missing intentionally */
+
 		default:
 			if (callable_name) {
 				*callable_name = *callable;
Index: Zend/Zend.dsp
===================================================================
--- Zend/Zend.dsp	(.../trunk)	(revision 30)
+++ Zend/Zend.dsp	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -123,6 +123,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\zend_closures.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\zend_compile.c
 # End Source File
 # Begin Source File
Index: Zend/zend_language_parser.y
===================================================================
--- Zend/zend_language_parser.y	(.../trunk)	(revision 30)
+++ Zend/zend_language_parser.y	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -304,7 +304,7 @@
 
 
 unticked_function_declaration_statement:
-		T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type, NULL TSRMLS_CC); }
+		function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); }
 			'(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
 ;
 
@@ -512,8 +512,8 @@
 class_statement:
 		variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
 	|	class_constant_declaration ';'
-	|	method_modifiers T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, &$1 TSRMLS_CC); } '('
-			parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
+	|	method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } '('
+			parameter_list ')' method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
 ;
 
 
@@ -647,8 +647,26 @@
 	|	T_ARRAY '(' array_pair_list ')' { $$ = $3; }
 	|	'`' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '`' { zend_do_shell_exec(&$$, &$3 TSRMLS_CC); }
 	|	T_PRINT expr  { zend_do_print(&$$, &$2 TSRMLS_CC); }
+	|	function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type TSRMLS_CC); }
+			parameter_list ')' lexical_vars '{' inner_statement_list '}' {  zend_do_end_lambda_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
 ;
 
+function:
+	T_FUNCTION { $$.u.opline_num = CG(zend_lineno); }
+;
+
+lexical_vars:
+		/* emptry */
+	|	T_USE '(' lexical_var_list ')'
+;
+
+lexical_var_list:
+		lexical_var_list ',' T_VARIABLE			{ zend_do_fetch_lexical_variable(&$3, 0 TSRMLS_CC); }
+	|	lexical_var_list ',' '&' T_VARIABLE		{ zend_do_fetch_lexical_variable(&$4, 1 TSRMLS_CC); }
+	|	T_VARIABLE								{ zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); }
+	|	'&' T_VARIABLE							{ zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); }
+;
+
 function_call:
 		T_STRING	'(' { $2.u.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
 				function_call_parameter_list
Index: Zend/zend_execute_API.c
===================================================================
--- Zend/zend_execute_API.c	(.../trunk)	(revision 30)
+++ Zend/zend_execute_API.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -30,6 +30,7 @@
 #include "zend_constants.h"
 #include "zend_extensions.h"
 #include "zend_exceptions.h"
+#include "zend_closures.h"
 #include "zend_vm.h"
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -795,6 +796,21 @@
 			SEPARATE_ZVAL_IF_NOT_REF(tmp_object_ptr);
 			fci->object_pp = tmp_object_ptr;
 			Z_SET_ISREF_PP(fci->object_pp);
+		} else if (Z_TYPE_P(fci->function_name) == IS_OBJECT) {
+			zend_closure *closure = (zend_closure*) zend_get_closure(fci->function_name TSRMLS_CC);
+
+			if (!closure) {
+				return FAILURE;
+			}
+			EX(function_state).function = (zend_function*)&closure->op_array;
+			if (closure->This) {
+				fci->object_pp = &closure->This;
+				calling_scope = Z_OBJCE_P(closure->This);
+			} else {
+				fci->object_pp = NULL;
+				calling_scope = closure->op_array.scope;
+			}
+			goto init_fci_cache;
 		}
 
 		if (fci->object_pp && !*fci->object_pp) {
@@ -1035,6 +1051,8 @@
 				return FAILURE;
 			}
 		}
+
+init_fci_cache:
 		if (fci_cache &&
 			(EX(function_state).function->type != ZEND_INTERNAL_FUNCTION ||
 			((zend_internal_function*)EX(function_state).function)->handler != zend_std_call_user_call)
Index: Zend/zend_vm_def.h
===================================================================
--- Zend/zend_vm_def.h	(.../trunk)	(revision 30)
+++ Zend/zend_vm_def.h	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -2084,8 +2084,22 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
 		}
 	} else {
+		zend_closure *closure;
 		function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
+		if (Z_TYPE_P(function_name) == IS_OBJECT &&
+		    (closure = (zend_closure*) zend_get_closure(function_name TSRMLS_CC)) != NULL) {
+			EX(fbc) = (zend_function*)&closure->op_array;
+			if ((EX(object) = closure->This) != NULL) {
+				Z_ADDREF_P(EX(object));
+				EX(called_scope) = Z_OBJCE_P(EX(object));
+			} else {
+				EX(called_scope) = closure->op_array.scope;
+			}
+			FREE_OP2();
+			ZEND_VM_NEXT_OPCODE();
+		}
+
 		if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
 			zend_error_noreturn(E_ERROR, "Function name must be a string");
 		}
@@ -4533,4 +4547,45 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, CONST)
+{
+	zend_op *opline = EX(opline);
+	zend_op_array *op_array;
+	zend_closure  *closure;
+
+	if (zend_u_hash_quick_find(EG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), Z_LVAL(opline->op2.u.constant), (void *) &op_array) == FAILURE ||
+	    op_array->type != ZEND_USER_FUNCTION) {
+		zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+	}
+
+	object_init_ex(&EX_T(opline->result.u.var).tmp_var, zend_ce_closure);
+	/* don't use zend_get_closure() since the initialized property is yet 0 */
+	closure = (zend_closure *)zend_object_store_get_object(&EX_T(opline->result.u.var).tmp_var);
+
+	closure->initialized = 1;
+	closure->op_array = *op_array;
+
+	if (closure->op_array.static_variables) {
+		HashTable *static_variables = closure->op_array.static_variables;
+	
+		ALLOC_HASHTABLE(closure->op_array.static_variables);
+		zend_u_hash_init(closure->op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
+		zend_hash_apply_with_arguments(static_variables, (apply_func_args_t)zval_copy_static_var, 1, closure->op_array.static_variables);
+	}
+
+	if ((closure->op_array.scope = EG(scope)) != NULL) {
+		closure->op_array.fn_flags |= ZEND_ACC_PUBLIC;
+		if (closure->op_array.this_used && (closure->This = EG(This)) != NULL) {
+			Z_ADDREF_P(closure->This);
+		} else {
+			closure->op_array.fn_flags |= ZEND_ACC_STATIC;
+		}
+	} else {
+		closure->This = NULL;
+	}
+	(*closure->op_array.refcount)++;
+
+	ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
Index: Zend/Makefile.am
===================================================================
--- Zend/Makefile.am	(.../trunk)	(revision 30)
+++ Zend/Makefile.am	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -17,7 +17,7 @@
 	zend_objects_API.c zend_ts_hash.c zend_stream.c \
 	zend_default_classes.c \
 	zend_iterators.c zend_interfaces.c zend_exceptions.c \
-	zend_strtod.c zend_strtod.c zend_strtol.c
+	zend_strtod.c zend_strtod.c zend_strtol.c zend_closures.c
 
 libZend_la_LDFLAGS =
 libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
Index: Zend/zend_opcode.c
===================================================================
--- Zend/zend_opcode.c	(.../trunk)	(revision 30)
+++ Zend/zend_opcode.c	(.../tags/6.0-closures-obj-use-this)	(revision 30)
@@ -109,6 +109,8 @@
 
 	op_array->early_binding = -1;
 
+	op_array->this_used = 0;
+
 	memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
 
 	zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
