| 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;
|
|
|