Index: Zend/zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.296.2.27.2.34.2.38
diff -u -r1.296.2.27.2.34.2.38 zend_API.c
--- Zend/zend_API.c	5 Jun 2008 18:53:06 -0000	1.296.2.27.2.34.2.38
+++ Zend/zend_API.c	17 Jun 2008 14:29:27 -0000
@@ -2337,6 +2337,19 @@
 			*fptr_ptr = fptr;
 			efree(lmname);
 			return 1;
+			/* If the function is a compile-time lambda function but not a closure,
+			 * it is not callable. We still assign the function pointer though, just
+			 * in case some code relies on the fact that every function table entry
+			 * is actually callable. */
+			if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.is_lambda && !fptr->op_array.is_closure) {
+				if (error) {
+					if (*error) {
+						efree(*error);
+					}
+					zend_spprintf(error, 0, "cannot access lambda function that is not a closure");
+				}
+				return 0;
+			}
 		}
 		efree(lmname);
 	}
@@ -2470,6 +2483,19 @@
 					}
 				}
 			}
+			/* If the function is a compile-time lambda function but not a closure,
+			 * it is not callable. We still assign the function pointer though, just
+			 * in case some code relies on the fact that every function table entry
+			 * is actually callable. */
+			if (retval && ((zend_op_array *)fptr)->is_lambda && !((zend_op_array *)fptr)->is_closure) {
+				if (error) {
+					if (*error) {
+						efree(*error);
+					}
+					zend_spprintf(error, 0, "cannot access lambda function that is not a closure");
+				}
+				retval = 0;
+			}
 		}
 	}
 	efree(lmname);
@@ -2482,7 +2508,7 @@
 	char *lcname;
 	int callable_name_len_local;
 	zend_class_entry *ce_local, **pce;
-	zend_function *fptr_local;
+	zend_function *fptr_local, *tmp_func;
 	zval **zobj_ptr_local;
 
 	if (callable_name) {
@@ -2519,6 +2545,60 @@
 
 			return zend_is_callable_check_func(check_flags, zobj_ptr_ptr, NULL, callable, ce_ptr, fptr_ptr, error TSRMLS_CC);
 
+		case IS_RESOURCE:
+			tmp_func = (zend_function *) zend_fetch_resource (&callable TSRMLS_CC, -1, NULL, NULL, 1, le_lambda_func);
+			if (!tmp_func) {
+				if (callable_name) {
+					zval expr_copy;
+					int use_copy;
+	
+					zend_make_printable_zval(callable, &expr_copy, &use_copy);
+					*callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
+					*callable_name_len = Z_STRLEN(expr_copy);
+					zval_dtor(&expr_copy);
+				}
+				if (error) zend_spprintf(error, 0, "no array or string given");
+				return 0;
+			}
+			{
+				zend_class_entry *ce = NULL;
+				if (tmp_func->op_array.scope) {
+					ce = tmp_func->op_array.scope;
+					if (tmp_func->op_array.closure_object_ctx) {
+						ce = Z_OBJCE_P(tmp_func->op_array.closure_object_ctx);
+					}
+				}
+				if (callable_name) {
+					if (ce) {
+						char *ptr;
+						*callable_name_len = ce->name_length + sizeof("::") + strlen(*callable_name);
+						ptr = *callable_name = emalloc(*callable_name_len + 1);
+						memcpy(ptr, ce->name, ce->name_length);
+						ptr += ce->name_length;
+						memcpy(ptr, "::", sizeof("::") - 1);
+						ptr += sizeof("::") - 1;
+						memcpy(ptr, tmp_func->op_array.function_name, strlen(tmp_func->op_array.function_name) + 1);
+					} else {
+						*callable_name = estrdup(tmp_func->op_array.function_name);
+						*callable_name_len = strlen(*callable_name);
+					}
+				}
+				if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
+					return 1;
+				} else {
+					*fptr_ptr = tmp_func;
+					if (ce) {
+						if (ce_ptr) {
+							*ce_ptr = ce;
+						}
+						if (zobj_ptr_ptr && tmp_func->op_array.closure_object_ctx) {
+							*zobj_ptr_ptr = &tmp_func->op_array.closure_object_ctx;
+						}
+					}
+					return 1;
+				}
+			}
+
 		case IS_ARRAY:
 			{
 				zend_class_entry *ce = NULL;
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.68
diff -u -r1.647.2.27.2.41.2.68 zend_compile.c
--- Zend/zend_compile.c	15 Jun 2008 18:27:37 -0000	1.647.2.27.2.41.2.68
+++ Zend/zend_compile.c	17 Jun 2008 14:29:27 -0000
@@ -86,6 +86,26 @@
 }
 
 
+static void build_lambda_function_key(zval *result TSRMLS_DC)
+{
+	char lambda_num_buf[32];
+	uint lambda_num_len;
+	char *filename;
+
+	lambda_num_len = zend_sprintf(lambda_num_buf, "%d", (*CG(compiled_lambda_count))++);
+	if (CG(compiled_filename)) {
+		filename = CG(compiled_filename);
+	} else {
+		filename = "-";
+	}
+
+	result->value.str.len = sizeof("__compiled_lambda__")+strlen(filename)+lambda_num_len-1;
+	zend_spprintf(&result->value.str.val, 0, "__compiled_lambda_%s_%s", filename, lambda_num_buf);
+	result->type = IS_STRING;
+	Z_SET_REFCOUNT_P(result, 1);
+}
+
+
 int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC)
 {
 	auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
@@ -143,12 +163,27 @@
 }
 
 
+static void free_filename(void *fn) {
+	zend_compiled_filename **filename = (zend_compiled_filename **)fn;
+	if (!*filename) {
+		return;
+	}
+	if ((*filename)->name) {
+		efree((*filename)->name);
+	}
+	if ((*filename)->lambda_count) {
+		efree((*filename)->lambda_count);
+	}
+	efree(*filename);
+}
+
+
 void init_compiler(TSRMLS_D)
 {
 	CG(active_op_array) = NULL;
 	zend_init_compiler_data_structures(TSRMLS_C);
 	zend_init_rsrc_list(TSRMLS_C);
-	zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
+	zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_filename, 0);
 	zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
 	CG(unclean_shutdown) = 0;
 }
@@ -171,17 +206,22 @@
 
 ZEND_API char *zend_set_compiled_filename(char *new_compiled_filename TSRMLS_DC)
 {
-	char **pp, *p;
+	zend_compiled_filename **pfilename, *filename;
 	int length = strlen(new_compiled_filename);
 
-	if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
-		CG(compiled_filename) = *pp;
-		return *pp;
-	}
-	p = estrndup(new_compiled_filename, length);
-	zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
-	CG(compiled_filename) = p;
-	return p;
+	if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pfilename) == SUCCESS) {
+		CG(compiled_filename) = (*pfilename)->name;
+		CG(compiled_lambda_count) = (*pfilename)->lambda_count;
+		return (*pfilename)->name;
+	}
+	filename = emalloc(sizeof(*filename));
+	filename->name = estrndup(new_compiled_filename, length);
+	filename->lambda_count = emalloc(sizeof(*filename->lambda_count));
+	*filename->lambda_count = 0;
+	zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &filename, sizeof(char *), (void **) &pfilename);
+	CG(compiled_filename) = filename->name;
+	CG(compiled_lambda_count) = filename->lambda_count;
+	return filename->name;
 }
 
 
@@ -1137,30 +1177,55 @@
 }
 
 
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC)
+void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_lambda, znode *fn_flags_znode, znode *result TSRMLS_DC)
 {
 	zend_op_array op_array;
-	char *name = function_name->u.constant.value.str.val;
-	int name_len = function_name->u.constant.value.str.len;
+	char *name;
+	int name_len;
 	int function_begin_line = function_token->u.opline_num;
 	zend_uint fn_flags;
 	char *lcname;
 	zend_bool orig_interactive;
+	zval lambda_name;
 	ALLOCA_FLAG(use_heap)
 
-	if (is_method) {
-		if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
-			if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
-				zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+	if (is_lambda) {
+		/* generate a new lambda key */
+		memset(&lambda_name, 0, sizeof(lambda_name));
+		build_lambda_function_key(&lambda_name TSRMLS_CC);
+		name = estrndup(lambda_name.value.str.val, lambda_name.value.str.len);
+		name_len = lambda_name.value.str.len;
+	} else {
+		name = function_name->u.constant.value.str.val;
+		name_len = function_name->u.constant.value.str.len;
+
+		/* make sure these checks are within !is_lambda since function_name
+		 * may be NULL for lambda functions. Note that these checks don't
+		 * matter for lambda functions anyway. */
+		if (is_method) {
+			if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
+				if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
+					zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+				}
+				Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
 			}
-			Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
+			fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
+		} else {
+			fn_flags = 0;
+		}
+		if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
+			zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
 		}
-		fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
-	} else {
-		fn_flags = 0;
 	}
-	if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
-		zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
+
+	if (is_lambda && CG(active_class_entry)) {
+		is_method = 1;
+		fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_FINAL;
+		if (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) {
+			fn_flags |= ZEND_ACC_STATIC;
+		}
+	} else if (is_lambda) {
+		fn_flags = 0;
 	}
 
 	function_token->u.op_array = CG(active_op_array);
@@ -1172,6 +1237,7 @@
 	CG(interactive) = orig_interactive;
 
 	op_array.function_name = name;
+	op_array.is_lambda = is_lambda;
 	op_array.return_reference = return_reference;
 	op_array.fn_flags |= fn_flags;
 	op_array.pass_rest_by_reference = 0;
@@ -1181,7 +1247,36 @@
 
 	op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
 
-	if (is_method) {
+	if (is_lambda) {
+		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+		opline->opcode = ZEND_DECLARE_LAMBDA_FUNC;
+		opline->op1.op_type = IS_CONST;
+		opline->op1.u.constant = lambda_name;
+		if (is_method) {
+			opline->op2.op_type = IS_CONST;
+			ZVAL_STRINGL(&opline->op2.u.constant, CG(active_class_entry)->name, CG(active_class_entry)->name_length, 1);
+		} else {
+			SET_UNUSED(opline->op2);
+		}
+		opline->result.op_type = IS_TMP_VAR;
+		opline->result.u.var = get_temporary_variable(CG(active_op_array));
+		*result = opline->result;
+		
+		HashTable *function_table;
+		if (is_method) {
+			function_table = &CG(active_class_entry)->function_table;
+		} else {
+			function_table = CG(function_table);
+		}
+		zend_hash_update(function_table, name, name_len + 1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+		
+		if (!(fn_flags & ZEND_ACC_STATIC)) {
+			CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
+		}
+		
+		efree(lcname);
+	} else if (is_method) {
 		if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
 			zend_op_array *child_op_array, *parent_op_array;
 			if (CG(active_class_entry)->parent
@@ -4181,6 +4276,50 @@
 }
 
 
+static void add_lexical_var(char *name TSRMLS_DC) {
+	zend_op_array *func = CG(active_op_array);
+	if (func->last_lexical_name + 1 > func->size_lexical_name) {
+		func->size_lexical_name += 4;
+		func->lexical_names = erealloc(func->lexical_names, func->size_lexical_name * sizeof(zend_lexical_variable));
+	}
+	func->lexical_names[func->last_lexical_name].name = estrdup(name);
+	func->lexical_names[func->last_lexical_name++].name_len = strlen(name);
+}
+
+
+void zend_do_fetch_lexical_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC)
+{
+	zend_op *opline;
+	znode lval;
+	znode result;
+	
+	if (!CG(active_op_array)->is_lambda) {
+		zend_error(E_COMPILE_WARNING, "Lexical scope variables are not supported in non-lambda functions");
+		return;
+	} else {
+		add_lexical_var (Z_STRVAL(varname->u.constant) TSRMLS_CC);
+	}
+
+	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+	opline->opcode = ZEND_FETCH_W;		/* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
+	opline->result.op_type = IS_VAR;
+	opline->result.u.EA.type = 0;
+	opline->result.u.var = get_temporary_variable(CG(active_op_array));
+	opline->op1 = *varname;
+	SET_UNUSED(opline->op2);
+	opline->op2.u.EA.type = fetch_type;
+	result = opline->result;
+
+	if (varname->op_type == IS_CONST) {
+		zval_copy_ctor(&varname->u.constant);
+	}
+	fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
+
+	zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
+	CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
+}
+
+
 void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC)
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.12.2.25
diff -u -r1.316.2.8.2.12.2.25 zend_compile.h
--- Zend/zend_compile.h	11 Jun 2008 13:18:39 -0000	1.316.2.8.2.12.2.25
+++ Zend/zend_compile.h	17 Jun 2008 14:29:28 -0000
@@ -184,6 +184,11 @@
 	ulong hash_value;
 } zend_compiled_variable;
 
+typedef struct _zend_lexical_variable {
+	char *name;
+	int name_len;
+} zend_lexical_variable;
+
 struct _zend_op_array {
 	/* Common elements */
 	zend_uchar type;
@@ -200,6 +205,9 @@
 
 	zend_bool done_pass_two;
 
+	zend_bool is_lambda;
+	zend_bool is_closure;
+
 	zend_uint *refcount;
 
 	zend_op *opcodes;
@@ -220,6 +228,14 @@
 	/* static variables support */
 	HashTable *static_variables;
 
+	/* support for lexical scope variables in lambda functions */
+	zend_lexical_variable *lexical_names;
+	zend_uint last_lexical_name, size_lexical_name;
+	HashTable *lexical_variables;
+
+	/* object context for closures */
+	zval *closure_object_ctx;
+
 	zend_op *start_op;
 	int backpatch_count;
 
@@ -236,6 +252,12 @@
 };
 
 
+typedef struct _zend_compiled_filename {
+	char *name;
+	zend_uint *lambda_count;
+} zend_compiled_filename;
+
+
 #define ZEND_RETURN_VALUE				0
 #define ZEND_RETURN_REFERENCE			1
 
@@ -375,6 +397,7 @@
 void zend_do_indirect_references(znode *result, znode *num_references, znode *variable TSRMLS_DC);
 void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC);
 void zend_do_fetch_global_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC);
+void zend_do_fetch_lexical_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC);
 
 void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC);
 void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
@@ -415,7 +438,7 @@
 void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 
 int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier);
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC);
+void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_lambda, znode *fn_flags_znode, znode *result TSRMLS_DC);
 void zend_do_end_function_declaration(znode *function_token TSRMLS_DC);
 void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, znode *class_type, znode *varname, zend_bool pass_by_reference TSRMLS_DC);
 int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC);
@@ -614,7 +637,8 @@
 #define ZEND_FETCH_LOCAL			1
 #define ZEND_FETCH_STATIC			2
 #define ZEND_FETCH_STATIC_MEMBER	3
-#define ZEND_FETCH_GLOBAL_LOCK	4
+#define ZEND_FETCH_GLOBAL_LOCK		4
+#define ZEND_FETCH_LEXICAL			5
 
 
 /* class fetches */
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.c,v
retrieving revision 1.716.2.12.2.24.2.30
diff -u -r1.716.2.12.2.24.2.30 zend_execute.c
--- Zend/zend_execute.c	11 Jun 2008 13:18:39 -0000	1.716.2.12.2.24.2.30
+++ Zend/zend_execute.c	17 Jun 2008 14:29:28 -0000
@@ -780,6 +780,15 @@
 		case ZEND_FETCH_GLOBAL_LOCK:
 			return &EG(symbol_table);
 			break;
+		case ZEND_FETCH_LEXICAL:
+			if (!EG(active_op_array)->lexical_variables) {
+				if (!EG(active_symbol_table)) {
+					zend_rebuild_symbol_table(TSRMLS_C);
+				}
+				return EG(active_symbol_table);
+			}
+			return EG(active_op_array)->lexical_variables;
+			break;
 		case ZEND_FETCH_STATIC:
 			if (!EG(active_op_array)->static_variables) {
 				ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
Index: Zend/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.20.2.24.2.42
diff -u -r1.331.2.20.2.24.2.42 zend_execute_API.c
--- Zend/zend_execute_API.c	5 Jun 2008 18:50:29 -0000	1.331.2.20.2.24.2.42
+++ Zend/zend_execute_API.c	17 Jun 2008 14:29:28 -0000
@@ -955,6 +955,12 @@
 		}
 	}
 
+	if (EX(function_state).function->type == ZEND_USER_FUNCTION && EX(function_state).function->op_array.is_lambda &&
+		!EX(function_state).function->op_array.is_closure)
+	{
+		zend_error(E_ERROR, "Cannot call lambda function directly");
+	}
+
 	if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
 		if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
 			zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
Index: Zend/zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.141.2.3.2.7.2.15
diff -u -r1.141.2.3.2.7.2.15 zend_globals.h
--- Zend/zend_globals.h	9 Apr 2008 20:50:58 -0000	1.141.2.3.2.7.2.15
+++ Zend/zend_globals.h	17 Jun 2008 14:29:28 -0000
@@ -82,6 +82,7 @@
 	zend_stack function_call_stack;
 
 	char *compiled_filename;
+	zend_uint *compiled_lambda_count;
 
 	int zend_lineno;
 
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.8.2.21
diff -u -r1.160.2.4.2.8.2.21 zend_language_parser.y
--- Zend/zend_language_parser.y	8 Jun 2008 09:38:47 -0000	1.160.2.4.2.8.2.21
+++ Zend/zend_language_parser.y	17 Jun 2008 14:29:28 -0000
@@ -149,6 +149,7 @@
 %token T_DIR
 %token T_START_NOWDOC
 %token T_END_NOWDOC
+%token T_LEXICAL;
 
 %% /* Rules */
 
@@ -235,6 +236,7 @@
 	|	T_RETURN expr_without_variable ';'	{ zend_do_return(&$2, 0 TSRMLS_CC); }
 	|	T_RETURN variable ';'				{ zend_do_return(&$2, 1 TSRMLS_CC); }
 	|	T_GLOBAL global_var_list ';'
+	|	T_LEXICAL lexical_var_list ';'
 	|	T_STATIC static_var_list ';'
 	|	T_ECHO echo_expr_list ';'
 	|	T_INLINE_HTML			{ zend_do_echo(&$1 TSRMLS_CC); }
@@ -302,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); }
+		T_FUNCTION is_reference T_STRING { $1.u.opline_num = CG(zend_lineno); zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, 0, NULL, NULL TSRMLS_CC); }
 			'(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
 ;
 
@@ -492,6 +494,19 @@
 ;
 
 
+lexical_var_list:
+		lexical_var_list ',' lexical_var	{ zend_do_fetch_lexical_variable(&$3, NULL, ZEND_FETCH_LEXICAL TSRMLS_CC); }
+	|	lexical_var							{ zend_do_fetch_lexical_variable(&$1, NULL, ZEND_FETCH_LEXICAL TSRMLS_CC); }
+;
+
+
+/* variable names have to be known at compile time so $$... or ${...} is not
+ * possible for lexical variables */
+lexical_var:
+		T_VARIABLE			{ $$ = $1; }
+;
+
+
 static_var_list:
 		static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
 	|	static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
@@ -510,7 +525,7 @@
 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); } '('
+	|	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, 0, &$1, NULL TSRMLS_CC); } '('
 			parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
 ;
 
@@ -643,6 +658,8 @@
 	|	T_ARRAY '(' array_pair_list ')' { $$ = $3; }
 	|	'`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
 	|	T_PRINT expr  { zend_do_print(&$$, &$2 TSRMLS_CC); }
+	|	T_FUNCTION is_reference '(' { $1.u.opline_num = CG(zend_lineno); zend_do_begin_function_declaration(&$1, NULL, 0, $2.op_type, 1, NULL, &$$ TSRMLS_CC); }
+			parameter_list ')' '{' inner_statement_list '}' {  zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
 ;
 
 function_call:
Index: Zend/zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.131.2.11.2.13.2.17
diff -u -r1.131.2.11.2.13.2.17 zend_language_scanner.l
--- Zend/zend_language_scanner.l	10 May 2008 09:17:29 -0000	1.131.2.11.2.13.2.17
+++ Zend/zend_language_scanner.l	17 Jun 2008 14:29:30 -0000
@@ -932,6 +932,10 @@
 	return T_GLOBAL;
 }
 
+<ST_IN_SCRIPTING>"lexical" {
+	return T_LEXICAL;
+}
+
 <ST_IN_SCRIPTING>"isset" {
 	return T_ISSET;
 }
Index: Zend/zend_language_scanner_defs.h
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner_defs.h,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 zend_language_scanner_defs.h
--- Zend/zend_language_scanner_defs.h	10 Apr 2008 19:19:04 -0000	1.1.2.8
+++ Zend/zend_language_scanner_defs.h	17 Jun 2008 14:29:30 -0000
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5.dev on Thu Apr 10 20:01:41 2008 */
+/* Generated by re2c 0.13.5 on Mon Jun 16 16:29:03 2008 */
 #line 3 "Zend/zend_language_scanner_defs.h"
 
 enum YYCONDTYPE {
Index: Zend/zend_list.c
===================================================================
RCS file: /repository/ZendEngine2/zend_list.c,v
retrieving revision 1.66.2.1.2.1.2.1
diff -u -r1.66.2.1.2.1.2.1 zend_list.c
--- Zend/zend_list.c	31 Dec 2007 07:17:04 -0000	1.66.2.1.2.1.2.1
+++ Zend/zend_list.c	17 Jun 2008 14:29:31 -0000
@@ -27,6 +27,7 @@
 #include "zend_globals.h"
 
 ZEND_API int le_index_ptr;
+ZEND_API int le_lambda_func;
 
 /* true global */
 static HashTable list_destructors;
@@ -365,6 +366,15 @@
 	}
 }
 
+
+ZEND_API void zend_lambda_func_resource_dtor (zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+	zend_function *func = (zend_function *)rsrc->ptr;
+	if (!func) return;
+	destroy_zend_function(func TSRMLS_CC);
+	efree (func);
+}
+
 /*
  * Local variables:
  * tab-width: 4
Index: Zend/zend_list.h
===================================================================
RCS file: /repository/ZendEngine2/zend_list.h,v
retrieving revision 1.48.2.1.2.1.2.1
diff -u -r1.48.2.1.2.1.2.1 zend_list.h
--- Zend/zend_list.h	31 Dec 2007 07:17:04 -0000	1.48.2.1.2.1.2.1
+++ Zend/zend_list.h	17 Jun 2008 14:29:31 -0000
@@ -86,6 +86,9 @@
 ZEND_API int zend_fetch_list_dtor_id(char *type_name);
 
 extern ZEND_API int le_index_ptr;  /* list entry type for index pointers */
+extern ZEND_API int le_lambda_func;  /* list entry type for lambda functions */
+
+ZEND_API void zend_lambda_func_resource_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
 
 #define ZEND_VERIFY_RESOURCE(rsrc)		\
 	if (!rsrc) {						\
Index: Zend/zend_opcode.c
===================================================================
RCS file: /repository/ZendEngine2/zend_opcode.c,v
retrieving revision 1.110.2.6.2.3.2.8
diff -u -r1.110.2.6.2.3.2.8 zend_opcode.c
--- Zend/zend_opcode.c	7 May 2008 12:04:37 -0000	1.110.2.6.2.3.2.8
+++ Zend/zend_opcode.c	17 Jun 2008 14:29:31 -0000
@@ -78,6 +78,9 @@
 	op_array->doc_comment = NULL;
 	op_array->doc_comment_len = 0;
 
+	op_array->is_lambda = 0;
+	op_array->is_closure = 0;
+
 	op_array->arg_info = NULL;
 	op_array->num_args = 0;
 	op_array->required_num_args = 0;
@@ -90,6 +93,11 @@
 	op_array->current_brk_cont = -1;
 
 	op_array->static_variables = NULL;
+	op_array->size_lexical_name = 0;
+	op_array->last_lexical_name = 0;
+	op_array->lexical_names = NULL;
+	op_array->lexical_variables = NULL;
+	op_array->closure_object_ctx = NULL;
 	op_array->last_try_catch = 0;
 
 	op_array->return_reference = 0;
@@ -224,6 +232,16 @@
 	zend_op *end = op_array->opcodes+op_array->last;
 	zend_uint i;
 
+	if (op_array->lexical_variables) {
+		zend_hash_destroy(op_array->lexical_variables);
+		FREE_HASHTABLE(op_array->lexical_variables);
+	}
+
+	if (op_array->closure_object_ctx) {
+		zval_dtor(op_array->closure_object_ctx);
+		efree(op_array->closure_object_ctx);
+	}
+
 	if (op_array->static_variables) {
 		zend_hash_destroy(op_array->static_variables);
 		FREE_HASHTABLE(op_array->static_variables);
@@ -235,6 +253,15 @@
 
 	efree(op_array->refcount);
 
+	if (op_array->lexical_names) {
+		for (i = 0; i < op_array->last_lexical_name; i++) {
+			if (op_array->lexical_names[i].name) {
+				efree(op_array->lexical_names[i].name);
+			}
+		}
+		efree(op_array->lexical_names);
+	}
+
 	if (op_array->vars) {
 		i = op_array->last_var;
 		while (i > 0) {
Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.58
diff -u -r1.59.2.29.2.48.2.58 zend_vm_def.h
--- Zend/zend_vm_def.h	11 Jun 2008 13:18:39 -0000	1.59.2.29.2.48.2.58
+++ Zend/zend_vm_def.h	17 Jun 2008 14:29:32 -0000
@@ -971,6 +971,7 @@
 			}
 		}
 		switch (opline->op2.u.EA.type) {
+			case ZEND_FETCH_LEXICAL:
 			case ZEND_FETCH_GLOBAL:
 				if (OP1_TYPE != IS_TMP_VAR) {
 					FREE_OP1();
@@ -1887,6 +1888,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -1970,6 +1975,11 @@
 		if (OP2_TYPE != IS_CONST) {
 			FREE_OP2();
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -2019,6 +2029,7 @@
 	char *function_name_strval, *lcname;
 	int function_name_strlen;
 	zend_free_op free_op2;
+	zend_function *lambda_func;
 
 	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
@@ -2030,26 +2041,51 @@
 		function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
 		if (Z_TYPE_P(function_name) != IS_STRING) {
-			zend_error_noreturn(E_ERROR, "Function name must be a string");
-		}
-		function_name_strval = Z_STRVAL_P(function_name);
-		function_name_strlen = Z_STRLEN_P(function_name);
-		if (function_name_strval[0] == ':' &&
-		    function_name_strval[1] == ':') {
-
-		    function_name_strlen -= 2;
-			lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			if (Z_TYPE_P(function_name) != IS_RESOURCE) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+			} else {
+				lambda_func = (zend_function *) zend_fetch_resource (&function_name TSRMLS_CC, -1, NULL, NULL, 1, le_lambda_func);
+				if (!lambda_func) {
+					zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+				}
+				EX(fbc) = lambda_func;
+			}
 		} else {
-			lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
-		}
-		if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
-			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			function_name_strval = Z_STRVAL_P(function_name);
+			function_name_strlen = Z_STRLEN_P(function_name);
+			if (function_name_strval[0] == ':' &&
+				function_name_strval[1] == ':') {
+	
+				function_name_strlen -= 2;
+				lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			} else {
+				lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+			}
+			if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+			efree(lcname);
 		}
-		efree(lcname);
 		FREE_OP2();
+
+		if (EX(fbc)->type == ZEND_USER_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	}
 
-	EX(object) = NULL;
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_closure) {
+		EX(called_scope) = EX(fbc)->op_array.scope;
+		if (EX(fbc)->op_array.closure_object_ctx) {
+			EX(object) = EX(fbc)->op_array.closure_object_ctx;
+			Z_ADDREF_P(EX(object));
+			EX(called_scope) = Z_OBJCE_P(EX(object));
+		} else {
+			EX(object) = NULL;
+		}
+	} else {
+		EX(object) = NULL;
+	}
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -2068,6 +2104,10 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
 		}
 	}
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+		EX(fbc) = NULL;
+		zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+	}
 
 	EX(object) = NULL;
 	ZEND_VM_NEXT_OPCODE();
@@ -2364,6 +2404,11 @@
 	if (zend_hash_quick_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, Z_LVAL(opline->op2.u.constant), (void **) &EX(function_state).function)==FAILURE) {
 		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
 	}
+	if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION && EX(function_state).function->op_array.is_lambda &&
+		!EX(function_state).function->op_array.is_closure)
+	{
+		zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+	}
 	EX(object) = NULL;
 
 	FREE_OP1();
@@ -4328,3 +4373,93 @@
 }
 
 ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
+
+ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNC, CONST, CONST|UNUSED)
+{
+	zend_op *opline = EX(opline);
+	zend_free_op free_op1, free_op2;
+	zval *func_name = GET_OP1_ZVAL_PTR(BP_VAR_R);
+	zend_function *func;
+	zend_function *closure;
+	zend_uint i;
+	int ret;
+
+	long hval = zend_hash_func(Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1);
+
+	if (OP2_TYPE == IS_CONST) {
+		zend_class_entry *ce;
+		ce = zend_fetch_class(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), opline->extended_value TSRMLS_CC);
+		if (!ce) {
+			ret = FAILURE;
+		} else {
+			ret = zend_hash_quick_find(&ce->function_table, Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1, hval, (void **) &func);
+		}
+		FREE_OP2();
+	} else {
+		ret = zend_hash_quick_find(EG(function_table), Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1, hval, (void **) &func);
+	}
+
+	if (ret != SUCCESS) {
+		zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+		ZVAL_NULL(&EX_T(opline->result.u.var).tmp_var);
+	} else {
+		if (func->type != ZEND_USER_FUNCTION) {
+			zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+			ZVAL_NULL(&EX_T(opline->result.u.var).tmp_var);
+		} else {
+			if (!EG(active_symbol_table)) {
+				zend_rebuild_symbol_table(TSRMLS_C);
+			}
+
+			closure = (zend_function *)emalloc(sizeof *closure);
+			*closure = *func;
+			/* copy static variables to make sure each closure has its own */
+			if (closure->op_array.static_variables) {
+				HashTable *static_variables = closure->op_array.static_variables;
+				zval *tmp_zval;
+	
+				ALLOC_HASHTABLE(closure->op_array.static_variables);
+				zend_hash_init(closure->op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
+				zend_hash_copy(closure->op_array.static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
+			}
+			/* initialize lexical variables */
+			if (closure->op_array.last_lexical_name > 0) {
+				if (!closure->op_array.lexical_variables) {
+					ALLOC_HASHTABLE(closure->op_array.lexical_variables);
+					zend_hash_init(closure->op_array.lexical_variables, closure->op_array.last_lexical_name, NULL, ZVAL_PTR_DTOR, 0);
+				}
+				// create references
+				for (i = 0; i < closure->op_array.last_lexical_name; i++) {
+					zval *ref_var, dummy, **local_var;
+					zend_lexical_variable *var = &closure->op_array.lexical_names[i];
+					if (zend_hash_find(EG(active_symbol_table), var->name, var->name_len+1, (void **) &local_var) == FAILURE) {
+						zval *new_zval = &EG(uninitialized_zval);
+
+						Z_ADDREF_P(new_zval);
+						zend_hash_update(EG(active_symbol_table), var->name, var->name_len+1, &new_zval, sizeof(zval *), (void **) &local_var);
+					}
+					ref_var = &dummy;
+					zend_assign_to_variable_reference (&ref_var, local_var TSRMLS_CC);
+					zend_hash_update(closure->op_array.lexical_variables, var->name, var->name_len+1, &ref_var, sizeof(zval *), NULL);
+				}
+			}
+
+			if (closure->op_array.scope && EG(This)) {
+				zval *this_ptr;
+				ALLOC_ZVAL(this_ptr);
+				INIT_PZVAL_COPY(this_ptr, EG(This));
+				zval_copy_ctor(this_ptr);
+				closure->op_array.closure_object_ctx = this_ptr;
+			}
+
+			closure->op_array.is_closure = 1;
+
+			(*func->op_array.refcount)++;
+
+			ZEND_REGISTER_RESOURCE(&EX_T(opline->result.u.var).tmp_var, closure, le_lambda_func);
+		}
+	}
+
+	FREE_OP1();
+	ZEND_VM_NEXT_OPCODE();
+}
Index: Zend/zend_vm_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.62.2.30.2.49.2.58
diff -u -r1.62.2.30.2.49.2.58 zend_vm_execute.h
--- Zend/zend_vm_execute.h	11 Jun 2008 13:18:39 -0000	1.62.2.30.2.49.2.58
+++ Zend/zend_vm_execute.h	17 Jun 2008 14:29:40 -0000
@@ -737,6 +737,7 @@
 	char *function_name_strval, *lcname;
 	int function_name_strlen;
 
+	zend_function *lambda_func;
 
 	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
@@ -748,26 +749,50 @@
 		function_name = &opline->op2.u.constant;
 
 		if (Z_TYPE_P(function_name) != IS_STRING) {
-			zend_error_noreturn(E_ERROR, "Function name must be a string");
-		}
-		function_name_strval = Z_STRVAL_P(function_name);
-		function_name_strlen = Z_STRLEN_P(function_name);
-		if (function_name_strval[0] == ':' &&
-		    function_name_strval[1] == ':') {
-
-		    function_name_strlen -= 2;
-			lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			if (Z_TYPE_P(function_name) != IS_RESOURCE) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+			} else {
+				lambda_func = (zend_function *) zend_fetch_resource (&function_name TSRMLS_CC, -1, NULL, NULL, 1, le_lambda_func);
+				if (!lambda_func) {
+					zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+				}
+				EX(fbc) = lambda_func;
+			}
 		} else {
-			lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
-		}
-		if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
-			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			function_name_strval = Z_STRVAL_P(function_name);
+			function_name_strlen = Z_STRLEN_P(function_name);
+			if (function_name_strval[0] == ':' &&
+				function_name_strval[1] == ':') {
+
+				function_name_strlen -= 2;
+				lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			} else {
+				lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+			}
+			if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+			efree(lcname);
 		}
-		efree(lcname);
 
+		if (EX(fbc)->type == ZEND_USER_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	}
 
-	EX(object) = NULL;
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_closure) {
+		EX(called_scope) = EX(fbc)->op_array.scope;
+		if (EX(fbc)->op_array.closure_object_ctx) {
+			EX(object) = EX(fbc)->op_array.closure_object_ctx;
+			Z_ADDREF_P(EX(object));
+			EX(called_scope) = Z_OBJCE_P(EX(object));
+		} else {
+			EX(object) = NULL;
+		}
+	} else {
+		EX(object) = NULL;
+	}
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -786,6 +811,10 @@
 			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL(opline->op2.u.constant));
 		}
 	}
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+		EX(fbc) = NULL;
+		zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+	}
 
 	EX(object) = NULL;
 	ZEND_VM_NEXT_OPCODE();
@@ -925,6 +954,7 @@
 	char *function_name_strval, *lcname;
 	int function_name_strlen;
 	zend_free_op free_op2;
+	zend_function *lambda_func;
 
 	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
@@ -936,26 +966,51 @@
 		function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
 		if (Z_TYPE_P(function_name) != IS_STRING) {
-			zend_error_noreturn(E_ERROR, "Function name must be a string");
-		}
-		function_name_strval = Z_STRVAL_P(function_name);
-		function_name_strlen = Z_STRLEN_P(function_name);
-		if (function_name_strval[0] == ':' &&
-		    function_name_strval[1] == ':') {
-
-		    function_name_strlen -= 2;
-			lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			if (Z_TYPE_P(function_name) != IS_RESOURCE) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+			} else {
+				lambda_func = (zend_function *) zend_fetch_resource (&function_name TSRMLS_CC, -1, NULL, NULL, 1, le_lambda_func);
+				if (!lambda_func) {
+					zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+				}
+				EX(fbc) = lambda_func;
+			}
 		} else {
-			lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
-		}
-		if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
-			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			function_name_strval = Z_STRVAL_P(function_name);
+			function_name_strlen = Z_STRLEN_P(function_name);
+			if (function_name_strval[0] == ':' &&
+				function_name_strval[1] == ':') {
+
+				function_name_strlen -= 2;
+				lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			} else {
+				lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+			}
+			if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+			efree(lcname);
 		}
-		efree(lcname);
 		zval_dtor(free_op2.var);
+
+		if (EX(fbc)->type == ZEND_USER_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	}
 
-	EX(object) = NULL;
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_closure) {
+		EX(called_scope) = EX(fbc)->op_array.scope;
+		if (EX(fbc)->op_array.closure_object_ctx) {
+			EX(object) = EX(fbc)->op_array.closure_object_ctx;
+			Z_ADDREF_P(EX(object));
+			EX(called_scope) = Z_OBJCE_P(EX(object));
+		} else {
+			EX(object) = NULL;
+		}
+	} else {
+		EX(object) = NULL;
+	}
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -1021,6 +1076,7 @@
 	char *function_name_strval, *lcname;
 	int function_name_strlen;
 	zend_free_op free_op2;
+	zend_function *lambda_func;
 
 	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
@@ -1032,26 +1088,51 @@
 		function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
 		if (Z_TYPE_P(function_name) != IS_STRING) {
-			zend_error_noreturn(E_ERROR, "Function name must be a string");
-		}
-		function_name_strval = Z_STRVAL_P(function_name);
-		function_name_strlen = Z_STRLEN_P(function_name);
-		if (function_name_strval[0] == ':' &&
-		    function_name_strval[1] == ':') {
-
-		    function_name_strlen -= 2;
-			lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			if (Z_TYPE_P(function_name) != IS_RESOURCE) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+			} else {
+				lambda_func = (zend_function *) zend_fetch_resource (&function_name TSRMLS_CC, -1, NULL, NULL, 1, le_lambda_func);
+				if (!lambda_func) {
+					zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+				}
+				EX(fbc) = lambda_func;
+			}
 		} else {
-			lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
-		}
-		if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
-			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			function_name_strval = Z_STRVAL_P(function_name);
+			function_name_strlen = Z_STRLEN_P(function_name);
+			if (function_name_strval[0] == ':' &&
+				function_name_strval[1] == ':') {
+
+				function_name_strlen -= 2;
+				lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			} else {
+				lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+			}
+			if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+			efree(lcname);
 		}
-		efree(lcname);
 		if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
+
+		if (EX(fbc)->type == ZEND_USER_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	}
 
-	EX(object) = NULL;
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_closure) {
+		EX(called_scope) = EX(fbc)->op_array.scope;
+		if (EX(fbc)->op_array.closure_object_ctx) {
+			EX(object) = EX(fbc)->op_array.closure_object_ctx;
+			Z_ADDREF_P(EX(object));
+			EX(called_scope) = Z_OBJCE_P(EX(object));
+		} else {
+			EX(object) = NULL;
+		}
+	} else {
+		EX(object) = NULL;
+	}
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -1145,6 +1226,7 @@
 	char *function_name_strval, *lcname;
 	int function_name_strlen;
 
+	zend_function *lambda_func;
 
 	zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
@@ -1156,26 +1238,50 @@
 		function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
 
 		if (Z_TYPE_P(function_name) != IS_STRING) {
-			zend_error_noreturn(E_ERROR, "Function name must be a string");
-		}
-		function_name_strval = Z_STRVAL_P(function_name);
-		function_name_strlen = Z_STRLEN_P(function_name);
-		if (function_name_strval[0] == ':' &&
-		    function_name_strval[1] == ':') {
-
-		    function_name_strlen -= 2;
-			lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			if (Z_TYPE_P(function_name) != IS_RESOURCE) {
+				zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+			} else {
+				lambda_func = (zend_function *) zend_fetch_resource (&function_name TSRMLS_CC, -1, NULL, NULL, 1, le_lambda_func);
+				if (!lambda_func) {
+					zend_error_noreturn(E_ERROR, "Function name must be a string or a lambda function resource");
+				}
+				EX(fbc) = lambda_func;
+			}
 		} else {
-			lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
-		}
-		if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
-			zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			function_name_strval = Z_STRVAL_P(function_name);
+			function_name_strlen = Z_STRLEN_P(function_name);
+			if (function_name_strval[0] == ':' &&
+				function_name_strval[1] == ':') {
+
+				function_name_strlen -= 2;
+				lcname = zend_str_tolower_dup(function_name_strval + 2, function_name_strlen);
+			} else {
+				lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
+			}
+			if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE) {
+				zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+			}
+			efree(lcname);
 		}
-		efree(lcname);
 
+		if (EX(fbc)->type == ZEND_USER_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	}
 
-	EX(object) = NULL;
+	if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_closure) {
+		EX(called_scope) = EX(fbc)->op_array.scope;
+		if (EX(fbc)->op_array.closure_object_ctx) {
+			EX(object) = EX(fbc)->op_array.closure_object_ctx;
+			Z_ADDREF_P(EX(object));
+			EX(called_scope) = Z_OBJCE_P(EX(object));
+		} else {
+			EX(object) = NULL;
+		}
+	} else {
+		EX(object) = NULL;
+	}
 	ZEND_VM_NEXT_OPCODE();
 }
 
@@ -1339,6 +1445,7 @@
 			}
 		}
 		switch (opline->op2.u.EA.type) {
+			case ZEND_FETCH_LEXICAL:
 			case ZEND_FETCH_GLOBAL:
 				if (IS_CONST != IS_TMP_VAR) {
 
@@ -1522,6 +1629,11 @@
 	if (zend_hash_quick_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, Z_LVAL(opline->op2.u.constant), (void **) &EX(function_state).function)==FAILURE) {
 		zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
 	}
+	if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION && EX(function_state).function->op_array.is_lambda &&
+		!EX(function_state).function->op_array.is_closure)
+	{
+		zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+	}
 	EX(object) = NULL;
 
 	return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -2603,6 +2715,11 @@
 		if (IS_CONST != IS_CONST) {
 
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -2875,6 +2992,95 @@
 	ZEND_VM_NEXT_OPCODE();
 }
 
+
+static int ZEND_FASTCALL  ZEND_DECLARE_LAMBDA_FUNC_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+
+	zval *func_name = &opline->op1.u.constant;
+	zend_function *func;
+	zend_function *closure;
+	zend_uint i;
+	int ret;
+
+	long hval = zend_hash_func(Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1);
+
+	if (IS_CONST == IS_CONST) {
+		zend_class_entry *ce;
+		ce = zend_fetch_class(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), opline->extended_value TSRMLS_CC);
+		if (!ce) {
+			ret = FAILURE;
+		} else {
+			ret = zend_hash_quick_find(&ce->function_table, Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1, hval, (void **) &func);
+		}
+
+	} else {
+		ret = zend_hash_quick_find(EG(function_table), Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1, hval, (void **) &func);
+	}
+
+	if (ret != SUCCESS) {
+		zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+		ZVAL_NULL(&EX_T(opline->result.u.var).tmp_var);
+	} else {
+		if (func->type != ZEND_USER_FUNCTION) {
+			zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+			ZVAL_NULL(&EX_T(opline->result.u.var).tmp_var);
+		} else {
+			if (!EG(active_symbol_table)) {
+				zend_rebuild_symbol_table(TSRMLS_C);
+			}
+
+			closure = (zend_function *)emalloc(sizeof *closure);
+			*closure = *func;
+			/* copy static variables to make sure each closure has its own */
+			if (closure->op_array.static_variables) {
+				HashTable *static_variables = closure->op_array.static_variables;
+				zval *tmp_zval;
+
+				ALLOC_HASHTABLE(closure->op_array.static_variables);
+				zend_hash_init(closure->op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
+				zend_hash_copy(closure->op_array.static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
+			}
+			/* initialize lexical variables */
+			if (closure->op_array.last_lexical_name > 0) {
+				if (!closure->op_array.lexical_variables) {
+					ALLOC_HASHTABLE(closure->op_array.lexical_variables);
+					zend_hash_init(closure->op_array.lexical_variables, closure->op_array.last_lexical_name, NULL, ZVAL_PTR_DTOR, 0);
+				}
+				// create references
+				for (i = 0; i < closure->op_array.last_lexical_name; i++) {
+					zval *ref_var, dummy, **local_var;
+					zend_lexical_variable *var = &closure->op_array.lexical_names[i];
+					if (zend_hash_find(EG(active_symbol_table), var->name, var->name_len+1, (void **) &local_var) == FAILURE) {
+						zval *new_zval = &EG(uninitialized_zval);
+
+						Z_ADDREF_P(new_zval);
+						zend_hash_update(EG(active_symbol_table), var->name, var->name_len+1, &new_zval, sizeof(zval *), (void **) &local_var);
+					}
+					ref_var = &dummy;
+					zend_assign_to_variable_reference (&ref_var, local_var TSRMLS_CC);
+					zend_hash_update(closure->op_array.lexical_variables, var->name, var->name_len+1, &ref_var, sizeof(zval *), NULL);
+				}
+			}
+
+			if (closure->op_array.scope && EG(This)) {
+				zval *this_ptr;
+				ALLOC_ZVAL(this_ptr);
+				INIT_PZVAL_COPY(this_ptr, EG(This));
+				zval_copy_ctor(this_ptr);
+				closure->op_array.closure_object_ctx = this_ptr;
+			}
+
+			closure->op_array.is_closure = 1;
+
+			(*func->op_array.refcount)++;
+
+			ZEND_REGISTER_RESOURCE(&EX_T(opline->result.u.var).tmp_var, closure, le_lambda_func);
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
 static int ZEND_FASTCALL  ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -3176,6 +3382,11 @@
 		if (IS_TMP_VAR != IS_CONST) {
 			zval_dtor(free_op2.var);
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -3644,6 +3855,11 @@
 		if (IS_VAR != IS_CONST) {
 			if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -3868,6 +4084,11 @@
 		if (IS_UNUSED != IS_CONST) {
 
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -4003,6 +4224,94 @@
 	}
 }
 
+static int ZEND_FASTCALL  ZEND_DECLARE_LAMBDA_FUNC_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	zend_op *opline = EX(opline);
+
+	zval *func_name = &opline->op1.u.constant;
+	zend_function *func;
+	zend_function *closure;
+	zend_uint i;
+	int ret;
+
+	long hval = zend_hash_func(Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1);
+
+	if (IS_UNUSED == IS_CONST) {
+		zend_class_entry *ce;
+		ce = zend_fetch_class(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), opline->extended_value TSRMLS_CC);
+		if (!ce) {
+			ret = FAILURE;
+		} else {
+			ret = zend_hash_quick_find(&ce->function_table, Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1, hval, (void **) &func);
+		}
+
+	} else {
+		ret = zend_hash_quick_find(EG(function_table), Z_STRVAL_P(func_name), Z_STRLEN_P(func_name) + 1, hval, (void **) &func);
+	}
+
+	if (ret != SUCCESS) {
+		zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+		ZVAL_NULL(&EX_T(opline->result.u.var).tmp_var);
+	} else {
+		if (func->type != ZEND_USER_FUNCTION) {
+			zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
+			ZVAL_NULL(&EX_T(opline->result.u.var).tmp_var);
+		} else {
+			if (!EG(active_symbol_table)) {
+				zend_rebuild_symbol_table(TSRMLS_C);
+			}
+
+			closure = (zend_function *)emalloc(sizeof *closure);
+			*closure = *func;
+			/* copy static variables to make sure each closure has its own */
+			if (closure->op_array.static_variables) {
+				HashTable *static_variables = closure->op_array.static_variables;
+				zval *tmp_zval;
+
+				ALLOC_HASHTABLE(closure->op_array.static_variables);
+				zend_hash_init(closure->op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
+				zend_hash_copy(closure->op_array.static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
+			}
+			/* initialize lexical variables */
+			if (closure->op_array.last_lexical_name > 0) {
+				if (!closure->op_array.lexical_variables) {
+					ALLOC_HASHTABLE(closure->op_array.lexical_variables);
+					zend_hash_init(closure->op_array.lexical_variables, closure->op_array.last_lexical_name, NULL, ZVAL_PTR_DTOR, 0);
+				}
+				// create references
+				for (i = 0; i < closure->op_array.last_lexical_name; i++) {
+					zval *ref_var, dummy, **local_var;
+					zend_lexical_variable *var = &closure->op_array.lexical_names[i];
+					if (zend_hash_find(EG(active_symbol_table), var->name, var->name_len+1, (void **) &local_var) == FAILURE) {
+						zval *new_zval = &EG(uninitialized_zval);
+
+						Z_ADDREF_P(new_zval);
+						zend_hash_update(EG(active_symbol_table), var->name, var->name_len+1, &new_zval, sizeof(zval *), (void **) &local_var);
+					}
+					ref_var = &dummy;
+					zend_assign_to_variable_reference (&ref_var, local_var TSRMLS_CC);
+					zend_hash_update(closure->op_array.lexical_variables, var->name, var->name_len+1, &ref_var, sizeof(zval *), NULL);
+				}
+			}
+
+			if (closure->op_array.scope && EG(This)) {
+				zval *this_ptr;
+				ALLOC_ZVAL(this_ptr);
+				INIT_PZVAL_COPY(this_ptr, EG(This));
+				zval_copy_ctor(this_ptr);
+				closure->op_array.closure_object_ctx = this_ptr;
+			}
+
+			closure->op_array.is_closure = 1;
+
+			(*func->op_array.refcount)++;
+
+			ZEND_REGISTER_RESOURCE(&EX_T(opline->result.u.var).tmp_var, closure, le_lambda_func);
+		}
+	}
+
+	ZEND_VM_NEXT_OPCODE();
+}
 static int ZEND_FASTCALL  ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	zend_op *opline = EX(opline);
@@ -4304,6 +4613,11 @@
 		if (IS_CV != IS_CONST) {
 
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -4569,6 +4883,7 @@
 			}
 		}
 		switch (opline->op2.u.EA.type) {
+			case ZEND_FETCH_LEXICAL:
 			case ZEND_FETCH_GLOBAL:
 				if (IS_TMP_VAR != IS_TMP_VAR) {
 					zval_dtor(free_op1.var);
@@ -5851,6 +6166,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -6306,6 +6625,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -6763,6 +7086,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -7312,6 +7639,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -7717,6 +8048,7 @@
 			}
 		}
 		switch (opline->op2.u.EA.type) {
+			case ZEND_FETCH_LEXICAL:
 			case ZEND_FETCH_GLOBAL:
 				if (IS_VAR != IS_TMP_VAR) {
 					if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
@@ -10160,6 +10492,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -10242,6 +10578,11 @@
 		if (IS_CONST != IS_CONST) {
 
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -11991,6 +12332,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -12074,6 +12419,11 @@
 		if (IS_TMP_VAR != IS_CONST) {
 			zval_dtor(free_op2.var);
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -13793,6 +14143,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -13876,6 +14230,11 @@
 		if (IS_VAR != IS_CONST) {
 			if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -14781,6 +15140,11 @@
 		if (IS_UNUSED != IS_CONST) {
 
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -16202,6 +16566,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -16284,6 +16652,11 @@
 		if (IS_CV != IS_CONST) {
 
 		}
+
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			EX(fbc) = NULL;
+			zend_error(E_ERROR, "Cannot call lambda function directly");
+		}
 	} else {
 		if(!ce->constructor) {
 			zend_error_noreturn(E_ERROR, "Can not call constructor");
@@ -17514,6 +17887,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -18604,6 +18981,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -19623,6 +20004,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -20913,6 +21298,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -21461,6 +21850,7 @@
 			}
 		}
 		switch (opline->op2.u.EA.type) {
+			case ZEND_FETCH_LEXICAL:
 			case ZEND_FETCH_GLOBAL:
 				if (IS_CV != IS_TMP_VAR) {
 
@@ -23734,6 +24124,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -25382,6 +25776,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -27072,6 +27470,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -29268,6 +29670,10 @@
 		if (!EX(fbc)) {
 			zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
 		}
+		if (EX(fbc)->type != ZEND_INTERNAL_FUNCTION && EX(fbc)->op_array.is_lambda && !EX(fbc)->op_array.is_closure) {
+			zend_error_noreturn(E_ERROR, "Cannot call lambda function directly");
+			EX(fbc) = NULL;
+		}
 	} else {
 		zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
 	}
@@ -33508,6 +33914,31 @@
   	ZEND_JMP_SET_SPEC_CV_HANDLER,
   	ZEND_JMP_SET_SPEC_CV_HANDLER,
   	ZEND_JMP_SET_SPEC_CV_HANDLER,
+  	ZEND_DECLARE_LAMBDA_FUNC_SPEC_CONST_CONST_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_DECLARE_LAMBDA_FUNC_SPEC_CONST_UNUSED_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_vm_opcodes.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_opcodes.h,v
retrieving revision 1.42.2.17.2.1.2.6
diff -u -r1.42.2.17.2.1.2.6 zend_vm_opcodes.h
--- Zend/zend_vm_opcodes.h	28 Mar 2008 14:35:01 -0000	1.42.2.17.2.1.2.6
+++ Zend/zend_vm_opcodes.h	17 Jun 2008 14:29:40 -0000
@@ -152,3 +152,4 @@
 #define ZEND_HANDLE_EXCEPTION                149
 #define ZEND_USER_OPCODE                     150
 #define ZEND_JMP_SET                         152
+#define ZEND_DECLARE_LAMBDA_FUNC             153
Index: main/main.c
===================================================================
RCS file: /repository/php-src/main/main.c,v
retrieving revision 1.640.2.23.2.57.2.22
diff -u -r1.640.2.23.2.57.2.22 main.c
--- main/main.c	21 May 2008 15:55:31 -0000	1.640.2.23.2.57.2.22
+++ main/main.c	17 Jun 2008 14:29:46 -0000
@@ -1778,6 +1778,7 @@
 #endif
 
 	le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
+	le_lambda_func = zend_register_list_destructors_ex(zend_lambda_func_resource_dtor, NULL, "lambda function", 0);
 
 	/* Register constants */
 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
