1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_FUNCTIONDECLARATION
9#define SKSL_FUNCTIONDECLARATION
10
11#include "src/sksl/ir/SkSLExpression.h"
12#include "src/sksl/ir/SkSLModifiers.h"
13#include "src/sksl/ir/SkSLSymbol.h"
14#include "src/sksl/ir/SkSLSymbolTable.h"
15#include "src/sksl/ir/SkSLType.h"
16#include "src/sksl/ir/SkSLVariable.h"
17
18#include <atomic>
19
20namespace SkSL {
21
22struct FunctionDefinition;
23
24/**
25 * A function declaration (not a definition -- does not contain a body).
26 */
27struct FunctionDeclaration : public Symbol {
28 FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
29 std::vector<const Variable*> parameters, const Type& returnType,
30 bool builtin)
31 : INHERITED(offset, kFunctionDeclaration_Kind, std::move(name))
32 , fDefinition(nullptr)
33 , fBuiltin(builtin)
34 , fModifiers(modifiers)
35 , fParameters(std::move(parameters))
36 , fReturnType(returnType) {}
37
38 String description() const override {
39 String result = fReturnType.displayName() + " " + fName + "(";
40 String separator;
41 for (auto p : fParameters) {
42 result += separator;
43 separator = ", ";
44 result += p->fType.displayName();
45 }
46 result += ")";
47 return result;
48 }
49
50 bool matches(const FunctionDeclaration& f) const {
51 if (fName != f.fName) {
52 return false;
53 }
54 if (fParameters.size() != f.fParameters.size()) {
55 return false;
56 }
57 for (size_t i = 0; i < fParameters.size(); i++) {
58 if (fParameters[i]->fType != f.fParameters[i]->fType) {
59 return false;
60 }
61 }
62 return true;
63 }
64
65 /**
66 * Determine the effective types of this function's parameters and return value when called with
67 * the given arguments. This is relevant for functions with generic parameter types, where this
68 * will collapse the generic types down into specific concrete types.
69 *
70 * Returns true if it was able to select a concrete set of types for the generic function, false
71 * if there is no possible way this can match the argument types. Note that even a true return
72 * does not guarantee that the function can be successfully called with those arguments, merely
73 * indicates that an attempt should be made. If false is returned, the state of
74 * outParameterTypes and outReturnType are undefined.
75 */
76 bool determineFinalTypes(const std::vector<std::unique_ptr<Expression>>& arguments,
77 std::vector<const Type*>* outParameterTypes,
78 const Type** outReturnType) const {
79 SkASSERT(arguments.size() == fParameters.size());
80 int genericIndex = -1;
81 for (size_t i = 0; i < arguments.size(); i++) {
82 if (fParameters[i]->fType.kind() == Type::kGeneric_Kind) {
83 std::vector<const Type*> types = fParameters[i]->fType.coercibleTypes();
84 if (genericIndex == -1) {
85 for (size_t j = 0; j < types.size(); j++) {
86 if (arguments[i]->fType.canCoerceTo(*types[j])) {
87 genericIndex = j;
88 break;
89 }
90 }
91 if (genericIndex == -1) {
92 return false;
93 }
94 }
95 outParameterTypes->push_back(types[genericIndex]);
96 } else {
97 outParameterTypes->push_back(&fParameters[i]->fType);
98 }
99 }
100 if (fReturnType.kind() == Type::kGeneric_Kind) {
101 if (genericIndex == -1) {
102 return false;
103 }
104 *outReturnType = fReturnType.coercibleTypes()[genericIndex];
105 } else {
106 *outReturnType = &fReturnType;
107 }
108 return true;
109 }
110
111 mutable FunctionDefinition* fDefinition;
112 bool fBuiltin;
113 Modifiers fModifiers;
114 const std::vector<const Variable*> fParameters;
115 const Type& fReturnType;
116 mutable std::atomic<int> fCallCount = 0;
117
118 typedef Symbol INHERITED;
119};
120
121} // namespace SkSL
122
123#endif
124