Пример #1
0
function parseCaseBase(&$source, &$base, &$cases, &$default)
{
    $base_name = generate_name("case_base");
    $base_value = $base->type() . " " . $base_name . " = " . $base->value() . ";";
    $retType = null;
    $retSource = null;
    $prep = [];
    $value_name = generate_name("case_value");
    $info = new ExpressionInfo($source, null, $value_name, true);
    $info->absorbMeta($base);
    grokit_logic_assert(count($cases) > 0, 'No cases found for case statement with base at ' . $source);
    // Handle cases
    foreach ($cases as $case) {
        $test = parseExpression(ast_get($case, NodeKey::TEST));
        $expr = parseExpression(ast_get($case, NodeKey::EXPR));
        $first = false;
        // TODO: Test if == operator exists between test and base
        // If the return type is not set, set it.
        // Otherwise, make sure that 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)) {
                // They aren't the same but we can perform an implicit conversion
                // to make them the same, so do so.
                $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);
            }
        }
        $info->absorbMeta($test);
        $info->absorbMeta($expr);
        $myPrep = '';
        if (!$first) {
            $myPrep .= 'else ';
        }
        $myPrep .= "if( {$base_name} == {$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 variable that holds the return value of the case.
    array_unshift($prep, "{$retType} {$value_name};");
    // If base expression is constant, add to constants, otherwise to preprocessing.
    if ($base->is_const()) {
        $info->addConstant($base_value);
    } else {
        $info->addPreprocess($base_value);
    }
    $info->addPreprocesses($prep);
    // If everything was constant, transform the expression into a constant
    if ($info->is_const()) {
        $info->makeConstant();
    }
    $testRetType = lookupType('bool');
}