/**
  * Compile class from source and return compiled type
  *
  * @param   string src
  * @return  xp.compiler.types.TypeReflection
  */
 protected function compile($src)
 {
     $unique = 'FixtureClassFor' . $this->getClass()->getSimpleName() . ucfirst($this->name);
     $r = $this->emitter->emit(Syntax::forName('xp')->parse(new MemoryInputStream(sprintf($src, $unique))), $this->scope);
     $r->executeWith([]);
     return new TypeReflection(\lang\XPClass::forName($r->type()->name()));
 }
Beispiel #2
0
 /**
  * Constructor
  *
  * @param   io.File file
  * @param   xp.compiler.Syntax s Syntax to use, determined via source file's syntax otherwise
  * @throws  lang.IllegalArgumentException in case the syntax cannot be determined
  */
 public function __construct(File $file, Syntax $s = null)
 {
     $this->file = $file;
     try {
         $this->syntax = $s ?: Syntax::forName($this->file->getExtension());
     } catch (IllegalArgumentException $e) {
         throw new IllegalArgumentException('Cannot determine syntax for "' . $this->file->getFileName() . '"', $e);
     }
 }
Beispiel #3
0
 /**
  * Get parse tree for a given qualified class name by looking it
  * up in the source path.
  *
  * @param   string qualified
  * @return  xp.compiler.io.Source
  */
 public function findClass($qualified)
 {
     $name = DIRECTORY_SEPARATOR . strtr($qualified, '.', DIRECTORY_SEPARATOR);
     foreach ($this->sourcePaths as $path) {
         foreach (Syntax::available() as $ext => $syntax) {
             if (!file_exists($uri = $path . $name . '.' . $ext)) {
                 continue;
             }
             return new FileSource(new File($uri), $syntax);
             // FIXME: Use class loader / resources
         }
     }
     return null;
 }
 /**
  * Returns file targets from a folder
  *
  * @param   string uri
  * @param   bool recursive
  * @return  xp.compiler.io.FileSource[]
  */
 protected static function fromFolder($uri, $recursive)
 {
     static $filter = null;
     if (null === $filter) {
         $filter = new AnyOfFilter();
         foreach (Syntax::available() as $ext => $syntax) {
             $filter->add(new ExtensionEqualsFilter($ext));
         }
     }
     $files = [];
     $it = new FilteredIOCollectionIterator(new FileCollection($uri), $filter, $recursive);
     foreach ($it as $element) {
         $files[] = new FileSource(new File($element->getURI()));
     }
     return $files;
 }
 /**
  * Constructor
  *
  * @param   string syntax
  * @param   string fragment
  * @param   bool return whether to add return statement if not present in fragment
  * @throws  lang.IllegalArgumentException
  */
 public function __construct($syntax, $fragment, $return = false)
 {
     $this->syntax = \xp\compiler\Syntax::forName($syntax);
     // Add "return" statement if not present. TODO: If other languages are added
     // in which the string "return" is not the return statement, then this needs
     // to be rewritten
     $this->fragment = rtrim($fragment, ';') . ';';
     if ($return && !(strstr($fragment, 'return ') || strstr($fragment, 'return;'))) {
         $this->fragment = 'return ' . $this->fragment;
     }
     // Verify template
     $name = $this->syntax->name();
     if (!isset(self::$TEMPLATE[$name])) {
         throw new \lang\IllegalArgumentException('No command line code template for syntax "' . $name . '"');
     }
     $this->template = self::$TEMPLATE[$name];
 }
 /**
  * Define class from a given name and source
  *
  * @param   string type
  * @param   string class
  * @param   var parent either a string or a lang.XPClass
  * @param   string src
  * @param   string[] imports
  * @return  lang.XPClass
  */
 protected static function define($type, $class, $parent, $src, array $imports = [])
 {
     $emitter = self::emitter();
     $emitter->clearMessages();
     $syntax = Syntax::forName('xp');
     $class = 'Source' . $class;
     $scope = new TaskScope(new CompilationTask(new FileSource(new File(__FILE__), $syntax), new NullDiagnosticListener(), new FileManager(), $emitter));
     // Parent class
     if ($parent instanceof XPClass) {
         $extends = (new XPClass(self::class))->getPackage()->getName() . '.' . $parent->getName();
         $scope->addResolved($extends, new TypeReflection($parent));
         $scope->addTypeImport($extends);
     } else {
         $extends = $parent;
     }
     // Emit
     $r = $emitter->emit($syntax->parse(new MemoryInputStream(implode("\n", $imports) . ' public ' . $type . ' ' . $class . ' ' . ($extends ? ' extends ' . $extends : '') . $src), $class), $scope);
     \xp::gc();
     // DEBUG $r->writeTo(\util\cmd\Console::$out->getStream());
     $r->executeWith([]);
     return XPClass::forName($r->type()->name());
 }
 /**
  * Parse source
  *
  * @param  string $source
  * @return xp.compiler.ast.ParseTree
  */
 protected function parse($source)
 {
     return Syntax::forName('php')->parse(new \io\streams\MemoryInputStream($source), $this->name);
 }
Beispiel #8
0
 /**
  * Parse sourcecode
  *
  * @param  string $source
  * @return xp.compiler.ast.TypeDeclarationNode
  */
 private function parse($source)
 {
     return Syntax::forName('xp')->parse(new MemoryInputStream($source))->declaration;
 }
 /**
  * Returns a given package's contents
  *
  * @param  string $package
  * @return string[]
  */
 public function packageContents($package)
 {
     static $syntaxes = '';
     // Calculate syntax regex for matching on files
     if (!$syntaxes) {
         foreach (Syntax::available() as $syntax) {
             $syntaxes .= '|' . $syntax->name();
         }
         $syntaxes = '/\\.(' . substr($syntaxes, 1) . ')$/';
     }
     // List directory contents, replacing compileable source files with
     // class file names. These of course don't exist yet, but will be
     // compiled on demand
     $return = [];
     $dir = strtr($package, '.', DIRECTORY_SEPARATOR);
     foreach ($this->files->getSourcePaths() as $path) {
         if (!is_dir($d = $path . $dir . DIRECTORY_SEPARATOR)) {
             continue;
         }
         $handle = opendir($d);
         while ($e = readdir($handle)) {
             if ('.' === $e || '..' === $e) {
                 continue;
             } else {
                 if (is_dir($d . $e)) {
                     $return[] = $e . '/';
                 } else {
                     if (strstr($e, \xp::CLASS_FILE_EXT)) {
                         $return[] = $e;
                     } else {
                         if ('module.xp' === $e) {
                             $return[] = $e;
                         } else {
                             $return[] = preg_replace($syntaxes, \xp::CLASS_FILE_EXT, $e);
                         }
                     }
                 }
             }
         }
         closedir($handle);
     }
     return $return;
 }
Beispiel #10
0
 /**
  * Sets up this testcase
  *
  * @return void
  */
 public function setUp()
 {
     $this->fixture = new TaskScope(new CompilationTask(new FileSource(new File(__FILE__), Syntax::forName('xp')), new NullDiagnosticListener(), new FileManager(), new V54Emitter()));
 }
 public static function useXpSyntax()
 {
     self::$syntax = Syntax::forName('xp');
 }
Beispiel #12
0
 /**
  * Compile class from source and return compiled type
  *
  * @param   string src
  * @return  xp.compiler.types.Types
  */
 protected function compile($src)
 {
     $r = $this->emitter->emit(Syntax::forName('xp')->parse(new MemoryInputStream($src)), $this->scope);
     return $r->type();
 }
Beispiel #13
0
 /**
  * Compile class from source and return compiled type
  *
  * @param   string src
  * @return  xp.compiler.types.Types
  */
 protected function compile($src)
 {
     $r = $this->emitter->emit(Syntax::forName('xp')->parse(new MemoryInputStream($src)), $this->scope);
     $r->executeWith([]);
     return XPClass::forName($r->type()->name());
 }
 /**
  * Returns a subtask (overloaded)
  *
  * @param   var arg either a xp.compiler.io.Source or a fully qualified class name
  * @return  xp.compiler.task.CompilationTask
  * @throws  lang.IllegalArgumentException for argument type mismatches
  * @throws  lang.ElementNotFoundException if class given and class cannot be found
  */
 public function newSubTask($arg)
 {
     if ($arg instanceof Source) {
         $source = $arg;
     } else {
         if (is_string($arg)) {
             if (!($source = $this->manager->findClass($arg))) {
                 throw new ElementNotFoundException(sprintf("Cannot find class %s, tried {*.%s} in [\n  %s\n]", $arg, implode(', *.', array_keys(Syntax::available())), implode("\n  ", $this->manager->getSourcePaths())));
             }
         } else {
             throw new \lang\IllegalArgumentException('Expected either a string or a Source object');
         }
     }
     return new self($source, $this->listener, $this->manager, $this->emitter, $this->done);
 }