Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:28474 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 28285 invoked by uid 1010); 20 Mar 2007 00:02:59 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 28268 invoked from network); 20 Mar 2007 00:02:59 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 20 Mar 2007 00:02:59 -0000 Authentication-Results: pb1.pair.com header.from=wez@omniti.com; sender-id=pass; domainkeys=good Authentication-Results: pb1.pair.com smtp.mail=wez@omniti.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain omniti.com designates 66.225.209.50 as permitted sender) DomainKey-Status: good X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: wez@omniti.com X-Host-Fingerprint: 66.225.209.50 mail.omniti.com Linux 2.5 (sometimes 2.4) (4) Received: from [66.225.209.50] ([66.225.209.50:38342] helo=mail.omniti.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 2E/71-01604-FA42FF54 for ; Mon, 19 Mar 2007 19:02:57 -0500 X-DKIM: Ecelerity dkim_sign implementing draft-ietf-dkim-base-00 DKIM-Signature: a=rsa-sha1; d=omniti.com; s=test; t=1174348972; c=simple/simple; q=dns; i=@omniti.com; h=From; b=aBV10vuEFw2xsKLinj4VU04ZbbcNljCaPYJE+AsdGjSDf8Uy9AzhZJXKbN230cny M/ODQuaRir1PEb1VBE6OrSuQfy7hR9Sz3qxUigde7hmOsZjjrLrmXnTzL3Ou0sf3 X-DomainKeys: Ecelerity dk_sign implementing draft-delany-domainkeys-base-01 DomainKey-Signature: q=dns; a=rsa-sha1; c=nofws; s=test; d=omniti.com; h=Authentication-Results:Received:In-Reply-To:References:Mime-Version:Content-Type:Message-Id:Cc:Content-Transfer-Encoding:From:Subject:Date:To:X-Mailer; b=Nf574XZLumY/f22sx4B3GdUdLa6aj/pE5c8wOm/tdH1X8S6jsON/a8EU3Kh61kp2 wHHOYT9RTNLVXMFM1OlEA9kRlvP8HHicFtEUbXp2/kdPGUg9cwKUyiRx4+b3CGUk Authentication-Results: mail.omniti.com smtp.user=wez; auth=pass (LOGIN) Received: from [76.100.30.170] ([76.100.30.170:56627] helo=[192.168.50.4]) by mail.omniti.com (ecelerity 2.1.1.12 r(14453)) with ESMTPSA (cipher=AES128-SHA) id 7E/32-26454-5A42FF54 for ; Mon, 19 Mar 2007 20:02:52 -0400 In-Reply-To: <698DE66518E7CA45812BD18E807866CE185525@us-ex1.zend.net> References: <86478A67-DCA2-4000-9EF0-DA4338E8389B@omniti.com> <45FDF031.4010508@zend.com> <45FE2312.1050506@zend.com> <45FED6D9.8030307@caedmon.net> <45FEDAE5.2010309@zend.com> <45FEE396.7040905@caedmon.net> <0757BDEA-65F5-4123-B647-060DCA84B4B0@omniti.com> <45FEEF52.1060002@zend.com> <1174336464.24632.110.camel@blobule> <45FEF9A5.4050409@zend.com> <1174338801.24632.124.camel@blobule> <45FEFDCE.7050100@zend.com> <1174339527.24632.129.camel@blobule> <45FF01FE.6070504@zend.com> <698DE66518E7CA45812BD18E807866CE185525@us-ex1.zend.net> Mime-Version: 1.0 (Apple Message framework v752.3) Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Message-ID: Cc: "Stas Malyshev" , "Robert Cummings" , "Sean Coates" , Content-Transfer-Encoding: 7bit Date: Mon, 19 Mar 2007 20:02:46 -0400 To: "Andi Gutmans" X-Mailer: Apple Mail (2.752.3) Subject: Re: [PHP-DEV] PATCH: anonymous functions in PHP From: wez@omniti.com (Wez Furlong) I've been thinking about this in the car, and it won't quite work as-is. Here's a contrived example: $funcs = array(); for ($i = 0; $i < 10; $i++) { $funcs[] = function() { return $_SCOPE['i']; }; } Here I'm assuming that $_SCOPE takes a copy of $i during fixup. The problem here is that the function is compiled once, so there is only one place to stash the fixup info for $_SCOPE, which leaves the results of calling any of the functions in $funcs undefined. (Just in case it's not clear, the intention is to create 10 anonymous functions, which return values 0 through 9). There are two ways to solve this, both give the same visible result to the person writing the code, but one is more invasive. The first solution is to have a unique function name generated on each run through the loop. The function name would be an alias (ala FALIAS) to the opcodes, so that there would only be one version of the compiled opcodes. The based on the information from $_SCOPE, copies of the variables from the instantiating scope would be stored along with the oparray, keyed by the unique function name. When the function is called, the name being invoked is used to locate the saved variables, which are then used to pre-populate the local scope for the function. $_SCOPE['i'] would have been transposed to simply $i in the op_array. So, in psuedo code the above would generate a funcs array like: $funcs[0] = "__anon_0"; $funcs[1] = "__anon_1"; and when the engine goes to invoke __anon_0: function __anon_0() { $_LOCALS = get_scope_vars_for('__anon_0'); return $i; } Where the $_LOCALS line represents the prologue in the ZE that sets up the local scope for that function "frame". The second possibility would be to make a first-class callable zval type which stores that information in the return value from the function declaration. The callable type would store a pointer to the op_array as well as a hash table to use to initialize the local scope of the function. Again, this would be created based on the $_SCOPES fixup information, and again, $_SCOPES['i'] would be rewritten as simply $i in the op_array. So the funcs array might look like this is var_dump()'d: 0 => callable('__anon_0', array('i' => 0)), 1 => callable('__anon_0', array('i' => 1)), 2 => callable('__anon_0', array('i' => 2)) Adding a type seems cleaner, but obviously requires more work as the rest of the internals need to understand what to do with it. A third possibility is similar to the second, but a bit less invasive. Create a callable class type to encapsulate that information. The rest of the internals would see $funcs[0] as an object, but the engine would know that calling it will invoke the appropriate function, prepping the local scope as described above. --Wez. On Mar 19, 2007, at 5:59 PM, Andi Gutmans wrote: > We could compile the anonymous function at compile-time but leave > placeholders which need to be "fixed-up" when at run-time the actual > closure is created. For this purpose we could introduce a new magical > variables $_SCOPE["var"] which references the current $var during > fixup > time. > So here's an example: > > $var = php_version(); > $fancyVer = function () { return "PHP $_SCOPE['ver']; }; > > So what this does is compile the "anonymous function" at compile-time, > but when this line is executed (note, this line of code should also be > reached during execution), then we do the fix-up for $_SCOPE > variables. > Regular variables remain what they would in create_function(). Fix-up > time would be faster than compiling the code. > > Thoughts? > Andi