function parseOperator($ast) { assert_ast_type($ast, NodeType::OPERATOR); $source = ast_node_source($ast); $data = ast_node_data($ast); $name = ast_get($data, NodeKey::NAME); $args = parseExpressionList(ast_get($data, NodeKey::ARGS)); // Special case for integer divison if ($name == "/" && \count($args) == 2 && ($args[0]->type()->is('integral') || $args[1]->type()->is('integral'))) { // We have division, and at least 1 argument is an integer. Force both // to be doubles. $dblType = lookupType('BASE::DOUBLE'); $args[0] = convertExpression($args[0], $dblType, $args[0]->source()); $args[1] = convertExpression($args[1], $dblType, $args[1]->source()); } $arg_types = array_map(function ($item) { return $item->type(); }, $args); try { $func = lookupOperator($name, $arg_types); } catch (Exception $e) { grokit_error('Failed to find operator ' . $name . ' called from ' . $source, $e); } $info = $func->apply($args, $source); // If the function is deterministic and all of the expressions were constant, // just turn this expression into a constant. if ($info->is_const()) { $info->makeConstant(); } return $info; }
function parseSelectionWP($ast, $name, $header) { // Push LibraryManager so we can undo this waypoint's definitions. ob_start(); LibraryManager::Push(); $res = new GenerationInfo(); /*************** PROCESS AST ***************/ $attMap = parseAttributeMap(ast_get($ast, NodeKey::ATT_MAP), $res); $qFilters = ast_get($ast, NodeKey::FILTERS); $qSynth = ast_get($ast, NodeKey::SYNTH); $queries = []; foreach ($qFilters as $query => $qInfo) { $filterAST = ast_get($qInfo, NodeKey::ARGS); $gfAST = ast_get($qInfo, NodeKey::TYPE); if ($gfAST !== null) { $filter = parseNamedExpressionList($filterAST); } else { $filter = parseExpressionList($filterAST); } $gf = null; if ($gfAST !== null) { $gf = parseGF($gfAST); $gf = $gf->apply($filter); } if (ast_has($qInfo, NodeKey::CARGS)) { $cargs = parseLiteralList(ast_get($qInfo, NodeKey::CARGS)); } else { $cargs = []; } $sargs = ast_has($qInfo, NodeKey::SARGS) ? parseStateList(ast_get($qInfo, NodeKey::SARGS), $query) : []; $synths = array(); $synthAST = ast_get($ast, NodeKey::SYNTH); if (ast_has($synthAST, $query)) { $curSynths = ast_get($synthAST, $query); foreach ($curSynths as $curSynthAST) { $expr = parseExpression(ast_get($curSynthAST, NodeKey::EXPR)); $att = parseAttribute(ast_get($curSynthAST, NodeKey::ATT)); if ($att->type() == null) { AttributeManager::setAttributeType($att->name(), $expr->type()); $att = AttributeManager::lookupAttribute($att->name()); } else { if (canConvert($expr, $att->type())) { $expr = convertExpression($expr, $att->type()); } else { grokit_error('Unable to convert expression for synthesized attribute ' . $att->name() . ' from type ' . $expr->type() . ' to type ' . $att->type() . ' ' . $expr->source()); } } $synths[$att->name()] = $expr; } } $info = ['filters' => $filter, 'synths' => $synths, 'gf' => $gf, 'cargs' => $cargs, 'states' => $sargs]; $queries[$query] = $info; $res->addJob($query, $name); $res->absorbInfoList($filter); $res->absorbInfoList($synths); $res->absorbInfoList($cargs); $res->absorbStateList($sargs); if ($gf !== null) { $res->absorbInfo($gf); } } /*************** END PROCESS AST ***************/ // Get this waypoint's headers $myHeaders = $header . PHP_EOL . ob_get_clean(); // Only one file at the moment $filename = $name . '.cc'; $res->addFile($filename, $name); _startFile($filename); SelectionGenerate($name, $queries, $attMap); _endFile($filename, $myHeaders); // Pop LibraryManager again to get rid of this waypoint's declarations LibraryManager::Pop(); return $res; }