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