Ejemplo n.º 1
0
 /**
  *  Returns an integer describing the compatibility of the function
  *  with the given types.
  *
  *  @returns -1 if incompatible
  *      0 if perfectly compatible
  *      otherwise the number of implicit conversions required to make compatible
  */
 public function compatibility(array $types, $exact = false)
 {
     if (count($types) != count($this->args)) {
         return -1;
     }
     $types = array_map("strtoupper", $types);
     $rating = 0;
     foreach ($this->args as $name => $expected) {
         $given = $types[$name];
         if ($expected != $given) {
             if ($exact) {
                 return -1;
             }
             if (canConvert($given, $expected)) {
                 $rating += 1;
             } else {
                 return -1;
             }
         }
     }
     return $rating;
 }
Ejemplo n.º 2
0
function parseCaseNoBase(&$source, &$cases, &$default)
{
    // The return type of the tests must be boolean
    $testRetType = lookupType('bool');
    // We don't know the return type yet, it will be defined by the cases.
    $retType = null;
    $retSource = null;
    // Generate a name for the return value of the case.
    $value_name = generate_name("case_value");
    $prep = [];
    $info = new ExpressionInfo($source, null, $value_name, true);
    grokit_logic_assert(count($cases) > 0, 'No cases found for case statement at ' . $source);
    // Handle cases
    foreach ($cases as $case) {
        $test = parseExpression(ast_get($case, NodeKey::TEST));
        $expr = parseExpression(ast_get($case, NodeKey::EXPR));
        $first = false;
        // Test if the return type of the test is compatible with boolean
        if (canConvert($test->type(), $testRetType)) {
            $test = convertExpression($test, $testRetType, $retSource);
        } else {
            // Incompatible types
            grokit_error('Case test expression has return type ' . $test->type() . ' which is incompatible with boolean ' . $test->source());
        }
        // If the return type is not set, set it and continue.
        // Otherwise, make sure the expression's return type is compatible with
        // the already set return type.
        if ($retType === null) {
            $retType = $expr->type();
            $retSource = $expr->source();
            $first = true;
            $info->setType($retType);
        } else {
            if (canConvert($expr->type(), $retType)) {
                // The types are compatible or the same, so make them the same.
                $expr = convertExpression($expr, $retType, $retSource);
            } else {
                // Incompatible types
                grokit_error('Case return type ' . $expr->type() . ' of expression at ' . $expr->source() . ' incompatible with previous return type ' . $retType . ' defined by expression at ' . $retSource);
            }
        }
        // Absorb the metadata from the test and expression into our info
        $info->absorbMeta($test);
        $info->absorbMeta($expr);
        $myPrep = '';
        if (!$first) {
            $myPrep .= 'else ';
        }
        $myPrep .= "if( {$test->value()} ) {$value_name} = {$expr->value()};";
        $prep[] = $myPrep;
    }
    // Handle default
    if ($default !== null) {
        if (canConvert($default->type(), $retType)) {
            $default = convertExpression($default, $retType, $retSource);
        } else {
            // Incompatible types.
            grokit_error('Case return type ' . $default->type() . ' of default at ' . $default->source() . ' incompatible with previous return type ' . $retType . ' defined by expression at ' . $retSource);
        }
        $info->absorbMeta($default);
        $prep[] = "else {$value_name} = {$default->value()};";
    }
    // Prepend the declaration of the return variable
    array_unshift($prep, "{$retType} {$value_name};");
    // Add all of our stuff as preprocesses
    $info->addPreprocesses($prep);
    if ($info->is_const()) {
        $info->makeConstant();
    }
    return $info;
}
Ejemplo n.º 3
0
 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;
 }
Ejemplo n.º 4
0
 protected function CheckFuzzy(array &$expected, array &$exprs, $type)
 {
     //fwrite(STDERR, "CheckFuzzy: " . print_r($exprs,true) . PHP_EOL);
     $nGiven = \count($exprs);
     $nExpected = \count($expected);
     grokit_assert($nExpected == $nGiven, 'Unable to apply ' . $this . ' to given ' . $type . 's: Expected ' . $nExpected . ' ' . $type . 's, received ' . $nGiven);
     if ($nGiven == 0) {
         return;
     }
     $expectKeys = array_keys($expected);
     reset($expected);
     reset($exprs);
     foreach (range(0, $nExpected - 1) as $i) {
         $cExpected = current($expected);
         $cGiven = current($exprs);
         $cGivenType = is_datatype($cGiven) ? $cGiven : $cGiven->type();
         grokit_assert(canConvert($cGivenType, $cExpected), 'Unable to apply ' . $this . ' to given ' . $type . 's: ' . '' . $type . ' at position ' . $i . ' of type ' . $cGiven->type() . ' not compatible with ' . 'expected type ' . $cExpected);
         if (is_expression($cGiven)) {
             $exprs[key($exprs)] = convertExpression($cGiven, $cExpected);
         }
         next($expected);
         next($exprs);
     }
 }