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; } } } } }