Пример #1
0
 public function analyze($ast, $parent = NULL)
 {
     /* holds the name of the currently compiled function */
     $function = "";
     foreach ($ast as $i => $node) {
         /* set the function name in the objects */
         if ($node instanceof \Parser\Parsers\FunctionDefinition) {
             $function = $node->name;
             $node->function = $node->name;
         } elseif (!empty($node->function)) {
             $function = $node->function;
         } else {
             if (isset($node->name) && $node->name == "extern") {
                 continue;
             } elseif (!empty($function)) {
                 $node->function = $function;
             } else {
                 if (!empty($parent->function)) {
                     $node->function = $parent->function;
                 } elseif (!empty($function)) {
                     $node->function = $function;
                 }
             }
         }
         /* set the arguments as local variables */
         if ($node instanceof \Parser\Parsers\FunctionDefinition && count($node->arguments) > 0) {
             foreach ($node->arguments as $arg) {
                 \Tables::addLocalVariable($function, $arg->name);
             }
         }
         if ($node instanceof \Parser\Parsers\Assignment) {
             /* deal with assignments */
             if (is_object($node->content)) {
                 if (\Tables::localVariable($node->function, $node->name)) {
                     $var =& \Tables::updateLocalVariable($node->function, $node->name);
                 } else {
                     $var =& \Tables::addLocalVariable($node->function, $node->name);
                 }
                 $var->type[$node->line] = \Tables::I32;
                 continue;
             }
             switch (\Misc::baseClass($node->content[0])) {
                 case "String":
                     $type = \Tables::STRING;
                     break;
                 case "Integer":
                     $type = \Tables::I32;
                     break;
                 case "Addition":
                 case "Subtraction":
                 case "Multiplication":
                 case "Division":
                     $type = \Tables::I32;
                     break;
                 default:
                     error("unknown assignment type '" . \Misc::baseClass($node->content[0]) . "' in line {$node->line}");
             }
             if (\Tables::localVariable($node->function, $node->name)) {
                 $var =& \Tables::updateLocalVariable($node->function, $node->name);
             } else {
                 $var =& \Tables::addLocalVariable($node->function, $node->name);
             }
             $var->type[$node->line] = $type;
         } elseif (!$node instanceof \Parser\Parsers\Variable && count($node->content) > 0) {
             /* analyze recursively if needed */
             if ($node instanceof \Parser\Parsers\FunctionDefinition && !empty($node->arguments)) {
                 foreach ($node->arguments as $arg) {
                     $arg->function = $function;
                 }
             }
             $this->analyze($node->content, $node);
         } elseif ($node instanceof \Parser\Parsers\Variable) {
             /* do type inference based on printf */
             if ($parent instanceof \Parser\Parsers\Call) {
                 if ($parent->name == "printf") {
                     $matches = array();
                     preg_match_all("/%[scdiu]/", $ast[0]->string, $matches);
                     $format = substr($matches[0][$i - 1], -1);
                     $type = 0;
                     switch ($format) {
                         case 'd':
                         case 'i':
                         case 'c':
                             $type |= \Tables::I32;
                             break;
                         case 's':
                             $type |= \Tables::STRING;
                     }
                     $var =& \Tables::updateLocalVariable($node->function, $node->name);
                     if ($var == NULL) {
                         continue;
                     }
                     $node->type[$node->line] = $type;
                 }
             }
         }
     }
 }