- Optimized forloop.* variables
[haanga.git] / haanga / generator.php
blobfc7b33366eeb5944291c8a6567984bc018cbbeb3
1 <?php
2 /*
3 +---------------------------------------------------------------------------------+
4 | Copyright (c) 2010 Haanga |
5 +---------------------------------------------------------------------------------+
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met: |
8 | 1. Redistributions of source code must retain the above copyright |
9 | notice, this list of conditions and the following disclaimer. |
10 | |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | 3. All advertising materials mentioning features or use of this software |
16 | must display the following acknowledgement: |
17 | This product includes software developed by César D. Rodas. |
18 | |
19 | 4. Neither the name of the César D. Rodas nor the |
20 | names of its contributors may be used to endorse or promote products |
21 | derived from this software without specific prior written permission. |
22 | |
23 | THIS SOFTWARE IS PROVIDED BY CÉSAR D. RODAS ''AS IS'' AND ANY |
24 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
26 | DISCLAIMED. IN NO EVENT SHALL CÉSAR D. RODAS BE LIABLE FOR ANY |
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE |
33 +---------------------------------------------------------------------------------+
34 | Authors: César Rodas <crodas@php.net> |
35 +---------------------------------------------------------------------------------+
38 class Haanga_CodeGenerator
40 protected $ident;
41 protected $tab = " ";
43 function __construct()
47 function getCode($op_code)
49 $this->ident = 0;
50 $code = "";
51 foreach ($op_code as $op) {
52 $method = "php_{$op['op']}";
53 if (!is_callable(array($this, $method))) {
54 var_dump($code, $op);
55 throw new Exception("CodeGenerator: Missing method $method");
57 switch ($op['op']) {
58 case 'end_foreach':
59 case 'end_if':
60 case 'end_function':
61 case 'else':
62 break;
63 default:
64 $code .= $this->ident();
66 $code .= $this->$method($op);
68 return $code;
71 protected function php_else()
73 $this->ident--;
74 $code = $this->ident()."} else {";
75 $this->ident++;
76 return $code;
79 function php_comment($op)
81 return "/* {$op['comment']} */";
84 function php_function($op)
86 $this->ident++;
87 return "function {$op['name']}(\$vars, \$return=FALSE, \$blocks=array())\n{";
90 protected function ident()
92 $code = "\n";
93 $code .= str_repeat($this->tab, $this->ident);
95 return $code;
98 protected function php_ident($op)
100 $this->ident++;
101 return "{";
104 protected function php_ident_end($op)
106 $this->ident--;
107 return $this->ident()."}";
110 protected function php_if($op)
112 $code = "if (".$this->php_generate_expr($op['expr']).") {";
113 $this->ident++;
114 return $code;
117 protected function php_expr($op)
119 return $this->php_generate_expr($op[0]).";";
123 protected function php_end_block()
125 $this->ident--;
126 return $this->ident()."}";
129 protected function php_end_function($op)
131 return $this->php_end_block();
134 protected function php_end_if($op)
136 return $this->php_end_block();
139 protected function php_end_foreach($op)
141 return $this->php_end_block();
144 protected function php_foreach($op)
146 $op['array'] = $this->php_get_varname($op['array']);
147 $op['value'] = $this->php_get_varname($op['value']);
148 $code = "foreach ({$op['array']} as ";
149 if (!isset($op['key'])) {
150 $code .= " {$op['value']}";
151 } else {
152 $op['key'] = $this->php_get_varname($op['key']);
153 $code .= " {$op['key']} => {$op['value']}";
156 $code .= ") {";
157 $this->ident++;
158 return $code;
162 protected function php_append_var($op)
164 return $this->php_declare($op, '.=');
167 protected function php_exec($op, $stmt=TRUE)
169 $code = "";
170 $code .= $op['name'].'(';
171 if (isset($op['args'])) {
172 $code .= $this->php_generate_list($op['args']);
174 $code .= ')';
175 if ($stmt) {
176 $code .=";";
178 return $code;
181 protected function php_generate_expr($expr)
183 $code = '';
184 if (is_array($expr) && isset($expr['op_expr'])) {
185 if ($expr['op_expr'] == 'expr') {
186 $code .= "(";
187 $code .= $this->php_generate_expr($expr[0]);
188 $code .= ")";
189 } else {
190 $code .= $this->php_generate_expr($expr[0]);
191 $code .= " {$expr['op_expr']} ";
192 $code .= $this->php_generate_expr($expr[1]);
194 } else {
195 if (is_array($expr)) {
196 $code .= $this->php_generate_declare(array($expr));
197 } else {
198 if ($expr === FALSE) {
199 $expr = 'FALSE';
200 } else if ($expr === TRUE) {
201 $expr = 'TRUE';
203 $code .= $expr;
206 return $code;
209 protected function php_generate_list($array)
211 $code = "";
212 if (!is_array($array)) {
213 var_dump(debug_backtrace());die();
215 foreach ($array as $value) {
216 $code .= $this->php_generate_declare(array($value));
217 $code .= ", ";
219 return substr($code, 0, -2);
222 protected function php_generate_declare($op, $skip=0)
224 $code = "";
226 for ($i=$skip; $i < count($op); $i++) {
227 if (!isset($op[$i])) {
228 continue;
230 if (!is_Array($op[$i])) {
231 var_dump($op);die('error1');
233 $key = key($op[$i]);
234 $value = current($op[$i]);
235 switch ($key) {
236 case 'array':
237 $code .= "Array(";
238 $code .= $this->php_generate_list($value);
239 $code .= ")";
240 break;
241 case 'function':
242 case 'exec':
243 if (strlen($code) != 0 && $code[strlen($code) -1] != '.') {
244 $code .= '.';
247 $value = array('name' => $value, 'args' => $op[$i]['args']);
248 $code .= $this->php_exec($value, FALSE);
249 $code .= '.';
250 break;
251 case 'key':
252 $code .= $this->php_generate_declare(array($value[0]))." => ".$this->php_generate_declare(array($value[1]));
253 break;
254 case 'string':
255 if ($code != "" && $code[strlen($code)-1] == '"') {
256 $code = substr($code, 0, -1);
257 } else {
258 $code .= '"';
260 $html = addslashes($value);
261 $html = str_replace(array('$', "\r", "\t", "\n","\\'"), array('\\$', '\r', '\t', '\n',"'"), $html);
262 $code .= $html.'"';
263 break;
264 case 'var':
265 if (strlen($code) != 0 && $code[strlen($code) -1] != '.') {
266 $code .= '.';
268 $code .= $this->php_get_varname($value).'.';
269 break;
270 case 'number':
271 if (!is_numeric($value)) {
272 throw new Exception("$value is not a valid number");
274 $code .= $value;
275 break;
276 case 'expr':
277 if (strlen($code) != 0) {
278 $code .= '.';
280 $code .= $this->php_generate_expr($value);
281 $code .= ".";
282 break;
283 case 'expr_cond':
284 if (strlen($code) != 0) {
285 $code .= '.';
287 $code .= "(";
288 $code .= $this->php_generate_expr($value);
289 $code .= " ? ";
290 $code .= $this->php_generate_declare(array($op[$i]['true']));
291 $code .= " : ";
292 $code .= $this->php_generate_declare(array($op[$i]['false']));
293 $code .= ").";
294 break;
295 default:
296 var_dump($op);die('error');
297 throw new Exception("Don't know how to declare {$key} = {$value}");
301 if ($code != "" && $code[strlen($code)-1] == '.') {
302 $code = substr($code, 0, -1);
305 return $code;
308 protected function php_print($op)
310 return 'echo '.$this->php_generate_declare($op).';';
313 protected function php_inc($op)
315 return "\${$op['name']}++;";
318 protected function php_declare($op, $assign=' =')
320 $op['name'] = $this->php_get_varname($op['name']);
321 $code = "{$op['name']} {$assign} ".$this->php_generate_declare($op).";";
322 return $code;
325 protected function php_get_varname($var)
327 if (is_array($var)) {
328 if (!is_string($var[0])) {
329 if (count($var) == 1) {
330 return $this->php_get_varname($var[0]);
331 } else {
332 throw new Exception("Invalid variable definition ".print_r($var, TRUE));
335 $var_str = $this->php_get_varname($var[0]);
336 for ($i=1; $i < count($var); $i++) {
337 $var_str .= "[";
338 if (is_string($var[$i])) {
339 $var_str .= '"'.$var[$i].'"';
340 } else if (is_array($var[$i])) {
341 if (isset($var[$i]['var'])) {
342 $var_str .= $this->php_get_varname($var[$i]['var']);
343 } else if (isset($var[$i]['string'])) {
344 $var_str .= '"'.addslashes($var[$i]['string']).'"';
347 $var_str .= "]";
349 return $var_str;
350 } else {
351 return "\$".$var;
355 protected function php_return($op)
357 $code = "return ".$this->php_generate_declare($op).";";
358 return $code;