1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLTernaryExpression.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/sksl/SkSLErrorReporter.h" 11cb93a386Sopenharmony_ci#include "src/sksl/SkSLConstantFolder.h" 12cb93a386Sopenharmony_ci#include "src/sksl/SkSLContext.h" 13cb93a386Sopenharmony_ci#include "src/sksl/SkSLOperators.h" 14cb93a386Sopenharmony_ci#include "src/sksl/SkSLProgramSettings.h" 15cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLLiteral.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cinamespace SkSL { 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cistd::unique_ptr<Expression> TernaryExpression::Convert(const Context& context, 20cb93a386Sopenharmony_ci std::unique_ptr<Expression> test, 21cb93a386Sopenharmony_ci std::unique_ptr<Expression> ifTrue, 22cb93a386Sopenharmony_ci std::unique_ptr<Expression> ifFalse) { 23cb93a386Sopenharmony_ci test = context.fTypes.fBool->coerceExpression(std::move(test), context); 24cb93a386Sopenharmony_ci if (!test || !ifTrue || !ifFalse) { 25cb93a386Sopenharmony_ci return nullptr; 26cb93a386Sopenharmony_ci } 27cb93a386Sopenharmony_ci int line = test->fLine; 28cb93a386Sopenharmony_ci const Type* trueType; 29cb93a386Sopenharmony_ci const Type* falseType; 30cb93a386Sopenharmony_ci const Type* resultType; 31cb93a386Sopenharmony_ci Operator equalityOp(Token::Kind::TK_EQEQ); 32cb93a386Sopenharmony_ci if (!equalityOp.determineBinaryType(context, ifTrue->type(), ifFalse->type(), 33cb93a386Sopenharmony_ci &trueType, &falseType, &resultType) || 34cb93a386Sopenharmony_ci (*trueType != *falseType)) { 35cb93a386Sopenharmony_ci context.fErrors->error(line, "ternary operator result mismatch: '" + 36cb93a386Sopenharmony_ci ifTrue->type().displayName() + "', '" + 37cb93a386Sopenharmony_ci ifFalse->type().displayName() + "'"); 38cb93a386Sopenharmony_ci return nullptr; 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci if (trueType->componentType().isOpaque()) { 41cb93a386Sopenharmony_ci context.fErrors->error(line, "ternary expression of opaque type '" + 42cb93a386Sopenharmony_ci trueType->displayName() + "' not allowed"); 43cb93a386Sopenharmony_ci return nullptr; 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci if (context.fConfig->strictES2Mode() && trueType->isOrContainsArray()) { 46cb93a386Sopenharmony_ci context.fErrors->error(line, "ternary operator result may not be an array (or struct " 47cb93a386Sopenharmony_ci "containing an array)"); 48cb93a386Sopenharmony_ci return nullptr; 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci ifTrue = trueType->coerceExpression(std::move(ifTrue), context); 51cb93a386Sopenharmony_ci if (!ifTrue) { 52cb93a386Sopenharmony_ci return nullptr; 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci ifFalse = falseType->coerceExpression(std::move(ifFalse), context); 55cb93a386Sopenharmony_ci if (!ifFalse) { 56cb93a386Sopenharmony_ci return nullptr; 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci return TernaryExpression::Make(context, std::move(test), std::move(ifTrue), std::move(ifFalse)); 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_cistd::unique_ptr<Expression> TernaryExpression::Make(const Context& context, 62cb93a386Sopenharmony_ci std::unique_ptr<Expression> test, 63cb93a386Sopenharmony_ci std::unique_ptr<Expression> ifTrue, 64cb93a386Sopenharmony_ci std::unique_ptr<Expression> ifFalse) { 65cb93a386Sopenharmony_ci SkASSERT(ifTrue->type() == ifFalse->type()); 66cb93a386Sopenharmony_ci SkASSERT(!ifTrue->type().componentType().isOpaque()); 67cb93a386Sopenharmony_ci SkASSERT(!context.fConfig->strictES2Mode() || !ifTrue->type().isOrContainsArray()); 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci const Expression* testExpr = ConstantFolder::GetConstantValueForVariable(*test); 70cb93a386Sopenharmony_ci if (testExpr->isBoolLiteral()) { 71cb93a386Sopenharmony_ci // static boolean test, just return one of the branches 72cb93a386Sopenharmony_ci return testExpr->as<Literal>().boolValue() ? std::move(ifTrue) 73cb93a386Sopenharmony_ci : std::move(ifFalse); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci return std::make_unique<TernaryExpression>(test->fLine, std::move(test), std::move(ifTrue), 77cb93a386Sopenharmony_ci std::move(ifFalse)); 78cb93a386Sopenharmony_ci} 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci} // namespace SkSL 81