/** * Defines a type * * @param string $declaration * @param string[] $extends * @return lang.XPClass */ protected function define($declaration, $extends = [Object::class]) { if (!isset(self::$fixtures[$declaration])) { $definition = ['kind' => 'class', 'extends' => $extends, 'implements' => [], 'use' => [], 'imports' => [Identity::class => null]]; self::$fixtures[$declaration] = ClassLoader::defineType(nameof($this) . sizeof(self::$fixtures), $definition, $declaration); } return self::$fixtures[$declaration]; }
/** * Defines an anonymous type * * @param string $decl Type declaration * @param int $modifiers * @return lang.XPClass */ protected function type($decl = null, $modifiers = '') { if (!isset(self::$fixtures[$decl])) { $definition = ['modifiers' => $modifiers, 'kind' => 'class', 'extends' => [Object::class], 'implements' => [], 'use' => [CompareTo::class], 'imports' => [Value::class => null]]; self::$fixtures[$decl] = ClassLoader::defineType(get_class($this) . sizeof(self::$fixtures), $definition, $decl); } return self::$fixtures[$decl]; }
public function anonymous_instance_from_abstract_base_class() { \lang\ClassLoader::defineType('net.xp_lang.tests.Command', ['kind' => 'abstract class', 'extends' => ['lang.Object'], 'implements' => ['lang.Runnable'], 'use' => []], []); $command = $this->run('return new net.xp_lang.tests.Command() { public void run() { throw new lang.MethodNotImplementedException("run"); } };'); $this->assertAnonymousInstanceOf('net.xp_lang.tests.Command', $command); }
function newinstance($spec, $args, $def = null) { static $u = 0; if ('#' === $spec[0]) { $p = strrpos($spec, ' '); $annotations = substr($spec, 0, $p) . ' '; $spec = substr($spec, $p + 1); } else { $annotations = ''; } // Create unique name $n = "ยท" . ++$u; if (0 === strncmp($spec, 'php.', 4)) { $spec = substr($spec, 4); } else { if (false === strpos($spec, '.')) { $spec = \lang\XPClass::nameOf($spec); } } // Handle generics, PHP types and all others. if (strstr($spec, '<')) { $class = \lang\Type::forName($spec); $type = $class->literal(); $generic = xp::$meta[$class->getName()]['class'][DETAIL_GENERIC]; } else { if (false === strpos($spec, '.')) { $type = $spec; $generic = null; } else { try { $type = xp::$loader->loadClass0($spec); } catch (\lang\ClassLoadingException $e) { xp::error($e->getMessage()); } $generic = null; } } $name = strtr($type, '\\', '.') . $n; if (interface_exists($type)) { $decl = ['kind' => 'class', 'extends' => ['lang.Object'], 'implements' => ['\\' . $type], 'use' => []]; } else { if (trait_exists($type)) { $decl = ['kind' => 'class', 'extends' => ['lang.Object'], 'implements' => [], 'use' => ['\\' . $type]]; } else { $decl = ['kind' => 'class', 'extends' => ['\\' . $type], 'implements' => [], 'use' => []]; } } $defined = \lang\ClassLoader::defineType($annotations . $name, $decl, $def); if (false === strpos($type, '\\')) { xp::$cn[$type . $n] = $spec . $n; } if ($generic) { \lang\XPClass::detailsForClass($name); xp::$meta[$name]['class'][DETAIL_GENERIC] = $generic; } if ($defined->hasConstructor()) { return $defined->getConstructor()->newInstance($args); } else { return $defined->newInstance(); } }
/** * Creates a type from a given type body * * @param string[] $interfaces * @param string $body The string `<T>` is replaced by the unique type name * @return lang.XPClass */ protected function declareType($interfaces, $body) { $declaration = ['kind' => 'class', 'extends' => ['\\lang\\Object'], 'implements' => $interfaces, 'use' => []]; $unique = typeof($this)->getSimpleName() . '_' . $this->name; return ClassLoader::defineType($unique, $declaration, strtr($body, ['<T>' => $unique])); }
public static function defineImplementation() { $implementation = static::implementation(); self::$fixture = ClassLoader::defineType($implementation . 'Instance', ['kind' => 'class', 'extends' => [], 'implements' => [], 'use' => [$implementation]], '{ public $buffer; public function __construct($initial) { $this->buffer= (string)$initial; }}'); }