function assert_ast_type($ast, $expected) { $type = ast_node_type($ast); if (is_string($expected)) { grokit_logic_assert($type == $expected, 'Node Type Mismatch: Exptected ' . $expected . ', got ' . $type . ' from ' . ast_node_source($ast)); } else { if (is_array($expected)) { grokit_logic_assert(in_array($type, $expected), 'Node Type Mismatch: Expected one of [' . implode(', ', $expected) . '] got ' . $type . ' from ' . ast_node_source($ast)); } } }
function node_func($file, $conditional, $node, $current_scope, $current_class, $namespace = '') { global $scope, $classes; if ($node instanceof \ast\Node) { $req = $opt = 0; $dc = ['return' => '', 'params' => []]; if (!empty($node->docComment)) { $dc = parse_doc_comment($node->docComment); } $result = ['file' => $file, 'namespace' => $namespace, 'scope' => $current_scope, 'conditional' => $conditional, 'flags' => $node->flags, 'lineno' => $node->lineno, 'endLineno' => $node->endLineno, 'name' => strpos($current_scope, '::') === false ? $namespace . $node->name : $node->name, 'docComment' => $node->docComment, 'params' => node_paramlist($file, $node->children[0], $req, $opt, $dc, $namespace), 'required' => $req, 'optional' => $opt, 'ret' => '', 'oret' => '', 'ast' => $node->children[2]]; if (!empty($dc['deprecated'])) { $result['deprecated'] = true; } if ($node->children[3] !== null) { $result['oret'] = ast_node_type($file, $node->children[3], $namespace); // Original return type $result['ret'] = ast_node_type($file, $node->children[3], $namespace); // This one changes as we walk the tree } else { // Check if the docComment has a return value specified if (!empty($dc['return'])) { // We can't actually figure out 'static' at this point, but fill it in regardless. It will be partially correct if ($dc['return'] == 'static' || $dc['return'] == 'self' || $dc['return'] == '$this') { if (strpos($current_scope, '::') !== false) { list($dc['return'], ) = explode('::', $current_scope); } } $result['oret'] = $dc['return']; $result['ret'] = $dc['return']; } } // Add params to local scope for user functions if ($file != 'internal') { $i = 1; foreach ($result['params'] as $k => $v) { if (empty($v['type'])) { // If there is no type specified in PHP, check for a docComment // We assume order in the docComment matches the parameter order in the code if (!empty($dc['params'][$k]['type'])) { $scope[$current_scope]['vars'][$v['name']] = ['type' => $dc['params'][$k]['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } else { $scope[$current_scope]['vars'][$v['name']] = ['type' => '', 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } } else { $scope[$current_scope]['vars'][$v['name']] = ['type' => $v['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } if (array_key_exists('def', $v)) { $type = node_type($file, $namespace, $v['def'], $current_scope, empty($current_class) ? null : $classes[strtolower($current_class)]); if ($scope[$current_scope]['vars'][$v['name']]['type'] !== '') { // Does the default value match the declared type? if ($type !== 'null' && !type_check($type, $scope[$current_scope]['vars'][$v['name']]['type'])) { Log::err(Log::ETYPE, "Default value for {$scope[$current_scope]['vars'][$v['name']]['type']} \${$v['name']} can't be {$type}", $file, $node->lineno); } } add_type($current_scope, $v['name'], strtolower($type)); // If we have no other type info about a parameter, just because it has a default value of null // doesn't mean that is its type. Any type can default to null if ($type === 'null' && !empty($result['params'][$k]['type'])) { $result['params'][$k]['type'] = merge_type($result['params'][$k]['type'], strtolower($type)); } } $i++; } if (!empty($dc['vars'])) { foreach ($dc['vars'] as $var) { if (empty($scope[$current_scope]['vars'][$var['name']])) { $scope[$current_scope]['vars'][$var['name']] = ['type' => $var['type'], 'tainted' => false, 'tainted_by' => '']; } else { add_type($current_scope, $var['name'], $var['type']); } } } } return $result; } assert(false, "{$node} was not an \\ast\\Node"); }
function node_func($file, $conditional, $node, $current_scope, $current_class, $namespace = '') { global $scope; if ($node instanceof \ast\Node) { $req = $opt = 0; $dc = ['return' => '', 'params' => []]; if (!empty($node->docComment)) { $dc = parse_doc_comment($node->docComment); } $result = ['file' => $file, 'namespace' => $namespace, 'scope' => $current_scope, 'conditional' => $conditional, 'flags' => $node->flags, 'lineno' => $node->lineno, 'endLineno' => $node->endLineno, 'name' => strpos($current_scope, '::') === false ? $namespace . $node->name : $node->name, 'docComment' => $node->docComment, 'params' => node_paramlist($file, $node->children[0], $req, $opt, $dc, $namespace), 'required' => $req, 'optional' => $opt, 'ret' => '', 'oret' => '', 'ast' => $node->children[2]]; if ($node->children[3] !== null) { $result['oret'] = ast_node_type($file, $node->children[3], $namespace); // Original return type $result['ret'] = ast_node_type($file, $node->children[3], $namespace); // This one changes as we walk the tree } else { // Check if the docComment has a return value specified if (!empty($dc['return'])) { if ($dc['return'] == 'static' || $dc['return'] == 'self' || $dc['return'] == '$this') { if (strpos($current_scope, '::') !== false) { list($dc['return'], ) = explode('::', $current_scope); } } $result['oret'] = $dc['return']; $result['ret'] = $dc['return']; } } // Add params to local scope for user functions if ($file != 'internal') { $i = 1; foreach ($result['params'] as $k => $v) { if (empty($v['type'])) { // If there is no type specified in PHP, check for a docComment // We assume order in the docComment matches the parameter order in the code if (!empty($dc['params'][$k]['type'])) { $scope[$current_scope]['vars'][$v['name']] = ['type' => $dc['params'][$k]['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } else { $scope[$current_scope]['vars'][$v['name']] = ['type' => '', 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } } else { $scope[$current_scope]['vars'][$v['name']] = ['type' => $v['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } if (array_key_exists('def', $v)) { $type = node_type($file, $namespace, $v['def'], $current_scope, $current_class); if ($type === "NULL") { add_type($current_scope, $v['name'], $type); if (!empty($result['params'][$k]['type'])) { $result['params'][$k]['type'] .= '|NULL'; } } else { if ($scope[$current_scope]['vars'][$v['name']]['type'] !== '') { // Does the default value match the declared type? if (!type_check($type, $scope[$current_scope]['vars'][$v['name']]['type'])) { Log::err(Log::ETYPE, "Default value for {$scope[$current_scope]['vars'][$v['name']]['type']} \${$v['name']} can't be {$type}", $file, $node->lineno); } } } } $i++; } } return $result; } assert(false, "{$node} was not an \\ast\\Node"); }
function parseJsonAst($ast) { assert_ast_type($ast, [NodeType::JSON_INLINE, NodeType::JSON_FILE]); $type = ast_node_type($ast); switch ($type) { case NodeType::JSON_INLINE: return parseJsonInline($ast); break; case NodeType::JSON_FILE: return parseJsonFile($ast); break; } }
function parseProgramHeaders($ast) { $headers = ast_get($ast, NodeKey::HEADER); ob_start(); // Generate standard header with date of generation and copyright notice echo '// This file was automatically generated on ' . date('l jS \\of F Y h:i:s A') . PHP_EOL; echo '// Copyright 2013 Tera Insights, LLC. All Rights Reserved' . PHP_EOL; // Echo out the standard headers. echo <<<'EOT' // Including GrokIt headers #include <climits> #include <fstream> #include "HashFunctions.h" #include "WorkDescription.h" #include "ExecEngineData.h" #include "Chunk.h" #include "DataTypes.h" #include "MMappedStorage.h" #include "ColumnIterator.h" #include "ColumnIterator.cc" #include "BString.h" #include "BStringIterator.h" #include "Constants.h" #include "QueryManager.h" #include <string.h> #include "Logging.h" // for profiling facility #include "Profiling.h" #include "WPFExitCodes.h" #include "HashFunctions.h" #include "Null.h" EOT; // Implicit using base $base_dir = getenv('GROKIT_INSTALLED_LIBRARY_PATH'); include_once $base_dir . DIRECTORY_SEPARATOR . 'base.php'; foreach ($headers as $h) { $type = ast_node_type($h); switch ($type) { case NodeType::IMPORT: parseImport($h); break; case NodeType::DT: parseDataType($h); break; case NodeType::GLA: $res = parseGLA($h); $res->apply([], []); break; case NodeType::GT: $res = parseGT($h); $res->apply([], []); break; case NodeType::GF: $res = parseGF($h); $res->apply([]); break; case NodeType::GIST: $res = parseGIST($h); $res->apply([]); break; case NodeType::GI: $res = parseGI($h); $res->apply([]); break; } } $ret = ob_get_clean(); return $ret; }
function node_func($file, $conditional, $node, $current_scope, $namespace = '') { global $scope; if ($node instanceof \ast\Node) { $req = $opt = 0; $dc = ['return' => '', 'params' => []]; if (!empty($node->docComment)) { $dc = parse_doc_comment($node->docComment); } $result = ['file' => $file, 'scope' => $current_scope, 'conditional' => $conditional, 'flags' => $node->flags, 'lineno' => $node->lineno, 'endLineno' => $node->endLineno, 'name' => $namespace . $node->name, 'docComment' => $node->docComment, 'params' => node_paramlist($file, $node->children[0], $req, $opt, $dc), 'required' => $req, 'optional' => $opt, 'ast' => $node->children[2]]; if ($node->children[3] !== null) { $result['oret'] = ast_node_type($node->children[3]); // Original return type $result['ret'] = ast_node_type($node->children[3]); // This one changes as we walk the tree } else { // Check if the docComment has a return value specified if (!empty($dc['return'])) { $result['oret'] = $dc['return']; $result['ret'] = $dc['return']; } } // Add params to local scope for user functions if ($file != 'internal') { $i = 1; foreach ($result['params'] as $k => $v) { if (empty($v['type'])) { // If there is no type specified in PHP, check for a docComment // We assume order in the docComment matches the parameter order in the code if (!empty($dc['params'][$k]['type'])) { $scope[$current_scope]['vars'][$v['name']] = ['type' => $dc['params'][$k]['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } else { if (!empty($v['def'])) { $scope[$current_scope]['vars'][$v['name']] = ['type' => node_type($file, $v['def'], $current_scope), 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } else { $scope[$current_scope]['vars'][$v['name']] = ['type' => '', 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } } } else { $scope[$current_scope]['vars'][$v['name']] = ['type' => $v['type'], 'tainted' => false, 'tainted_by' => '', 'param' => $i]; } $i++; } } return $result; } assert(false, "{$node} was not an \\ast\\Node"); }