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/SkSLContext.h" 9cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLFieldAccess.h" 10cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLMethodReference.h" 11cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSetting.h" 12cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSymbolTable.h" 13cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLUnresolvedFunction.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_cinamespace SkSL { 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cistd::unique_ptr<Expression> FieldAccess::Convert(const Context& context, 18cb93a386Sopenharmony_ci SymbolTable& symbolTable, 19cb93a386Sopenharmony_ci std::unique_ptr<Expression> base, 20cb93a386Sopenharmony_ci skstd::string_view field) { 21cb93a386Sopenharmony_ci const Type& baseType = base->type(); 22cb93a386Sopenharmony_ci if (baseType.isEffectChild()) { 23cb93a386Sopenharmony_ci // Turn the field name into a free function name, prefixed with '$': 24cb93a386Sopenharmony_ci String methodName = String("$") + field; 25cb93a386Sopenharmony_ci const Symbol* result = symbolTable[methodName]; 26cb93a386Sopenharmony_ci if (result) { 27cb93a386Sopenharmony_ci switch (result->kind()) { 28cb93a386Sopenharmony_ci case Symbol::Kind::kFunctionDeclaration: { 29cb93a386Sopenharmony_ci std::vector<const FunctionDeclaration*> f = { 30cb93a386Sopenharmony_ci &result->as<FunctionDeclaration>()}; 31cb93a386Sopenharmony_ci return std::make_unique<MethodReference>( 32cb93a386Sopenharmony_ci context, base->fLine, std::move(base), f); 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci case Symbol::Kind::kUnresolvedFunction: { 35cb93a386Sopenharmony_ci const UnresolvedFunction& f = result->as<UnresolvedFunction>(); 36cb93a386Sopenharmony_ci return std::make_unique<MethodReference>( 37cb93a386Sopenharmony_ci context, base->fLine, std::move(base), f.functions()); 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci default: 40cb93a386Sopenharmony_ci break; 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci context.fErrors->error( 44cb93a386Sopenharmony_ci base->fLine, 45cb93a386Sopenharmony_ci "type '" + baseType.displayName() + "' has no method named '" + field + "'"); 46cb93a386Sopenharmony_ci return nullptr; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci if (baseType.isStruct()) { 49cb93a386Sopenharmony_ci const std::vector<Type::Field>& fields = baseType.fields(); 50cb93a386Sopenharmony_ci for (size_t i = 0; i < fields.size(); i++) { 51cb93a386Sopenharmony_ci if (fields[i].fName == field) { 52cb93a386Sopenharmony_ci return FieldAccess::Make(context, std::move(base), (int) i); 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci if (baseType == *context.fTypes.fSkCaps) { 57cb93a386Sopenharmony_ci return Setting::Convert(context, base->fLine, field); 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci context.fErrors->error(base->fLine, "type '" + baseType.displayName() + 61cb93a386Sopenharmony_ci "' does not have a field named '" + field + "'"); 62cb93a386Sopenharmony_ci return nullptr; 63cb93a386Sopenharmony_ci} 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_cistd::unique_ptr<Expression> FieldAccess::Make(const Context& context, 66cb93a386Sopenharmony_ci std::unique_ptr<Expression> base, 67cb93a386Sopenharmony_ci int fieldIndex, 68cb93a386Sopenharmony_ci OwnerKind ownerKind) { 69cb93a386Sopenharmony_ci SkASSERT(base->type().isStruct()); 70cb93a386Sopenharmony_ci SkASSERT(fieldIndex >= 0); 71cb93a386Sopenharmony_ci SkASSERT(fieldIndex < (int) base->type().fields().size()); 72cb93a386Sopenharmony_ci return std::make_unique<FieldAccess>(std::move(base), fieldIndex, ownerKind); 73cb93a386Sopenharmony_ci} 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci} // namespace SkSL 76