public function newType($type, $name)
 {
     if (FALSE === ($p = strrpos($name, "."))) {
         $class = $name;
         $ns = "";
     } else {
         $class = substr($name, $p + 1);
         $ns = "namespace " . strtr(substr($name, 0, $p), ".", "\\") . ";";
     }
     \lang\DynamicClassLoader::instanceFor("test")->setClassBytes($name, sprintf("%s %s %s extends \\lang\\Object { }", $ns, $type, $class));
 }
Пример #2
0
 /**
  * Helper method for defineClass() and defineInterface().
  *
  * @param  string $spec
  * @param  [:var] $declaration
  * @param  var $def
  * @return lang.XPClass
  */
 public static function defineType($spec, $declaration, $def)
 {
     if ('#' === $spec[0]) {
         $p = strrpos($spec, ' ');
         $typeAnnotations = substr($spec, 0, $p) . "\n";
         $spec = substr($spec, $p + 1);
     } else {
         $typeAnnotations = '';
     }
     if (isset(\xp::$cl[$spec])) {
         return new XPClass(literal($spec));
     }
     // Backwards compatibility, deprecated usage via declaration inside string.
     if (!is_array($declaration)) {
         preg_match('/(class|interface|trait)\\s+([^ ]+)(\\s+extends\\s+([^ ]+))?(\\s+implements\\s+([^\\{]+))?/', $declaration, $parsed);
         $declaration = ['kind' => $parsed[1], 'use' => [], 'extends' => [], 'implements' => []];
         if (isset($parsed[4])) {
             foreach (explode(',', $parsed[4]) as $type) {
                 $declaration['extends'][] = trim($type, ' ');
             }
         }
         if (isset($parsed[6])) {
             foreach (explode(',', $parsed[6]) as $type) {
                 $declaration['implements'][] = trim($type, ' ');
             }
         }
     }
     $functions = [];
     if (is_array($def)) {
         $iface = 'interface' === $declaration['kind'];
         $bytes = '';
         foreach ($def as $name => $member) {
             if ('#' === $name[0]) {
                 $p = strrpos($name, ' ');
                 $memberAnnotations = substr($name, 0, $p) . "\n";
                 $name = substr($name, $p + 1);
             } else {
                 $memberAnnotations = '';
             }
             if ($member instanceof \Closure) {
                 $bytes .= $memberAnnotations . self::defineForward($name, (new \ReflectionFunction($member))->getParameters(), $iface ? null : 'return self::$__func["' . $name . '"]->__invoke(%s);');
                 $iface || ($functions[$name] = $member);
             } else {
                 $bytes .= $memberAnnotations . 'public $' . $name . '= ' . var_export($member, true) . ';';
             }
         }
         if ($iface) {
             // Don't handle constructors
         } else {
             if (isset($functions['__construct'])) {
                 $bytes = 'static $__func= []; ' . $bytes;
             } else {
                 if ($declaration['extends'] && ($ctor = (new \ReflectionClass(self::classLiteral($declaration['extends'][0])))->getConstructor())) {
                     $constructor = self::defineForward('__construct', $ctor->getParameters(), 'parent::__construct(%s);');
                 } else {
                     $constructor = self::defineForward('__construct', [], '');
                     foreach ($declaration['use'] as $use) {
                         $trait = self::classLiteral($use);
                         if ($ctor = (new \ReflectionClass($trait))->getConstructor()) {
                             $bytes .= 'use ' . $trait . ' { __construct as __trait; }';
                             $constructor = self::defineForward('__construct', $ctor->getParameters(), 'self::__trait(%s);');
                         } else {
                             $bytes .= 'use ' . $trait . ';';
                         }
                     }
                     $declaration['use'] = [];
                 }
                 $bytes = 'static $__func= []; ' . $constructor . $bytes;
             }
         }
     } else {
         $bytes = substr(trim($def), 1, -1);
     }
     if (false !== ($p = strrpos($spec, '.'))) {
         $header = 'namespace ' . strtr(substr($spec, 0, $p), '.', '\\') . ';';
         $name = substr($spec, $p + 1);
     } else {
         $header = '';
         $name = $spec;
         \xp::$cn[$name] = $name;
     }
     $dyn = self::registerLoader(DynamicClassLoader::instanceFor(__METHOD__));
     $dyn->setClassBytes($spec, sprintf('%s%s%s %s%s%s {%s%s}', $header, $typeAnnotations, $declaration['kind'], $name, $declaration['extends'] ? ' extends ' . implode(', ', array_map('self::classLiteral', $declaration['extends'])) : '', $declaration['implements'] ? ' implements ' . implode(', ', array_map('self::classLiteral', $declaration['implements'])) : '', $declaration['use'] ? ' use ' . implode(', ', array_map('self::classLiteral', $declaration['use'])) . ';' : '', $bytes));
     $cl = $dyn->loadClass($spec);
     $functions && $cl->reflect()->setStaticPropertyValue('__func', $functions);
     return $cl;
 }
Пример #3
0
 public function cannot_parse_xml()
 {
     $class = nameof($this) . $this->name;
     DynamicClassLoader::instanceFor(self::class)->setClassBytes($class, '', '<?xml version="1.0">');
     new ClassSource($class);
 }
Пример #4
0
 /**
  * Execute with a given environment settings
  *
  * @param   array<string, var> env
  * @return  var
  */
 public function executeWith(array $env = [])
 {
     with($cl = \lang\DynamicClassLoader::instanceFor(__FUNCTION__), $name = $this->type->name());
     $cl->setClassBytes($name, $this->source);
     $cl->loadClass0($name);
 }
 /**
  * Creates fixture
  *
  * @return   lang.IClassLoader
  */
 protected function newFixture()
 {
     return DynamicClassLoader::instanceFor('test');
 }
Пример #6
0
 /**
  * Creates an XPClass instance from the specified code using a
  * DynamicClassLoader.
  *
  * @param   string bytes
  * @return  lang.XPClass
  */
 private function createClass($bytes)
 {
     $dyn = \lang\DynamicClassLoader::instanceFor(__METHOD__);
     try {
         $dyn->setClassBytes($this->getProxyName(), $bytes);
         $class = $dyn->loadClass($this->getProxyName());
     } catch (\lang\FormatException $e) {
         throw new \lang\IllegalArgumentException($e->getMessage());
     }
     return $class;
 }
Пример #7
0
 /**
  * Helper method for defineClass() and defineInterface().
  *
  * @param  string $spec
  * @param  [:var] $declaration
  * @param  var $def
  * @return lang.XPClass
  */
 public static function defineType($spec, $declaration, $def)
 {
     if ('#' === $spec[0]) {
         $p = strrpos($spec, ' ');
         $typeAnnotations = substr($spec, 0, $p) . "\n";
         $spec = substr($spec, $p + 1);
     } else {
         $typeAnnotations = '';
     }
     if (isset(\xp::$cl[$spec])) {
         return new XPClass(literal($spec));
     }
     $functions = [];
     if (is_array($def)) {
         $iface = 'interface' === $declaration['kind'];
         $bytes = '';
         foreach ($def as $name => $member) {
             if ('#' === $name[0]) {
                 $p = strrpos($name, ' ');
                 $memberAnnotations = substr($name, 0, $p) . "\n";
                 $name = substr($name, $p + 1);
             } else {
                 $memberAnnotations = '';
             }
             if ($member instanceof \Closure) {
                 $bytes .= $memberAnnotations . self::defineForward($name, (new \ReflectionFunction($member))->getParameters(), $iface ? null : 'return self::$__func["' . $name . '"]->call($this%s);', 0);
                 $iface || ($functions[$name] = $member);
             } else {
                 $bytes .= $memberAnnotations . 'public $' . $name . '= ' . var_export($member, true) . ';';
             }
         }
         $iface || ($bytes = 'static $__func= []; ' . $bytes);
     } else {
         $bytes = substr(trim($def), 1, -1);
     }
     if (false !== ($p = strrpos($spec, '.'))) {
         $header = 'namespace ' . strtr(substr($spec, 0, $p), '.', '\\') . ';';
         $name = substr($spec, $p + 1);
     } else {
         if (false !== ($p = strrpos($spec, '\\'))) {
             $header = 'namespace ' . substr($spec, 0, $p) . ';';
             $name = substr($spec, $p + 1);
             $spec = strtr($spec, '\\', '.');
         } else {
             $header = '';
             $name = $spec;
             \xp::$cn[$name] = $name;
         }
     }
     if (isset($declaration['imports'])) {
         foreach ($declaration['imports'] as $class => $alias) {
             $header .= 'use ' . substr(self::classLiteral($class), 1) . ($alias ? ' as ' . $alias : '') . ';';
         }
     }
     $dyn = self::registerLoader(DynamicClassLoader::instanceFor(__METHOD__));
     $dyn->setClassBytes($spec, $x = sprintf('%s%s%s %s %s%s%s {%s%s}', $header, $typeAnnotations, $declaration['modifiers'] ?? '', $declaration['kind'], $name, $declaration['extends'] ? ' extends ' . implode(', ', array_map('self::classLiteral', $declaration['extends'])) : '', $declaration['implements'] ? ' implements ' . implode(', ', array_map('self::classLiteral', $declaration['implements'])) : '', $declaration['use'] ? ' use ' . implode(', ', array_map('self::classLiteral', $declaration['use'])) . ';' : '', $bytes));
     $cl = $dyn->loadClass($spec);
     $functions && $cl->reflect()->setStaticPropertyValue('__func', $functions);
     return $cl;
 }