From 104ff522c43fabc7c284fc38a46d17c16fe114d1 Mon Sep 17 00:00:00 2001
From: Ludovic Pouzenc <ludovic@pouzenc.fr>
Date: Wed, 1 Aug 2012 20:24:03 +0000
Subject: Ecriure d'un squelette de l'outil de compilation. Une première
 instance sera implémentée pour le framework CakePHP. Pour l'instant les
 méthodes abstraites sont des bouchons qui ne permettent même pas de couvrir
 tout le code de la classe abstraite.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

git-svn-id: file:///var/svn/2012-php-weave/trunk@5 d972a294-176a-4cf9-8ea1-fcd5b0c30f5c
---
 .../src/php-weave/abstract_weaver.class.php        | 119 +++++++++++++++++++++
 .../src/php-weave/cakephp_weaver.class.php         |  49 +++++++++
 poc/poc02-compiling-cake/src/php-weave/main.php    |  62 +----------
 3 files changed, 172 insertions(+), 58 deletions(-)
 create mode 100644 poc/poc02-compiling-cake/src/php-weave/abstract_weaver.class.php
 create mode 100644 poc/poc02-compiling-cake/src/php-weave/cakephp_weaver.class.php

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);
+}
diff --git a/poc/poc02-compiling-cake/src/php-weave/cakephp_weaver.class.php b/poc/poc02-compiling-cake/src/php-weave/cakephp_weaver.class.php
new file mode 100644
index 0000000..cc25641
--- /dev/null
+++ b/poc/poc02-compiling-cake/src/php-weave/cakephp_weaver.class.php
@@ -0,0 +1,49 @@
+<?php
+require_once 'abstract_weaver.class.php';
+
+class CakePHPWeaver extends AbstractWeaver {
+	public function detectFramework($sourcetree_rootpath) {
+		
+	}
+
+	public function parseFrameworkConfig($fw_props) {
+		
+	}
+
+	public function parseFrameworkCode($fw_props, $fw_conf, $cache_path) {
+		
+	}
+
+	public function parseApplicationCode($fw_props, $fw_conf, $fw_extra, $cache_path) {
+		
+	}
+
+	public function computePageList($fw_props, $fw_conf, $fw_extra, $app_extra) {
+		return array(
+			'page1' => array(),
+			'page2' => array(),
+		);
+	}
+
+	public function outputMappingFile($app_pages,  $result_path) {
+		
+	}
+
+	public function makePageFullAST($page, $page_props, $fw_props, $fw_conf, $fw_extra, $app_extra, $cache_path) {
+		
+	}
+
+	public function analysePageAST($page_full_ast, $page, $page_props, $fw_props, $fw_conf, $fw_extra, $app_extra, $cache_path) {
+		
+	}
+
+	public function throwDeadCode(&$page_annotated_ast) {
+		
+	}
+
+	public function weaveCode($page_annotated_ast) {
+		return array(new PHPParser_Node_Stmt_Echo(array(new PHPParser_Node_Scalar_String("Hello World\n"))));
+	}
+
+}
+?>
diff --git a/poc/poc02-compiling-cake/src/php-weave/main.php b/poc/poc02-compiling-cake/src/php-weave/main.php
index 2a4df55..da94bbe 100644
--- a/poc/poc02-compiling-cake/src/php-weave/main.php
+++ b/poc/poc02-compiling-cake/src/php-weave/main.php
@@ -1,64 +1,10 @@
 <?php
-require '../vendor/nikic/php-parser/lib/bootstrap.php';
-require './visitors.inc.php';
+require_once './cakephp_weaver.class.php';
 
 ini_set('xdebug.max_nesting_level', 2000);
 
-function dbg($indent, $text) {
-	for($i=0;$i<$indent;$i++) echo ".";
-	echo "$text\n";
-}
-
-function recursive_parse($src_filepath, $stmts1_filepath, $stmts2_filepath, $level=0) {
-	global $parser,$nodeDumper;
-
-	try {
-		dbg($level,"Parsing '$src_filepath'");
-		$stmts = $parser->parse(file_get_contents($src_filepath));
-
-		if (strlen($stmts1_filepath) > 0 ) {
-			dbg($level,"Dumping1 '$src_filepath' AST to '$stmts1_filepath'");
-			file_put_contents($stmts1_filepath, $nodeDumper->dump($stmts));
-		}
-
-		dbg($level,"Transforming '$src_filepath'");
-		$traverser = new PHPParser_NodeTraverser;
-/*
-		$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
-		$traverser->addVisitor(new NodeVisitor_NamespaceConverter);
-*/
-		// FIXME : getcwd is quick and dirty here
-		$traverser->addVisitor(new NodeVisitor_PreprocessInclude($level, getcwd(), $src_filepath));
-		$stmts = $traverser->traverse($stmts);
-		$traverser=null; //Destroy
-
-		if (strlen($stmts2_filepath) > 0) {	
-			dbg($level,"Dumping2 '$src_filepath' AST to '$stmts2_filepath'");
-			file_put_contents($stmts2_filepath, $nodeDumper->dump($stmts));
-		}
-
-	} catch (PHPParser_Error $e) {
-	    echo 'Parse Error: ', $e->getMessage();
-	}
-	return $stmts;
-}
-
-
 // Main
-$src_filepath = "./main.php";
-#$src_filepath = "./to_parse.php";
-$stmts1_filepath = "out/stmts1.ast";
-$stmts2_filepath = "out/stmts2.ast";
-$dest_filepath = "out/result.php";
-
-$parser = new PHPParser_Parser(new PHPParser_Lexer);
-$nodeDumper = new PHPParser_NodeDumper;
-
-$level=0;
-$stmts=recursive_parse($src_filepath, $stmts1_filepath, $stmts2_filepath);
-
-dbg(0,"Outputing '$dest_filepath'");
-$prettyPrinter = new PHPParser_PrettyPrinter_Zend;
-file_put_contents($dest_filepath, "<?php\n" . $prettyPrinter->prettyPrint($stmts) . "\n?>");
-
+$weaver=new CakePHPWeaver;
+$weaver->runAllSteps("../workdir/in", "../workdir/cache", "../workdir/out");
+ 
 ?>
-- 
cgit v1.2.3