xp-framework / compiler

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

Compiler error: Call to undefined method lang\ast\emit\PHP72::emitoperator() #74

Closed thekid closed 5 years ago

thekid commented 5 years ago

This occured when parsing a hack-style lambda:

$authenticate= newinstance(Filter::class, [], [
  'filter' => ($request, $response, $invocation) ==> {
    // ...
  }
]);

I'd expect this to yield a parse error!

thekid commented 5 years ago

The compiler thinks this is an offset expression - e.g. $str{0}, where > gets interpreted as the expression, and {return} (the value of the global constant "return") as the offset:

image

thekid commented 5 years ago

Possible fix, but would need to be applied everywhere:

diff --git a/src/main/php/lang/ast/syntax/PHP.class.php b/src/main/php/lang/ast/syntax/PHP.class.php
index 2afea6b..76752f0 100755
--- a/src/main/php/lang/ast/syntax/PHP.class.php
+++ b/src/main/php/lang/ast/syntax/PHP.class.php
@@ -177,9 +177,12 @@ class PHP extends Language {
     });

     $this->infix('{', 80, function($parse, $token, $left) {
-      $expr= $this->expression($parse, 0);
-      $parse->expecting('}', 'offset');
-      return new OffsetExpression($left, $expr, $token->line);
+      if ($left instanceof Node) {
+        $expr= $this->expression($parse, 0);
+        $parse->expecting('}', 'offset');
+        return new OffsetExpression($left, $expr, $token->line);
+      }
+      $parse->raise('Invalid left-hand side of an offset expression '.\util\Objects::stringOf($left), 'offset');
     });

     $this->infix('?', 80, function($parse, $token, $left) {
thekid commented 5 years ago

By adding an emitOperator() method, we at least see the compile errors:

diff --git a/src/main/php/lang/ast/emit/PHP.class.php b/src/main/php/lang/ast/emit/PHP.class.php
index 6632269..1f15eb9 100755
--- a/src/main/php/lang/ast/emit/PHP.class.php
+++ b/src/main/php/lang/ast/emit/PHP.class.php
@@ -85,6 +85,10 @@ abstract class PHP extends Emitter {
     $result->out->write($name);
   }

+  protected function emitOperator($result, $operator) {
+    $result->out->write($operator->value);
+  }
+
   protected function emitEcho($result, $echo) {
     $result->out->write('echo ');
     $s= sizeof($echo->expressions) - 1;

Still not excellent, but at least the root cause is not shadowed.