Index: src/sksl/ir/SkSLFunctionDeclaration.h |
diff --git a/src/sksl/ir/SkSLFunctionDeclaration.h b/src/sksl/ir/SkSLFunctionDeclaration.h |
index ffde0c66c130aedb069da390899b5011eb1cc1af..52a579a89b9e13dbb2f36e22feaf224d0b04fbe8 100644 |
--- a/src/sksl/ir/SkSLFunctionDeclaration.h |
+++ b/src/sksl/ir/SkSLFunctionDeclaration.h |
@@ -8,6 +8,7 @@ |
#ifndef SKSL_FUNCTIONDECLARATION |
#define SKSL_FUNCTIONDECLARATION |
+#include "SkSLExpression.h" |
#include "SkSLModifiers.h" |
#include "SkSLSymbol.h" |
#include "SkSLSymbolTable.h" |
@@ -55,6 +56,50 @@ struct FunctionDeclaration : public Symbol { |
return true; |
} |
+ /** |
+ * Determine the effective types of this function's parameters and return value when called with |
+ * the given arguments. This is relevant for functions with generic parameter types, where this |
+ * will collapse the generic types down into specific concrete types. |
+ * |
+ * Returns true if it was able to select a concrete set of types for the generic function, false |
+ * if there is no possible way this can match the argument types. Note that even a true return |
+ * does not guarantee that the function can be successfully called with those arguments, merely |
+ * indicates that an attempt should be made. If false is returned, the state of |
+ * outParameterTypes and outReturnType are undefined. |
+ */ |
+ bool determineFinalTypes(const std::vector<std::unique_ptr<Expression>>& arguments, |
+ std::vector<const Type*>* outParameterTypes, |
+ const Type** outReturnType) const { |
+ assert(arguments.size() == fParameters.size()); |
+ int genericIndex = -1; |
+ for (size_t i = 0; i < arguments.size(); i++) { |
+ if (fParameters[i]->fType.kind() == Type::kGeneric_Kind) { |
+ std::vector<const Type*> types = fParameters[i]->fType.coercibleTypes(); |
+ if (genericIndex == -1) { |
+ for (size_t j = 0; j < types.size(); j++) { |
+ if (arguments[i]->fType.canCoerceTo(*types[j])) { |
+ genericIndex = j; |
+ break; |
+ } |
+ } |
+ if (genericIndex == -1) { |
+ return false; |
+ } |
+ } |
+ outParameterTypes->push_back(types[genericIndex]); |
+ } else { |
+ outParameterTypes->push_back(&fParameters[i]->fType); |
+ } |
+ } |
+ if (fReturnType.kind() == Type::kGeneric_Kind) { |
+ assert(genericIndex != -1); |
+ *outReturnType = fReturnType.coercibleTypes()[genericIndex]; |
+ } else { |
+ *outReturnType = &fReturnType; |
+ } |
+ return true; |
+ } |
+ |
mutable bool fDefined; |
bool fBuiltin; |
const std::vector<const Variable*> fParameters; |