Index: src/sksl/SkSLIRGenerator.cpp |
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp |
index 0c9ee2032865ec3e35a818ceb9e6facfde3ca60f..07fd9e27b0ade573bae73994bcac6c91163a10d6 100644 |
--- a/src/sksl/SkSLIRGenerator.cpp |
+++ b/src/sksl/SkSLIRGenerator.cpp |
@@ -371,11 +371,40 @@ |
return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition)); |
} |
+static const Type& expand_generics(const Type& type, int i) { |
+ if (type.kind() == Type::kGeneric_Kind) { |
+ return *type.coercibleTypes()[i]; |
+ } |
+ return type; |
+} |
+ |
+static void expand_generics(const FunctionDeclaration& decl, |
+ std::shared_ptr<SymbolTable> symbolTable) { |
+ for (int i = 0; i < 4; i++) { |
+ const Type& returnType = expand_generics(decl.fReturnType, i); |
+ std::vector<const Variable*> parameters; |
+ for (const auto& p : decl.fParameters) { |
+ Variable* var = new Variable(p->fPosition, Modifiers(p->fModifiers), p->fName, |
+ expand_generics(p->fType, i), |
+ Variable::kParameter_Storage); |
+ symbolTable->takeOwnership(var); |
+ parameters.push_back(var); |
+ } |
+ symbolTable->add(decl.fName, std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration( |
+ decl.fPosition, |
+ decl.fName, |
+ std::move(parameters), |
+ std::move(returnType)))); |
+ } |
+} |
+ |
std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFunction& f) { |
+ bool isGeneric; |
const Type* returnType = this->convertType(*f.fReturnType); |
if (!returnType) { |
return nullptr; |
} |
+ isGeneric = returnType->kind() == Type::kGeneric_Kind; |
std::vector<const Variable*> parameters; |
for (const auto& param : f.fParameters) { |
const Type* type = this->convertType(*param->fType); |
@@ -396,6 +425,7 @@ |
Variable::kParameter_Storage); |
fSymbolTable->takeOwnership(var); |
parameters.push_back(var); |
+ isGeneric |= type->kind() == Type::kGeneric_Kind; |
} |
// find existing declaration |
@@ -453,12 +483,19 @@ |
} |
if (!decl) { |
// couldn't find an existing declaration |
- auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fPosition, |
- f.fName, |
- parameters, |
- *returnType)); |
- decl = newDecl.get(); |
- fSymbolTable->add(decl->fName, std::move(newDecl)); |
+ if (isGeneric) { |
+ ASSERT(!f.fBody); |
+ expand_generics(FunctionDeclaration(f.fPosition, f.fName, parameters, *returnType), |
+ fSymbolTable); |
+ } else { |
+ auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration( |
+ f.fPosition, |
+ f.fName, |
+ parameters, |
+ *returnType)); |
+ decl = newDecl.get(); |
+ fSymbolTable->add(decl->fName, std::move(newDecl)); |
+ } |
} |
if (f.fBody) { |
ASSERT(!fCurrentFunction); |
@@ -878,22 +915,8 @@ |
fErrors.error(position, msg); |
return nullptr; |
} |
- std::vector<const Type*> types; |
- const Type* returnType; |
- if (!function.determineFinalTypes(arguments, &types, &returnType)) { |
- std::string msg = "no match for " + function.fName + "("; |
- std::string separator = ""; |
- for (size_t i = 0; i < arguments.size(); i++) { |
- msg += separator; |
- separator = ", "; |
- msg += arguments[i]->fType.description(); |
- } |
- msg += ")"; |
- fErrors.error(position, msg); |
- return nullptr; |
- } |
for (size_t i = 0; i < arguments.size(); i++) { |
- arguments[i] = this->coerce(std::move(arguments[i]), *types[i]); |
+ arguments[i] = this->coerce(std::move(arguments[i]), function.fParameters[i]->fType); |
if (!arguments[i]) { |
return nullptr; |
} |
@@ -901,7 +924,7 @@ |
this->markWrittenTo(*arguments[i]); |
} |
} |
- return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function, |
+ return std::unique_ptr<FunctionCall>(new FunctionCall(position, function, |
std::move(arguments))); |
} |
@@ -917,14 +940,9 @@ |
return false; |
} |
int total = 0; |
- std::vector<const Type*> types; |
- const Type* ignored; |
- if (!function.determineFinalTypes(arguments, &types, &ignored)) { |
- return false; |
- } |
for (size_t i = 0; i < arguments.size(); i++) { |
int cost; |
- if (arguments[i]->fType.determineCoercionCost(*types[i], &cost)) { |
+ if (arguments[i]->fType.determineCoercionCost(function.fParameters[i]->fType, &cost)) { |
total += cost; |
} else { |
return false; |