xp-framework / compiler

Compiles future PHP to today's PHP.
19 stars 0 forks source link

Implement first-class callable syntax #114

Closed thekid closed 3 years ago

thekid commented 3 years ago

Examples

// Old code without checks whether any of these are actually callable
$length= function(... $args) { return strlen(...$args); };
$run= function(... $args) use($instance) { return $instance->run(...$args); };
$of= function(... $args) { return Enum::valueOf(...$args); };

// Old code, requires PHP 7.1
$length= Closure::fromCallable('strlen');
$run= Closure::fromCallable([$instance, 'run']);
$of= Closure::fromCallable([Enum::class, 'valueOf']);

// Now possible, works on all PHP versions w/ XP Compiler
$length= strlen(...);
$run= $instance->run(...)
$of= Enum::valueOf(...);

See also

thekid commented 3 years ago

This implementation does not check for and subsequently disallow nullsafe calls as described in the PHP RFC, leaving it up to the runtime engine. This could be added easily (see below), however, it would be a first in the emitter, which doesn't throw errors up until now!

diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index 3a10a60..ba460e9 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -1,5 +1,6 @@
 <?php namespace lang\ast\emit;

+use lang\IllegalStateException;
 use lang\ast\Code;
 use lang\ast\nodes\{InstanceExpression, ScopeExpression, BinaryExpression, Variable, Literal, ArrayLiteral, Block};
 use lang\ast\types\{IsUnion, IsFunction, IsArray, IsMap};
@@ -989,6 +990,10 @@ abstract class PHP extends Emitter {
   }

   protected function emitCallable($result, $callable) {
+    if ($callable->expression->kind === 'nullsafeinstance') {
+      throw new IllegalStateException('Cannot use ?-> with callables');
+    }
+
     $t= $result->temp();
     $result->out->write('fn(...'.$t.') => ');
     $this->emitOne($result, $callable->expression);
thekid commented 3 years ago

This can safely be merged, the vote is at 41:0 in favor of including this and thus very unlikely to fail.

thekid commented 3 years ago

Released in https://github.com/xp-framework/compiler/releases/tag/v6.7.0

thekid commented 3 years ago

Updated https://github.com/xp-framework/compiler/wiki/Implementation-status