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