diff options
Diffstat (limited to 'poc/poc02-compiling-cake/src/php-weave/abstract_weaver.class.php')
-rw-r--r-- | poc/poc02-compiling-cake/src/php-weave/abstract_weaver.class.php | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/poc/poc02-compiling-cake/src/php-weave/abstract_weaver.class.php b/poc/poc02-compiling-cake/src/php-weave/abstract_weaver.class.php new file mode 100644 index 0000000..86a07b1 --- /dev/null +++ b/poc/poc02-compiling-cake/src/php-weave/abstract_weaver.class.php @@ -0,0 +1,119 @@ +<?php +require '../vendor/nikic/php-parser/lib/bootstrap.php'; + +function dbg($indent, $text) { + for($i=0;$i<$indent;$i++) echo "."; + echo "$text\n"; +} + +abstract class AbstractWeaver { + protected $parser; + protected $nodeDumper; + protected $prettyPrinter; + protected $ast_dump_before_walk; + protected $ast_dump_after_walk; + + public function __construct() { + $this->parser = new PHPParser_Parser(new PHPParser_Lexer); + $this->nodeDumper = new PHPParser_NodeDumper; + $this->prettyPrinter = new PHPParser_PrettyPrinter_Zend; + $this->ast_dump_before_walk=""; + $this->ast_dump_after_walk=""; + } + + public function setASTDumpFiles($ast_dump_before_walk, $ast_dump_after_walk) { + // Set file to "" to prevent AST dumping + $this->$ast_dump_before_walk=$ast_dump_before_walk; + $this->$ast_dump_after_walk=$ast_dump_after_walk; + } + + public function runAllSteps($sourcetree_rootpath, $cache_path, $result_path) { + try { + $step='detectFramework'; + $fw_props=$this->detectFramework($sourcetree_rootpath); + $step='parseFrameworkConfig'; + $fw_conf=$this->parseFrameworkConfig($fw_props); + $step='parseFrameworkCode'; + $fw_extra=$this->parseFrameworkCode($fw_props, $fw_conf, $cache_path); + $step='parseApplicationCode'; + $app_extra=$this->parseApplicationCode($fw_props, $fw_conf, $fw_extra, $cache_path); + $step='computePageList'; + $app_pages=$this->computePageList($fw_props, $fw_conf, $fw_extra, $app_extra); + $step='outputMappingFile'; + $this->outputMappingFile($app_pages, $result_path); + foreach ($app_pages as $page=>$page_props) { + $step="makePageFullAST of '$page'"; + $page_full_ast=$this->makePageFullAST($page, $page_props, $fw_props, $fw_conf, $fw_extra, $app_extra, $cache_path); + $step="analysePageAST of '$page'"; + $page_annotated_ast=$this->analysePageAST($page_full_ast, $page, $page_props, $fw_props, $fw_conf, $fw_extra, $app_extra, $cache_path); + $step="throwDeadCode of '$page'"; + $this->throwDeadCode($page_annotated_ast); + $step="weaveCode of '$page'"; + $out_ast=$this->weaveCode($page_annotated_ast); + + $page_dest_path=$this->makeDestPath($page, $result_path); + $step="prettyPrint to '$page_dest_path'"; + $this->prettyPrint($out_ast, $page_dest_path); + } + + } catch (Exception $e) { + echo "Step '$step' failure : ", $e->getMessage(); + } + } + + public function makeDestPath($page, $result_path) { + return $result_path . '/' . str_replace('/', '_', $page) . ".php"; + } + public function parseAndWalk($src_filepath, $traverser, $env=array(), $level=0) { + /* Parse a file et traverse the AST. + * Could be recursive if a traverser call again parseAndWalk for example when finding a include() directive + * The main call should be in this case : + * $w=new XXXWeaver; + * $nv=new NodeVisitor_XXX($w); // The node visitor + * $t=new PHPParser_NodeTraverser; $t->addVisitor($nv); + * w->parseAndWalk($src_mainfile, $t, array('cwd'=>dirname($src_mainfile)); + */ + try { + dbg($level,"Parsing '$src_filepath'"); + $stmts = $this->parser->parse(file_get_contents($src_filepath)); + + $this->dumpAST($stmts, $src_filepath, $this->ast_dump_before_walk); + + if ($traverser) { + dbg($level,"Transforming '$src_filepath'"); + $stmts = $traverser->traverse($stmts); + $traverser=null; //Destroy + } + + $this->dumpAST($stmts, $src_filepath, $this->ast_dump_after_walk); + + } catch (PHPParser_Error $e) { + echo 'Parse Error: ', $e->getMessage(); + } + return $stmts; + } + + public function prettyPrint($ast, $dest_filepath) { + dbg(0,"Outputing '$dest_filepath'"); + file_put_contents($dest_filepath, "<?php\n" . $this->prettyPrinter->prettyPrint($ast) . "\n?>"); + } + + public function dumpAST($ast, $ast_title, $dest_filepath) { + if (is_array($ast) && strlen($dest_filepath) > 0 ) { + dbg($level,"Dumping '$ast_title,' AST to '$dest_filepath'"); + file_put_contents($dest_filepath, $this->nodeDumper->dump($ast)); + } + } + + // Framework specific code + abstract public function detectFramework($sourcetree_rootpath); + abstract public function parseFrameworkConfig($fw_props); + abstract public function parseFrameworkCode($fw_props, $fw_conf, $cache_path); + abstract public function parseApplicationCode($fw_props, $fw_conf, $fw_extra, $cache_path); + abstract public function computePageList($fw_props, $fw_conf, $fw_extra, $app_extra); + abstract public function outputMappingFile($app_pages, $result_path); + abstract public function makePageFullAST($page, $page_props, $fw_props, $fw_conf, $fw_extra, $app_extra, $cache_path); + abstract public function analysePageAST($page_full_ast, $page, $page_props, $fw_props, $fw_conf, $fw_extra, $app_extra, $cache_path); + abstract public function throwDeadCode(&$page_annotated_ast); + abstract public function weaveCode($page_annotated_ast); +} |