blob: 6cea9e69e7d26fb061371b4e22950113eeb4e82b [file] [log] [blame]
//===--- OperatorNameLookup.h - Operator and Precedence Lookup --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces for looking up operator and precedence group
// declarations.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_OPERATOR_NAME_LOOKUP_H
#define SWIFT_AST_OPERATOR_NAME_LOOKUP_H
#include "swift/AST/Identifier.h"
#include "swift/AST/Module.h"
#include "llvm/ADT/TinyPtrVector.h"
namespace swift {
/// Base class for infix operator and precedence group lookup results.
template <typename Derived, typename DeclTy>
class OperatorLookupResultBase {
protected:
const DeclContext *ModuleDC;
Identifier Name;
TinyPtrVector<DeclTy *> Results;
private:
const Derived &asDerived() const {
return *static_cast<const Derived *>(this);
}
public:
OperatorLookupResultBase(const DeclContext *moduleDC, Identifier name,
TinyPtrVector<DeclTy *> &&results)
: ModuleDC(moduleDC), Name(name), Results(std::move(results)) {}
/// Retrieve the underlying results vector.
TinyPtrVector<DeclTy *> get() && { return std::move(Results); }
/// If the lookup produced a single result, returns it. Otherwise returns
/// \c nullptr.
DeclTy *getSingle() const {
return Results.size() == 1 ? Results[0] : nullptr;
}
/// If the lookup produced a single result, returns it. Otherwise, emits an
/// ambiguity or missing decl diagnostic, and returns \c nullptr.
DeclTy *getSingleOrDiagnose(SourceLoc loc, bool forBuiltin = false) const {
if (auto single = getSingle())
return single;
if (isAmbiguous()) {
asDerived().diagnoseAmbiguity(loc);
} else {
assert(!hasResults());
asDerived().diagnoseMissing(loc, forBuiltin);
}
return nullptr;
}
using const_iterator = typename decltype(Results)::const_iterator;
const_iterator begin() const { return Results.begin(); }
const_iterator end() const { return Results.end(); }
/// Whether the lookup produced at least one result.
bool hasResults() const { return !Results.empty(); }
/// Whether the lookup produced multiple ambiguous results.
bool isAmbiguous() const { return Results.size() > 1; }
friend bool operator==(const OperatorLookupResultBase &lhs,
const OperatorLookupResultBase &rhs) {
return lhs.Results == rhs.Results;
}
friend bool operator!=(const OperatorLookupResultBase &lhs,
const OperatorLookupResultBase &rhs) {
return !(lhs == rhs);
}
friend void simple_display(llvm::raw_ostream &out,
const OperatorLookupResultBase &result) {
simple_display(out, result.Results);
}
};
/// The result of a precedence group lookup.
class PrecedenceGroupLookupResult final
: public OperatorLookupResultBase<PrecedenceGroupLookupResult,
PrecedenceGroupDecl> {
friend class OperatorLookupResultBase<PrecedenceGroupLookupResult,
PrecedenceGroupDecl>;
public:
PrecedenceGroupLookupResult(const DeclContext *moduleDC, Identifier name,
TinyPtrVector<PrecedenceGroupDecl *> &&results)
: OperatorLookupResultBase(moduleDC, name, std::move(results)) {}
void diagnoseAmbiguity(SourceLoc loc) const;
void diagnoseMissing(SourceLoc loc, bool forBuiltin) const;
};
/// The result of an infix operator lookup.
class InfixOperatorLookupResult final
: public OperatorLookupResultBase<InfixOperatorLookupResult,
InfixOperatorDecl> {
friend class OperatorLookupResultBase<InfixOperatorLookupResult,
InfixOperatorDecl>;
public:
InfixOperatorLookupResult(const DeclContext *moduleDC, Identifier name,
TinyPtrVector<InfixOperatorDecl *> &&results)
: OperatorLookupResultBase(moduleDC, name, std::move(results)) {}
void diagnoseAmbiguity(SourceLoc loc) const;
void diagnoseMissing(SourceLoc loc, bool forBuiltin) const;
};
} // end namespace swift
#endif