Merge pull request #647 from steve-lunarg/default-fn-params

HLSL: default function parameters
This commit is contained in:
John Kessenich 2017-01-03 15:30:05 -07:00 committed by GitHub
commit c4ed950057
15 changed files with 1263 additions and 24 deletions

View file

@ -629,6 +629,9 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
//
TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
{
if (aggrNode == nullptr)
return aggrNode;
if (! areAllChildConst(aggrNode))
return aggrNode;

View file

@ -348,13 +348,18 @@ const TFunction* TParseContextBase::selectFunction(
for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
const TFunction& candidate = *(*it);
// to even be a potential match, number of arguments has to match
if (call.getParamCount() != candidate.getParamCount())
// to even be a potential match, number of arguments must be >= the number of
// fixed (non-default) parameters, and <= the total (including parameter with defaults).
if (call.getParamCount() < candidate.getFixedParamCount() ||
call.getParamCount() > candidate.getParamCount())
continue;
// see if arguments are convertible
bool viable = true;
for (int param = 0; param < candidate.getParamCount(); ++param) {
// The call can have fewer parameters than the candidate, if some have defaults.
const int paramCount = std::min(call.getParamCount(), candidate.getParamCount());
for (int param = 0; param < paramCount; ++param) {
if (candidate[param].type->getQualifier().isParamInput()) {
if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) {
viable = false;
@ -382,7 +387,7 @@ const TFunction* TParseContextBase::selectFunction(
return viableCandidates.front();
// 4. find best...
auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
// is call -> can2 better than call -> can1 for any parameter
bool hasBetterParam = false;
for (int param = 0; param < call.getParamCount(); ++param) {
@ -394,6 +399,16 @@ const TFunction* TParseContextBase::selectFunction(
return hasBetterParam;
};
const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
// is call -> can2 equivalent to call -> can1 for all the call parameters?
for (int param = 0; param < call.getParamCount(); ++param) {
if (better(*call[param].type, *can1[param].type, *can2[param].type) ||
better(*call[param].type, *can2[param].type, *can1[param].type))
return false;
}
return true;
};
const TFunction* incumbent = viableCandidates.front();
for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
const TFunction& candidate = *(*it);
@ -406,7 +421,10 @@ const TFunction* TParseContextBase::selectFunction(
if (incumbent == *it)
continue;
const TFunction& candidate = *(*it);
if (betterParam(*incumbent, candidate))
// In the case of default parameters, it may have an identical initial set, which is
// also ambiguous
if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate))
tie = true;
}

View file

@ -295,6 +295,7 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
op = copyOf.op;
defined = copyOf.defined;
prototyped = copyOf.prototyped;
defaultParamCount = copyOf.defaultParamCount;
}
TFunction* TFunction::clone() const

View file

@ -191,6 +191,7 @@ protected:
struct TParameter {
TString *name;
TType* type;
TIntermTyped* defaultValue;
void copyParam(const TParameter& param)
{
if (param.name)
@ -198,6 +199,7 @@ struct TParameter {
else
name = 0;
type = param.type->clone();
defaultValue = param.defaultValue;
}
};
@ -209,12 +211,12 @@ public:
explicit TFunction(TOperator o) :
TSymbol(0),
op(o),
defined(false), prototyped(false) { }
defined(false), prototyped(false), defaultParamCount(0) { }
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
TSymbol(name),
mangledName(*name + '('),
op(tOp),
defined(false), prototyped(false) { returnType.shallowCopy(retType); }
defined(false), prototyped(false), defaultParamCount(0) { returnType.shallowCopy(retType); }
virtual TFunction* clone() const;
virtual ~TFunction();
@ -226,6 +228,9 @@ public:
assert(writable);
parameters.push_back(p);
p.type->appendMangledName(mangledName);
if (p.defaultValue != nullptr)
defaultParamCount++;
}
virtual const TString& getMangledName() const { return mangledName; }
@ -238,7 +243,13 @@ public:
virtual void setPrototyped() { assert(writable); prototyped = true; }
virtual bool isPrototyped() const { return prototyped; }
// Return total number of parameters
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
// Return number of parameters with default values.
virtual int getDefaultParamCount() const { return defaultParamCount; }
// Return number of fixed parameters (without default values)
virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
virtual const TParameter& operator[](int i) const { return parameters[i]; }
@ -255,6 +266,7 @@ protected:
TOperator op;
bool defined;
bool prototyped;
int defaultParamCount;
};
//