mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-15 11:51:22 +00:00
tint: IntrinsicTable: Rename open/closed -> template
The concept of 'closing' an open type or number made sense when these were immutable once the first type/number had been matched during overload resolution. In order to support abstract numerics, these template parameters need to be constrained as the arguments are evaluated, so there's no longer a binary open / closed state. Give up on this concept, and rename everything to 'template type' and 'template number'. This is likely easier for people to understand anyway. Also fix a small typo in the ICE message printed when there's an ambiguous overload resolution (should never happen with the current entries in the table). Bug: tint:1504 Change-Id: I2bf043c71e5afa757259968eae4af830c50f38e0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90662 Commit-Queue: Ben Clayton <bclayton@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
d968e28a9a
commit
4c9ed74b5e
@ -154,7 +154,7 @@ match workgroup_or_storage: workgroup | storage
|
|||||||
// functions supported by the WGSL language. This builtin definition //
|
// functions supported by the WGSL language. This builtin definition //
|
||||||
// language supports simple static-type function declarations, as well as //
|
// language supports simple static-type function declarations, as well as //
|
||||||
// single overload declarations that can match a number of different //
|
// single overload declarations that can match a number of different //
|
||||||
// argument types via the use of 'open-types' and 'open-numbers'. //
|
// argument types via the use of template types and template numbers //
|
||||||
// //
|
// //
|
||||||
// * Basic example: //
|
// * Basic example: //
|
||||||
// //
|
// //
|
||||||
@ -163,10 +163,9 @@ match workgroup_or_storage: workgroup | storage
|
|||||||
// Declares an overload of the function 'isInf' that accepts a single //
|
// Declares an overload of the function 'isInf' that accepts a single //
|
||||||
// parameter of type 'f32' and returns a 'bool'. //
|
// parameter of type 'f32' and returns a 'bool'. //
|
||||||
// //
|
// //
|
||||||
// An 'open-type' can be thought as a template type that is determined by the //
|
// A template type is a type determined by the arguments to the builtin. //
|
||||||
// arguments to the builtin. //
|
|
||||||
// //
|
// //
|
||||||
// * Open-type example without constraint: //
|
// * Template type example without constraint: //
|
||||||
// //
|
// //
|
||||||
// fn arrayLength<T>(array<T>) -> u32 //
|
// fn arrayLength<T>(array<T>) -> u32 //
|
||||||
// //
|
// //
|
||||||
@ -175,7 +174,7 @@ match workgroup_or_storage: workgroup | storage
|
|||||||
// element type. This overload will always return a value of the same type //
|
// element type. This overload will always return a value of the same type //
|
||||||
// as its single argument. //
|
// as its single argument. //
|
||||||
// //
|
// //
|
||||||
// * Open-type example with constraint: //
|
// * Template type example with constraint: //
|
||||||
// //
|
// //
|
||||||
// fn abs<T: fiu32>(T) -> T //
|
// fn abs<T: fiu32>(T) -> T //
|
||||||
// //
|
// //
|
||||||
@ -183,10 +182,10 @@ match workgroup_or_storage: workgroup | storage
|
|||||||
// argument of type 'f32', 'i32' or 'u32', which returns a value of the //
|
// argument of type 'f32', 'i32' or 'u32', which returns a value of the //
|
||||||
// same argument type. //
|
// same argument type. //
|
||||||
// //
|
// //
|
||||||
// Similarly an 'open-number' can be thought as a template number or //
|
// Similarly a template number is a number or enumerator that is determined //
|
||||||
// enumerator that is determined by the arguments to the builtin. //
|
// by the arguments to the builtin. //
|
||||||
// //
|
// //
|
||||||
// * Open-number example: //
|
// * Template number example: //
|
||||||
// //
|
// //
|
||||||
// fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32> //
|
// fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32> //
|
||||||
// //
|
// //
|
||||||
@ -198,51 +197,50 @@ match workgroup_or_storage: workgroup | storage
|
|||||||
// Matching algorithm: //
|
// Matching algorithm: //
|
||||||
// ------------------- //
|
// ------------------- //
|
||||||
// //
|
// //
|
||||||
// Prior to matching an overload, all open-types are undefined. //
|
// Prior to matching an overload, all template types are undefined. //
|
||||||
// //
|
// //
|
||||||
// Open-types become closed-types (pinned to a fixed type) on the first //
|
// Template types become defined on the first attempt to match an argument to //
|
||||||
// attempt to match an argument to that open-type. //
|
// that template type. Once template types are defined, they remain that type //
|
||||||
// Once open-types are closed, they remain that type for the rest of the //
|
// for the rest of the overload evaluation. //
|
||||||
// overload evaluation. //
|
|
||||||
// //
|
// //
|
||||||
// To better understand, let's consider the following hypothetical overload //
|
// To better understand, let's consider the following hypothetical overload //
|
||||||
// declaration: //
|
// declaration: //
|
||||||
// //
|
// //
|
||||||
// fn foo<T: scalar>(T, T); //
|
// fn foo<T: scalar>(T, T); //
|
||||||
// //
|
// //
|
||||||
// T - is the open-type //
|
// T - is the template type name //
|
||||||
// scalar - is a matcher for the types 'f32', 'i32', 'u32' or 'bool' //
|
// scalar - is a matcher for the types 'f32', 'i32', 'u32' or 'bool' //
|
||||||
// (declared above) //
|
// (declared above) //
|
||||||
// <T: scalar> - declares the open-type T, with the constraint that T must //
|
// <T: scalar> - declares the template type T, with the constraint that T //
|
||||||
// match one of 'f32', 'i32', 'u32' or 'bool'. //
|
// must match one of 'f32', 'i32', 'u32' or 'bool'. //
|
||||||
// //
|
// //
|
||||||
// The process for resolving this overload is as follows: //
|
// The process for resolving this overload is as follows: //
|
||||||
// //
|
// //
|
||||||
// (1) The overload resolver begins by attempting to match the argument //
|
// (1) The overload resolver begins by attempting to match the argument //
|
||||||
// types from left to right. //
|
// types from left to right. //
|
||||||
// The first parameter type is compared against the argument type. //
|
// The first parameter type is compared against the argument type T. //
|
||||||
// As the open-type T has not been closed yet, T is closed as the type //
|
// As the template type T has not been defined yet, T is defined as the //
|
||||||
// of the first argument. //
|
// type of the first argument. //
|
||||||
// There's no verification that the T type is a scalar at this stage. //
|
// There's no verification that the T type is a scalar at this stage. //
|
||||||
// (2) The second parameter is then compared against the second argument. //
|
// (2) The second parameter is then compared against the second argument. //
|
||||||
// As the open-type T is now closed, the argument type is compared //
|
// As the template type T is now defined the argument type is compared //
|
||||||
// against the value of the closed-type of T. If the types match, then //
|
// against the value of the defined type of T. If the types match, then //
|
||||||
// the overload is still a candidate for matching, otherwise the //
|
// the overload is still a candidate for matching, otherwise the //
|
||||||
// overload is no longer considered. //
|
// overload is no longer considered. //
|
||||||
// (3) If all the parameters matched, constraints on the open-types need //
|
// (3) If all the parameters matched, constraints on the template types //
|
||||||
// to be checked next. If the closed-type does not match the 'match' //
|
// need to be checked next. If the defined type does not match the //
|
||||||
// constraint, then the overload is no longer considered. //
|
// 'match' constraint, then the overload is no longer considered. //
|
||||||
// //
|
// //
|
||||||
// The algorithm for matching open-numbers is almost identical to open-types, //
|
// The algorithm for matching template numbers is almost identical to //
|
||||||
// except of course, they match against integer numbers or enumerators //
|
// matching template types, except of course, they match against integer //
|
||||||
// instead of types. //
|
// numbers or enumerators instead of types. //
|
||||||
// //
|
// //
|
||||||
// //
|
// //
|
||||||
// * More examples: //
|
// * More examples: //
|
||||||
// //
|
// //
|
||||||
// fn F() //
|
// fn F() //
|
||||||
// - Function called F. //
|
// - Function called F. //
|
||||||
// No open types or numbers, no parameters, no return value //
|
// No template types or numbers, no parameters, no return value //
|
||||||
// //
|
// //
|
||||||
// fn F() -> RETURN_TYPE //
|
// fn F() -> RETURN_TYPE //
|
||||||
// - Function with RETURN_TYPE as the return type value //
|
// - Function with RETURN_TYPE as the return type value //
|
||||||
@ -256,21 +254,21 @@ match workgroup_or_storage: workgroup | storage
|
|||||||
// some builtin functions //
|
// some builtin functions //
|
||||||
// //
|
// //
|
||||||
// fn F<T>(T) //
|
// fn F<T>(T) //
|
||||||
// - Single parameter of unconstrained open-type T (any type) //
|
// - Single parameter of unconstrained template type T (any type) //
|
||||||
// //
|
// //
|
||||||
// fn F<T: scalar>(T) //
|
// fn F<T: scalar>(T) //
|
||||||
// - Single parameter of constrained open-type T (must be a scalar) //
|
// - Single parameter of constrained template type T (must be a scalar) //
|
||||||
// //
|
// //
|
||||||
// fn F<T: fiu32>(T) -> T //
|
// fn F<T: fiu32>(T) -> T //
|
||||||
// - Single parameter of constrained open-type T (must be a one of fiu32) //
|
// - Single parameter of constrained template type T (must be a one of //
|
||||||
// Return type matches parameter type //
|
// fiu32) Return type matches parameter type //
|
||||||
// //
|
// //
|
||||||
// fn F<T, N: num>(vec<N, T>) //
|
// fn F<T, N: num>(vec<N, T>) //
|
||||||
// - Single parameter of vector type with open-number size N and element //
|
// - Single parameter of vector type with template number size N and //
|
||||||
// open-type T //
|
// element template type T //
|
||||||
// //
|
// //
|
||||||
// fn F<A: access>(texture_storage_1d<f32_texel_format, A>) //
|
// fn F<A: access>(texture_storage_1d<f32_texel_format, A>) //
|
||||||
// - Single parameter of texture_storage_1d type with open-number //
|
// - Single parameter of texture_storage_1d type with template number //
|
||||||
// access-control C, and of a texel format that is listed in //
|
// access-control C, and of a texel format that is listed in //
|
||||||
// f32_texel_format //
|
// f32_texel_format //
|
||||||
// //
|
// //
|
||||||
|
@ -100,34 +100,33 @@ struct Number {
|
|||||||
const Number Number::any{Number::kAny};
|
const Number Number::any{Number::kAny};
|
||||||
const Number Number::invalid{Number::kInvalid};
|
const Number Number::invalid{Number::kInvalid};
|
||||||
|
|
||||||
/// ClosedState holds the state of the open / closed numbers and types.
|
/// TemplateState holds the state of the template numbers and types.
|
||||||
/// Used by the MatchState.
|
/// Used by the MatchState.
|
||||||
class ClosedState {
|
class TemplateState {
|
||||||
public:
|
public:
|
||||||
/// If the type with index `idx` is open, then it is closed with type `ty` and
|
/// If the type with index `idx` is undefined, then it is defined with type `ty` and Type()
|
||||||
/// Type() returns true. If the type is closed, then `Type()` returns true iff
|
/// returns true. If the template type is defined, then `Type()` returns true iff it is equal to
|
||||||
/// it is equal to `ty`.
|
/// `ty`.
|
||||||
bool Type(size_t idx, const sem::Type* ty) {
|
bool Type(size_t idx, const sem::Type* ty) {
|
||||||
auto res = types_.emplace(idx, ty);
|
auto res = types_.emplace(idx, ty);
|
||||||
return res.second || res.first->second == ty;
|
return res.second || res.first->second == ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the number with index `idx` is open, then it is closed with number
|
/// If the number with index `idx` is undefined, then it is defined with the number `number` and
|
||||||
/// `number` and Num() returns true. If the number is closed, then `Num()`
|
/// Num() returns true. If the number is defined, then `Num()` returns true iff it is equal to
|
||||||
/// returns true iff it is equal to `ty`.
|
/// `ty`.
|
||||||
bool Num(size_t idx, Number number) {
|
bool Num(size_t idx, Number number) {
|
||||||
auto res = numbers_.emplace(idx, number.Value());
|
auto res = numbers_.emplace(idx, number.Value());
|
||||||
return res.second || res.first->second == number.Value();
|
return res.second || res.first->second == number.Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type returns the closed type with index `idx`, or nullptr if the type was not closed.
|
/// Type returns the template type with index `idx`, or nullptr if the type was not defined.
|
||||||
const sem::Type* Type(size_t idx) const {
|
const sem::Type* Type(size_t idx) const {
|
||||||
auto it = types_.find(idx);
|
auto it = types_.find(idx);
|
||||||
return (it != types_.end()) ? it->second : nullptr;
|
return (it != types_.end()) ? it->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type returns the number type with index `idx`.
|
/// Type returns the number type with index `idx`.
|
||||||
/// An ICE is raised if the number is not closed.
|
|
||||||
Number Num(size_t idx) const {
|
Number Num(size_t idx) const {
|
||||||
auto it = numbers_.find(idx);
|
auto it = numbers_.find(idx);
|
||||||
return (it != numbers_.end()) ? Number(it->second) : Number::invalid;
|
return (it != numbers_.end()) ? Number(it->second) : Number::invalid;
|
||||||
@ -141,23 +140,23 @@ class ClosedState {
|
|||||||
/// Index type used for matcher indices
|
/// Index type used for matcher indices
|
||||||
using MatcherIndex = uint8_t;
|
using MatcherIndex = uint8_t;
|
||||||
|
|
||||||
/// Index value used for open types / numbers that do not have a constraint
|
/// Index value used for template types / numbers that do not have a constraint
|
||||||
constexpr MatcherIndex kNoMatcher = std::numeric_limits<MatcherIndex>::max();
|
constexpr MatcherIndex kNoMatcher = std::numeric_limits<MatcherIndex>::max();
|
||||||
|
|
||||||
/// MatchState holds the state used to match an overload.
|
/// MatchState holds the state used to match an overload.
|
||||||
class MatchState {
|
class MatchState {
|
||||||
public:
|
public:
|
||||||
MatchState(ProgramBuilder& b,
|
MatchState(ProgramBuilder& b,
|
||||||
ClosedState& c,
|
TemplateState& t,
|
||||||
const Matchers& m,
|
const Matchers& m,
|
||||||
const OverloadInfo* o,
|
const OverloadInfo* o,
|
||||||
MatcherIndex const* matcher_indices)
|
MatcherIndex const* matcher_indices)
|
||||||
: builder(b), closed(c), matchers(m), overload(o), matcher_indices_(matcher_indices) {}
|
: builder(b), templates(t), matchers(m), overload(o), matcher_indices_(matcher_indices) {}
|
||||||
|
|
||||||
/// The program builder
|
/// The program builder
|
||||||
ProgramBuilder& builder;
|
ProgramBuilder& builder;
|
||||||
/// The open / closed types and numbers
|
/// The template types and numbers
|
||||||
ClosedState& closed;
|
TemplateState& templates;
|
||||||
/// The type and number matchers
|
/// The type and number matchers
|
||||||
Matchers const& matchers;
|
Matchers const& matchers;
|
||||||
/// The current overload being evaluated
|
/// The current overload being evaluated
|
||||||
@ -198,7 +197,7 @@ class TypeMatcher {
|
|||||||
|
|
||||||
/// Checks whether the given type matches the matcher rules, and returns the
|
/// Checks whether the given type matches the matcher rules, and returns the
|
||||||
/// expected, canonicalized type on success.
|
/// expected, canonicalized type on success.
|
||||||
/// Match may close open types and numbers in state.
|
/// Match may define template types and numbers in state.
|
||||||
/// @param type the type to match
|
/// @param type the type to match
|
||||||
/// @returns the canonicalized type on match, otherwise nullptr
|
/// @returns the canonicalized type on match, otherwise nullptr
|
||||||
virtual const sem::Type* Match(MatchState& state, const sem::Type* type) const = 0;
|
virtual const sem::Type* Match(MatchState& state, const sem::Type* type) const = 0;
|
||||||
@ -216,7 +215,7 @@ class NumberMatcher {
|
|||||||
virtual ~NumberMatcher() = default;
|
virtual ~NumberMatcher() = default;
|
||||||
|
|
||||||
/// Checks whether the given number matches the matcher rules.
|
/// Checks whether the given number matches the matcher rules.
|
||||||
/// Match may close open numbers in state.
|
/// Match may define template numbers in state.
|
||||||
/// @param number the number to match
|
/// @param number the number to match
|
||||||
/// @returns true if the argument type is as expected.
|
/// @returns true if the argument type is as expected.
|
||||||
virtual Number Match(MatchState& state, Number number) const = 0;
|
virtual Number Match(MatchState& state, Number number) const = 0;
|
||||||
@ -226,19 +225,19 @@ class NumberMatcher {
|
|||||||
virtual std::string String(MatchState& state) const = 0;
|
virtual std::string String(MatchState& state) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// OpenTypeMatcher is a Matcher for an open type.
|
/// TemplateTypeMatcher is a Matcher for a template type.
|
||||||
/// The OpenTypeMatcher will match against any type (so long as it is consistent
|
/// The TemplateTypeMatcher will initially match against any type (so long as it is
|
||||||
/// across all uses in the overload)
|
/// consistent for all uses in the overload)
|
||||||
class OpenTypeMatcher : public TypeMatcher {
|
class TemplateTypeMatcher : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
explicit OpenTypeMatcher(size_t index) : index_(index) {}
|
explicit TemplateTypeMatcher(size_t index) : index_(index) {}
|
||||||
|
|
||||||
const sem::Type* Match(MatchState& state, const sem::Type* type) const override {
|
const sem::Type* Match(MatchState& state, const sem::Type* type) const override {
|
||||||
if (type->Is<Any>()) {
|
if (type->Is<Any>()) {
|
||||||
return state.closed.Type(index_);
|
return state.templates.Type(index_);
|
||||||
}
|
}
|
||||||
return state.closed.Type(index_, type) ? type : nullptr;
|
return state.templates.Type(index_, type) ? type : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string String(MatchState& state) const override;
|
std::string String(MatchState& state) const override;
|
||||||
@ -247,18 +246,18 @@ class OpenTypeMatcher : public TypeMatcher {
|
|||||||
size_t index_;
|
size_t index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// OpenNumberMatcher is a Matcher for an open number.
|
/// TemplateNumberMatcher is a Matcher for a template number.
|
||||||
/// The OpenNumberMatcher will match against any number (so long as it is
|
/// The TemplateNumberMatcher will match against any number (so long as it is
|
||||||
/// consistent for the overload)
|
/// consistent for all uses in the overload)
|
||||||
class OpenNumberMatcher : public NumberMatcher {
|
class TemplateNumberMatcher : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
explicit OpenNumberMatcher(size_t index) : index_(index) {}
|
explicit TemplateNumberMatcher(size_t index) : index_(index) {}
|
||||||
|
|
||||||
Number Match(MatchState& state, Number number) const override {
|
Number Match(MatchState& state, Number number) const override {
|
||||||
if (number.IsAny()) {
|
if (number.IsAny()) {
|
||||||
return state.closed.Num(index_);
|
return state.templates.Num(index_);
|
||||||
}
|
}
|
||||||
return state.closed.Num(index_, number) ? number : Number::invalid;
|
return state.templates.Num(index_, number) ? number : Number::invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string String(MatchState& state) const override;
|
std::string String(MatchState& state) const override;
|
||||||
@ -301,6 +300,10 @@ const sem::Bool* build_bool(MatchState& state) {
|
|||||||
return state.builder.create<sem::Bool>();
|
return state.builder.create<sem::Bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sem::F32* build_f32(MatchState& state) {
|
||||||
|
return state.builder.create<sem::F32>();
|
||||||
|
}
|
||||||
|
|
||||||
bool match_f32(const sem::Type* ty) {
|
bool match_f32(const sem::Type* ty) {
|
||||||
return ty->IsAnyOf<Any, sem::F32>();
|
return ty->IsAnyOf<Any, sem::F32>();
|
||||||
}
|
}
|
||||||
@ -321,10 +324,6 @@ bool match_u32(const sem::Type* ty) {
|
|||||||
return ty->IsAnyOf<Any, sem::U32>();
|
return ty->IsAnyOf<Any, sem::U32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::F32* build_f32(MatchState& state) {
|
|
||||||
return state.builder.create<sem::F32>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
|
||||||
if (ty->Is<Any>()) {
|
if (ty->Is<Any>()) {
|
||||||
N = Number::any;
|
N = Number::any;
|
||||||
@ -751,18 +750,18 @@ struct ParameterInfo {
|
|||||||
MatcherIndex const* const matcher_indices;
|
MatcherIndex const* const matcher_indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// OpenTypeInfo describes an open type
|
/// TemplateTypeInfo describes an template type
|
||||||
struct OpenTypeInfo {
|
struct TemplateTypeInfo {
|
||||||
/// Name of the open type (e.g. 'T')
|
/// Name of the template type (e.g. 'T')
|
||||||
const char* name;
|
const char* name;
|
||||||
/// Optional type matcher constraint.
|
/// Optional type matcher constraint.
|
||||||
/// Either an index in Matchers::type, or kNoMatcher
|
/// Either an index in Matchers::type, or kNoMatcher
|
||||||
const MatcherIndex matcher_index;
|
const MatcherIndex matcher_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// OpenNumberInfo describes an open number
|
/// TemplateNumberInfo describes a template number
|
||||||
struct OpenNumberInfo {
|
struct TemplateNumberInfo {
|
||||||
/// Name of the open number (e.g. 'N')
|
/// Name of the template number (e.g. 'N')
|
||||||
const char* name;
|
const char* name;
|
||||||
/// Optional number matcher constraint.
|
/// Optional number matcher constraint.
|
||||||
/// Either an index in Matchers::number, or kNoMatcher
|
/// Either an index in Matchers::number, or kNoMatcher
|
||||||
@ -773,14 +772,14 @@ struct OpenNumberInfo {
|
|||||||
struct OverloadInfo {
|
struct OverloadInfo {
|
||||||
/// Total number of parameters for the overload
|
/// Total number of parameters for the overload
|
||||||
const uint8_t num_parameters;
|
const uint8_t num_parameters;
|
||||||
/// Total number of open types for the overload
|
/// Total number of template types for the overload
|
||||||
const uint8_t num_open_types;
|
const uint8_t num_template_types;
|
||||||
/// Total number of open numbers for the overload
|
/// Total number of template numbers for the overload
|
||||||
const uint8_t num_open_numbers;
|
const uint8_t num_template_numbers;
|
||||||
/// Pointer to the first open type
|
/// Pointer to the first template type
|
||||||
OpenTypeInfo const* const open_types;
|
TemplateTypeInfo const* const template_types;
|
||||||
/// Pointer to the first open number
|
/// Pointer to the first template number
|
||||||
OpenNumberInfo const* const open_numbers;
|
TemplateNumberInfo const* const template_numbers;
|
||||||
/// Pointer to the first parameter
|
/// Pointer to the first parameter
|
||||||
ParameterInfo const* const parameters;
|
ParameterInfo const* const parameters;
|
||||||
/// Pointer to a list of matcher indices that index on Matchers::type and
|
/// Pointer to a list of matcher indices that index on Matchers::type and
|
||||||
@ -872,8 +871,8 @@ class Impl : public IntrinsicTable {
|
|||||||
struct Candidate {
|
struct Candidate {
|
||||||
/// The candidate overload
|
/// The candidate overload
|
||||||
const OverloadInfo* overload;
|
const OverloadInfo* overload;
|
||||||
/// The closed types and numbers
|
/// The template types and numbers
|
||||||
ClosedState closed;
|
TemplateState templates;
|
||||||
/// The parameter types for the candidate overload
|
/// The parameter types for the candidate overload
|
||||||
std::vector<IntrinsicPrototype::Parameter> parameters;
|
std::vector<IntrinsicPrototype::Parameter> parameters;
|
||||||
/// The match-score of the candidate overload.
|
/// The match-score of the candidate overload.
|
||||||
@ -893,9 +892,9 @@ class Impl : public IntrinsicTable {
|
|||||||
/// @param intrinsic the intrinsic being called
|
/// @param intrinsic the intrinsic being called
|
||||||
/// @param intrinsic_name the name of the intrinsic
|
/// @param intrinsic_name the name of the intrinsic
|
||||||
/// @param args the argument types
|
/// @param args the argument types
|
||||||
/// @param closed initial closed state. This may contain explicitly specified template
|
/// @param templates initial template state. This may contain explicitly specified template
|
||||||
/// arguments. For example `vec3<f32>()` would have the first template-type closed
|
/// arguments. For example `vec3<f32>()` would have the first template-type
|
||||||
/// as `f32`.
|
/// defined as `f32`.
|
||||||
/// @param on_no_match an error callback when no intrinsic overloads matched the provided
|
/// @param on_no_match an error callback when no intrinsic overloads matched the provided
|
||||||
/// arguments.
|
/// arguments.
|
||||||
/// @returns the matched intrinsic. If no intrinsic could be matched then IntrinsicPrototype
|
/// @returns the matched intrinsic. If no intrinsic could be matched then IntrinsicPrototype
|
||||||
@ -904,25 +903,25 @@ class Impl : public IntrinsicTable {
|
|||||||
IntrinsicPrototype MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
IntrinsicPrototype MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
||||||
const char* intrinsic_name,
|
const char* intrinsic_name,
|
||||||
const std::vector<const sem::Type*>& args,
|
const std::vector<const sem::Type*>& args,
|
||||||
ClosedState closed,
|
TemplateState templates,
|
||||||
OnNoMatch on_no_match) const;
|
OnNoMatch on_no_match) const;
|
||||||
|
|
||||||
/// Evaluates the overload for the provided argument types.
|
/// Evaluates the overload for the provided argument types.
|
||||||
/// @param overload the overload being considered
|
/// @param overload the overload being considered
|
||||||
/// @param args the argument types
|
/// @param args the argument types
|
||||||
/// @param closed initial closed state. This may contain explicitly specified template
|
/// @param templates initial template state. This may contain explicitly specified template
|
||||||
/// arguments. For example `vec3<f32>()` would have the first template-type closed
|
/// arguments. For example `vec3<f32>()` would have the first template-type
|
||||||
/// as `f32`.
|
/// template as `f32`.
|
||||||
/// @returns the evaluated Candidate information.
|
/// @returns the evaluated Candidate information.
|
||||||
Candidate ScoreOverload(const OverloadInfo* overload,
|
Candidate ScoreOverload(const OverloadInfo* overload,
|
||||||
const std::vector<const sem::Type*>& args,
|
const std::vector<const sem::Type*>& args,
|
||||||
ClosedState closed) const;
|
TemplateState templates) const;
|
||||||
|
|
||||||
/// Match constructs a new MatchState
|
/// Match constructs a new MatchState
|
||||||
/// @param closed the open / closed numbers and types used for matcher evaluation
|
/// @param templates the template state used for matcher evaluation
|
||||||
/// @param overload the overload being evaluated
|
/// @param overload the overload being evaluated
|
||||||
/// @param matcher_indices pointer to a list of matcher indices
|
/// @param matcher_indices pointer to a list of matcher indices
|
||||||
MatchState Match(ClosedState& closed,
|
MatchState Match(TemplateState& templates,
|
||||||
const OverloadInfo* overload,
|
const OverloadInfo* overload,
|
||||||
MatcherIndex const* matcher_indices) const;
|
MatcherIndex const* matcher_indices) const;
|
||||||
|
|
||||||
@ -940,7 +939,7 @@ class Impl : public IntrinsicTable {
|
|||||||
void ErrMultipleOverloadsMatched(size_t num_matched,
|
void ErrMultipleOverloadsMatched(size_t num_matched,
|
||||||
const char* intrinsic_name,
|
const char* intrinsic_name,
|
||||||
const std::vector<const sem::Type*>& args,
|
const std::vector<const sem::Type*>& args,
|
||||||
ClosedState closed,
|
TemplateState templates,
|
||||||
Candidates candidates) const;
|
Candidates candidates) const;
|
||||||
|
|
||||||
ProgramBuilder& builder;
|
ProgramBuilder& builder;
|
||||||
@ -979,12 +978,12 @@ std::string CallSignature(ProgramBuilder& builder,
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OpenTypeMatcher::String(MatchState& state) const {
|
std::string TemplateTypeMatcher::String(MatchState& state) const {
|
||||||
return state.overload->open_types[index_].name;
|
return state.overload->template_types[index_].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OpenNumberMatcher::String(MatchState& state) const {
|
std::string TemplateNumberMatcher::String(MatchState& state) const {
|
||||||
return state.overload->open_numbers[index_].name;
|
return state.overload->template_numbers[index_].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl::Impl(ProgramBuilder& b) : builder(b) {}
|
Impl::Impl(ProgramBuilder& b) : builder(b) {}
|
||||||
@ -1009,7 +1008,7 @@ const sem::Builtin* Impl::Lookup(sem::BuiltinType builtin_type,
|
|||||||
|
|
||||||
// Resolve the intrinsic overload
|
// Resolve the intrinsic overload
|
||||||
auto match = MatchIntrinsic(kBuiltins[static_cast<size_t>(builtin_type)], intrinsic_name, args,
|
auto match = MatchIntrinsic(kBuiltins[static_cast<size_t>(builtin_type)], intrinsic_name, args,
|
||||||
ClosedState{}, on_no_match);
|
TemplateState{}, on_no_match);
|
||||||
if (!match.overload) {
|
if (!match.overload) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -1070,7 +1069,7 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
|||||||
|
|
||||||
// Resolve the intrinsic overload
|
// Resolve the intrinsic overload
|
||||||
auto match = MatchIntrinsic(kUnaryOperators[intrinsic_index], intrinsic_name, {arg},
|
auto match = MatchIntrinsic(kUnaryOperators[intrinsic_index], intrinsic_name, {arg},
|
||||||
ClosedState{}, on_no_match);
|
TemplateState{}, on_no_match);
|
||||||
if (!match.overload) {
|
if (!match.overload) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -1141,7 +1140,7 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
|||||||
|
|
||||||
// Resolve the intrinsic overload
|
// Resolve the intrinsic overload
|
||||||
auto match = MatchIntrinsic(kBinaryOperators[intrinsic_index], intrinsic_name, {lhs, rhs},
|
auto match = MatchIntrinsic(kBinaryOperators[intrinsic_index], intrinsic_name, {lhs, rhs},
|
||||||
ClosedState{}, on_no_match);
|
TemplateState{}, on_no_match);
|
||||||
if (!match.overload) {
|
if (!match.overload) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -1184,14 +1183,14 @@ const sem::CallTarget* Impl::Lookup(CtorConvIntrinsic type,
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If a template type was provided, then close the 0'th type with this.
|
// If a template type was provided, then close the 0'th type with this.
|
||||||
ClosedState closed;
|
TemplateState templates;
|
||||||
if (template_arg) {
|
if (template_arg) {
|
||||||
closed.Type(0, template_arg);
|
templates.Type(0, template_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the intrinsic overload
|
// Resolve the intrinsic overload
|
||||||
auto match = MatchIntrinsic(kConstructorsAndConverters[static_cast<size_t>(type)], name, args,
|
auto match = MatchIntrinsic(kConstructorsAndConverters[static_cast<size_t>(type)], name, args,
|
||||||
closed, on_no_match);
|
templates, on_no_match);
|
||||||
if (!match.overload) {
|
if (!match.overload) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -1222,14 +1221,14 @@ const sem::CallTarget* Impl::Lookup(CtorConvIntrinsic type,
|
|||||||
IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
||||||
const char* intrinsic_name,
|
const char* intrinsic_name,
|
||||||
const std::vector<const sem::Type*>& args,
|
const std::vector<const sem::Type*>& args,
|
||||||
ClosedState closed,
|
TemplateState templates,
|
||||||
OnNoMatch on_no_match) const {
|
OnNoMatch on_no_match) const {
|
||||||
size_t num_matched = 0;
|
size_t num_matched = 0;
|
||||||
Candidates candidates;
|
Candidates candidates;
|
||||||
candidates.reserve(intrinsic.num_overloads);
|
candidates.reserve(intrinsic.num_overloads);
|
||||||
for (size_t overload_idx = 0; overload_idx < static_cast<size_t>(intrinsic.num_overloads);
|
for (size_t overload_idx = 0; overload_idx < static_cast<size_t>(intrinsic.num_overloads);
|
||||||
overload_idx++) {
|
overload_idx++) {
|
||||||
auto candidate = ScoreOverload(&intrinsic.overloads[overload_idx], args, closed);
|
auto candidate = ScoreOverload(&intrinsic.overloads[overload_idx], args, templates);
|
||||||
if (candidate.score == 0) {
|
if (candidate.score == 0) {
|
||||||
num_matched++;
|
num_matched++;
|
||||||
}
|
}
|
||||||
@ -1248,7 +1247,7 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||||||
case 1:
|
case 1:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ErrMultipleOverloadsMatched(num_matched, intrinsic_name, args, closed, candidates);
|
ErrMultipleOverloadsMatched(num_matched, intrinsic_name, args, templates, candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto match = candidates[0];
|
auto match = candidates[0];
|
||||||
@ -1257,7 +1256,7 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||||||
const sem::Type* return_type = nullptr;
|
const sem::Type* return_type = nullptr;
|
||||||
if (auto* indices = match.overload->return_matcher_indices) {
|
if (auto* indices = match.overload->return_matcher_indices) {
|
||||||
Any any;
|
Any any;
|
||||||
return_type = Match(match.closed, match.overload, indices).Type(&any);
|
return_type = Match(match.templates, match.overload, indices).Type(&any);
|
||||||
if (!return_type) {
|
if (!return_type) {
|
||||||
TINT_ICE(Resolver, builder.Diagnostics()) << "MatchState.Match() returned null";
|
TINT_ICE(Resolver, builder.Diagnostics()) << "MatchState.Match() returned null";
|
||||||
return {};
|
return {};
|
||||||
@ -1271,15 +1270,15 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
|
|||||||
|
|
||||||
Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
||||||
const std::vector<const sem::Type*>& args,
|
const std::vector<const sem::Type*>& args,
|
||||||
ClosedState closed) const {
|
TemplateState templates) const {
|
||||||
// Penalty weights for overload mismatching.
|
// Penalty weights for overload mismatching.
|
||||||
// This scoring is used to order the suggested overloads in diagnostic on overload mismatch, and
|
// This scoring is used to order the suggested overloads in diagnostic on overload mismatch, and
|
||||||
// has no impact for a correct program.
|
// has no impact for a correct program.
|
||||||
// The overloads with the lowest score will be displayed first (top-most).
|
// The overloads with the lowest score will be displayed first (top-most).
|
||||||
constexpr int kMismatchedParamCountPenalty = 3;
|
constexpr int kMismatchedParamCountPenalty = 3;
|
||||||
constexpr int kMismatchedParamTypePenalty = 2;
|
constexpr int kMismatchedParamTypePenalty = 2;
|
||||||
constexpr int kMismatchedOpenTypePenalty = 1;
|
constexpr int kMismatchedTemplateTypePenalty = 1;
|
||||||
constexpr int kMismatchedOpenNumberPenalty = 1;
|
constexpr int kMismatchedTemplateNumberPenalty = 1;
|
||||||
|
|
||||||
size_t num_parameters = static_cast<size_t>(overload->num_parameters);
|
size_t num_parameters = static_cast<size_t>(overload->num_parameters);
|
||||||
size_t num_arguments = static_cast<size_t>(args.size());
|
size_t num_arguments = static_cast<size_t>(args.size());
|
||||||
@ -1297,7 +1296,7 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||||||
for (size_t p = 0; p < num_params; p++) {
|
for (size_t p = 0; p < num_params; p++) {
|
||||||
auto& parameter = overload->parameters[p];
|
auto& parameter = overload->parameters[p];
|
||||||
auto* indices = parameter.matcher_indices;
|
auto* indices = parameter.matcher_indices;
|
||||||
auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
|
auto* type = Match(templates, overload, indices).Type(args[p]->UnwrapRef());
|
||||||
if (type) {
|
if (type) {
|
||||||
parameters.emplace_back(IntrinsicPrototype::Parameter{type, parameter.usage});
|
parameters.emplace_back(IntrinsicPrototype::Parameter{type, parameter.usage});
|
||||||
} else {
|
} else {
|
||||||
@ -1306,14 +1305,14 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (score == 0) {
|
if (score == 0) {
|
||||||
// Check all constrained open types matched
|
// Check all constrained template types matched
|
||||||
for (size_t ot = 0; ot < overload->num_open_types; ot++) {
|
for (size_t ot = 0; ot < overload->num_template_types; ot++) {
|
||||||
auto& open_type = overload->open_types[ot];
|
auto* matcher_index = &overload->template_types[ot].matcher_index;
|
||||||
if (open_type.matcher_index != kNoMatcher) {
|
if (*matcher_index != kNoMatcher) {
|
||||||
auto* closed_type = closed.Type(ot);
|
auto* template_type = templates.Type(ot);
|
||||||
auto* matcher_index = &open_type.matcher_index;
|
if (!template_type ||
|
||||||
if (!closed_type || !Match(closed, overload, matcher_index).Type(closed_type)) {
|
!Match(templates, overload, matcher_index).Type(template_type)) {
|
||||||
score += kMismatchedOpenTypePenalty;
|
score += kMismatchedTemplateTypePenalty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1321,32 +1320,31 @@ Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
|
|||||||
|
|
||||||
if (score == 0) {
|
if (score == 0) {
|
||||||
// Check all constrained open numbers matched
|
// Check all constrained open numbers matched
|
||||||
for (size_t on = 0; on < overload->num_open_numbers; on++) {
|
for (size_t on = 0; on < overload->num_template_numbers; on++) {
|
||||||
auto& open_number = overload->open_numbers[on];
|
auto* matcher_index = &overload->template_numbers[on].matcher_index;
|
||||||
if (open_number.matcher_index != kNoMatcher) {
|
if (*matcher_index != kNoMatcher) {
|
||||||
auto closed_num = closed.Num(on);
|
auto template_num = templates.Num(on);
|
||||||
auto* index = &open_number.matcher_index;
|
if (!template_num.IsValid() ||
|
||||||
if (!closed_num.IsValid() ||
|
!Match(templates, overload, matcher_index).Num(template_num).IsValid()) {
|
||||||
!Match(closed, overload, index).Num(closed_num).IsValid()) {
|
score += kMismatchedTemplateNumberPenalty;
|
||||||
score += kMismatchedOpenNumberPenalty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Candidate{overload, closed, parameters, score};
|
return Candidate{overload, templates, parameters, score};
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchState Impl::Match(ClosedState& closed,
|
MatchState Impl::Match(TemplateState& templates,
|
||||||
const OverloadInfo* overload,
|
const OverloadInfo* overload,
|
||||||
MatcherIndex const* matcher_indices) const {
|
MatcherIndex const* matcher_indices) const {
|
||||||
return MatchState(builder, closed, matchers, overload, matcher_indices);
|
return MatchState(builder, templates, matchers, overload, matcher_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Impl::PrintOverload(std::ostream& ss,
|
void Impl::PrintOverload(std::ostream& ss,
|
||||||
const OverloadInfo* overload,
|
const OverloadInfo* overload,
|
||||||
const char* intrinsic_name) const {
|
const char* intrinsic_name) const {
|
||||||
ClosedState closed;
|
TemplateState templates;
|
||||||
|
|
||||||
ss << intrinsic_name << "(";
|
ss << intrinsic_name << "(";
|
||||||
for (size_t p = 0; p < overload->num_parameters; p++) {
|
for (size_t p = 0; p < overload->num_parameters; p++) {
|
||||||
@ -1358,13 +1356,13 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||||||
ss << sem::str(parameter.usage) << ": ";
|
ss << sem::str(parameter.usage) << ": ";
|
||||||
}
|
}
|
||||||
auto* indices = parameter.matcher_indices;
|
auto* indices = parameter.matcher_indices;
|
||||||
ss << Match(closed, overload, indices).TypeName();
|
ss << Match(templates, overload, indices).TypeName();
|
||||||
}
|
}
|
||||||
ss << ")";
|
ss << ")";
|
||||||
if (overload->return_matcher_indices) {
|
if (overload->return_matcher_indices) {
|
||||||
ss << " -> ";
|
ss << " -> ";
|
||||||
auto* indices = overload->return_matcher_indices;
|
auto* indices = overload->return_matcher_indices;
|
||||||
ss << Match(closed, overload, indices).TypeName();
|
ss << Match(templates, overload, indices).TypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@ -1372,22 +1370,22 @@ void Impl::PrintOverload(std::ostream& ss,
|
|||||||
ss << (first ? " where: " : ", ");
|
ss << (first ? " where: " : ", ");
|
||||||
first = false;
|
first = false;
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < overload->num_open_types; i++) {
|
for (size_t i = 0; i < overload->num_template_types; i++) {
|
||||||
auto& open_type = overload->open_types[i];
|
auto& template_type = overload->template_types[i];
|
||||||
if (open_type.matcher_index != kNoMatcher) {
|
if (template_type.matcher_index != kNoMatcher) {
|
||||||
separator();
|
separator();
|
||||||
ss << open_type.name;
|
ss << template_type.name;
|
||||||
auto* index = &open_type.matcher_index;
|
auto* index = &template_type.matcher_index;
|
||||||
ss << " is " << Match(closed, overload, index).TypeName();
|
ss << " is " << Match(templates, overload, index).TypeName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < overload->num_open_numbers; i++) {
|
for (size_t i = 0; i < overload->num_template_numbers; i++) {
|
||||||
auto& open_number = overload->open_numbers[i];
|
auto& template_number = overload->template_numbers[i];
|
||||||
if (open_number.matcher_index != kNoMatcher) {
|
if (template_number.matcher_index != kNoMatcher) {
|
||||||
separator();
|
separator();
|
||||||
ss << open_number.name;
|
ss << template_number.name;
|
||||||
auto* index = &open_number.matcher_index;
|
auto* index = &template_number.matcher_index;
|
||||||
ss << " is " << Match(closed, overload, index).NumName();
|
ss << " is " << Match(templates, overload, index).NumName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1429,15 +1427,17 @@ std::string MatchState::NumName() {
|
|||||||
void Impl::ErrMultipleOverloadsMatched(size_t num_matched,
|
void Impl::ErrMultipleOverloadsMatched(size_t num_matched,
|
||||||
const char* intrinsic_name,
|
const char* intrinsic_name,
|
||||||
const std::vector<const sem::Type*>& args,
|
const std::vector<const sem::Type*>& args,
|
||||||
ClosedState closed,
|
TemplateState templates,
|
||||||
Candidates candidates) const {
|
Candidates candidates) const {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << num_matched << " overloads matched " << intrinsic_name;
|
ss << num_matched << " overloads matched " << intrinsic_name;
|
||||||
for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
|
for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
|
||||||
if (auto* ty = closed.Type(i)) {
|
if (auto* ty = templates.Type(i)) {
|
||||||
ss << ((i == 0) ? "<" : ", ") << ty->FriendlyName(builder.Symbols());
|
ss << ((i == 0) ? "<" : ", ") << ty->FriendlyName(builder.Symbols());
|
||||||
} else if (i > 0) {
|
} else {
|
||||||
|
if (i > 0) {
|
||||||
ss << ">";
|
ss << ">";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -51,8 +51,8 @@ constexpr ParameterInfo kParameters[] = {
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr OpenTypeInfo kOpenTypes[] = {
|
constexpr TemplateTypeInfo kTemplateTypes[] = {
|
||||||
{{- range $i, $o := .OpenTypes }}
|
{{- range $i, $o := .TemplateTypes }}
|
||||||
{
|
{
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
/* name */ "{{$o.Name}}",
|
/* name */ "{{$o.Name}}",
|
||||||
@ -64,8 +64,8 @@ constexpr OpenTypeInfo kOpenTypes[] = {
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr OpenNumberInfo kOpenNumbers[] = {
|
constexpr TemplateNumberInfo kTemplateNumbers[] = {
|
||||||
{{- range $i, $o := .OpenNumbers }}
|
{{- range $i, $o := .TemplateNumbers }}
|
||||||
{
|
{
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
/* name */ "{{$o.Name}}",
|
/* name */ "{{$o.Name}}",
|
||||||
@ -82,14 +82,14 @@ constexpr OverloadInfo kOverloads[] = {
|
|||||||
{
|
{
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
/* num parameters */ {{$o.NumParameters}},
|
/* num parameters */ {{$o.NumParameters}},
|
||||||
/* num open types */ {{$o.NumOpenTypes}},
|
/* num template types */ {{$o.NumTemplateTypes}},
|
||||||
/* num open numbers */ {{$o.NumOpenNumbers}},
|
/* num template numbers */ {{$o.NumTemplateNumbers}},
|
||||||
/* open types */
|
/* template types */
|
||||||
{{- if $o.OpenTypesOffset }} &kOpenTypes[{{$o.OpenTypesOffset}}],
|
{{- if $o.TemplateTypesOffset }} &kTemplateTypes[{{$o.TemplateTypesOffset}}],
|
||||||
{{- else }} nullptr,
|
{{- else }} nullptr,
|
||||||
{{- end }}
|
{{- end }}
|
||||||
/* open numbers */
|
/* template numbers */
|
||||||
{{- if $o.OpenNumbersOffset }} &kOpenNumbers[{{$o.OpenNumbersOffset}}]
|
{{- if $o.TemplateNumbersOffset }} &kTemplateNumbers[{{$o.TemplateNumbersOffset}}]
|
||||||
{{- else }} nullptr
|
{{- else }} nullptr
|
||||||
{{- end }},
|
{{- end }},
|
||||||
/* parameters */ &kParameters[{{$o.ParametersOffset}}],
|
/* parameters */ &kParameters[{{$o.ParametersOffset}}],
|
||||||
@ -180,7 +180,7 @@ constexpr IntrinsicInfo kConstructorsAndConverters[] = {
|
|||||||
class {{$class}} : public TypeMatcher {
|
class {{$class}} : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
/// Match may close open types and numbers in state.
|
/// Match may define template types and numbers in state.
|
||||||
/// @param state the MatchState
|
/// @param state the MatchState
|
||||||
/// @param type the type to match
|
/// @param type the type to match
|
||||||
/// @returns the canonicalized type on match, otherwise nullptr
|
/// @returns the canonicalized type on match, otherwise nullptr
|
||||||
@ -236,7 +236,7 @@ class {{$class}} : public TypeMatcher {
|
|||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules, and returns the
|
/// Checks whether the given type matches the matcher rules, and returns the
|
||||||
/// expected, canonicalized type on success.
|
/// expected, canonicalized type on success.
|
||||||
/// Match may close open types and numbers in state.
|
/// Match may define template types and numbers in state.
|
||||||
/// @param state the MatchState
|
/// @param state the MatchState
|
||||||
/// @param type the type to match
|
/// @param type the type to match
|
||||||
/// @returns the canonicalized type on match, otherwise nullptr
|
/// @returns the canonicalized type on match, otherwise nullptr
|
||||||
@ -280,7 +280,7 @@ std::string {{$class}}::String(MatchState&) const {
|
|||||||
class {{$class}} : public NumberMatcher {
|
class {{$class}} : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
/// Match may close open types and numbers in state.
|
/// Match may define template types and numbers in state.
|
||||||
/// @param state the MatchState
|
/// @param state the MatchState
|
||||||
/// @param number the enum value as a Number
|
/// @param number the enum value as a Number
|
||||||
/// @return true if the enum value matches the set
|
/// @return true if the enum value matches the set
|
||||||
@ -332,15 +332,15 @@ class Matchers {
|
|||||||
private:
|
private:
|
||||||
{{- $t_names := Map -}}
|
{{- $t_names := Map -}}
|
||||||
{{- $n_names := Map -}}
|
{{- $n_names := Map -}}
|
||||||
{{- range Iterate .Sem.MaxOpenTypes -}}
|
{{- range Iterate .Sem.MaxTemplateTypes -}}
|
||||||
{{- $name := printf "open_type_%v" . -}}
|
{{- $name := printf "template_type_%v" . -}}
|
||||||
{{- $t_names.Put . $name }}
|
{{- $t_names.Put . $name }}
|
||||||
OpenTypeMatcher {{$name}}_{ {{- . -}} };
|
TemplateTypeMatcher {{$name}}_{ {{- . -}} };
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- range Iterate .Sem.MaxOpenNumbers -}}
|
{{- range Iterate .Sem.MaxTemplateNumbers -}}
|
||||||
{{- $name := printf "open_number_%v" . -}}
|
{{- $name := printf "template_number_%v" . -}}
|
||||||
{{- $n_names.Put . $name }}
|
{{- $n_names.Put . $name }}
|
||||||
OpenNumberMatcher {{$name}}_{ {{- . -}} };
|
TemplateNumberMatcher {{$name}}_{ {{- . -}} };
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- range .Sem.Types -}}
|
{{- range .Sem.Types -}}
|
||||||
{{- $name := PascalCase .Name -}}
|
{{- $name := PascalCase .Name -}}
|
||||||
@ -364,7 +364,7 @@ class Matchers {
|
|||||||
/// Destructor
|
/// Destructor
|
||||||
~Matchers();
|
~Matchers();
|
||||||
|
|
||||||
/// The open-types, types, and type matchers
|
/// The template types, types, and type matchers
|
||||||
TypeMatcher const* const type[{{len .TMatchers}}] = {
|
TypeMatcher const* const type[{{len .TMatchers}}] = {
|
||||||
{{- range $i, $m := .TMatchers }}
|
{{- range $i, $m := .TMatchers }}
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
@ -374,7 +374,7 @@ class Matchers {
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The open-numbers, and number matchers
|
/// The template numbers, and number matchers
|
||||||
NumberMatcher const* const number[{{len .NMatchers}}] = {
|
NumberMatcher const* const number[{{len .NMatchers}}] = {
|
||||||
{{- range $i, $m := .NMatchers }}
|
{{- range $i, $m := .NMatchers }}
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
|
@ -27,19 +27,19 @@ type IntrinsicTable struct {
|
|||||||
// The semantic info
|
// The semantic info
|
||||||
Sem *sem.Sem
|
Sem *sem.Sem
|
||||||
|
|
||||||
// TMatchers are all the sem.OpenType, sem.Type and sem.TypeMatchers.
|
// TMatchers are all the sem.TemplateType, sem.Type and sem.TypeMatchers.
|
||||||
// These are all implemented by classes deriving from tint::TypeMatcher
|
// These are all implemented by classes deriving from tint::TypeMatcher
|
||||||
TMatchers []sem.Named
|
TMatchers []sem.Named
|
||||||
TMatcherIndex map[sem.Named]int // [object -> index] in TMatcher
|
TMatcherIndex map[sem.Named]int // [object -> index] in TMatcher
|
||||||
|
|
||||||
// NMatchers are all the sem.OpenNumber and sem.EnumMatchers.
|
// NMatchers are all the sem.TemplateNumber and sem.EnumMatchers.
|
||||||
// These are all implemented by classes deriving from tint::NumberMatcher
|
// These are all implemented by classes deriving from tint::NumberMatcher
|
||||||
NMatchers []sem.Named
|
NMatchers []sem.Named
|
||||||
NMatcherIndex map[sem.Named]int // [object -> index] in NMatchers
|
NMatcherIndex map[sem.Named]int // [object -> index] in NMatchers
|
||||||
|
|
||||||
MatcherIndices []int // kMatcherIndices table content
|
MatcherIndices []int // kMatcherIndices table content
|
||||||
OpenTypes []OpenType // kOpenTypes table content
|
TemplateTypes []TemplateType // kTemplateTypes table content
|
||||||
OpenNumbers []OpenNumber // kOpenNumbers table content
|
TemplateNumbers []TemplateNumber // kTemplateNumbers table content
|
||||||
Parameters []Parameter // kParameters table content
|
Parameters []Parameter // kParameters table content
|
||||||
Overloads []Overload // kOverloads table content
|
Overloads []Overload // kOverloads table content
|
||||||
Builtins []Intrinsic // kBuiltins table content
|
Builtins []Intrinsic // kBuiltins table content
|
||||||
@ -48,18 +48,18 @@ type IntrinsicTable struct {
|
|||||||
ConstructorsAndConverters []Intrinsic // kConstructorsAndConverters table content
|
ConstructorsAndConverters []Intrinsic // kConstructorsAndConverters table content
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenType is used to create the C++ OpenTypeInfo structure
|
// TemplateType is used to create the C++ TemplateTypeInfo structure
|
||||||
type OpenType struct {
|
type TemplateType struct {
|
||||||
// Name of the open type (e.g. 'T')
|
// Name of the template type (e.g. 'T')
|
||||||
Name string
|
Name string
|
||||||
// Optional type matcher constraint.
|
// Optional type matcher constraint.
|
||||||
// Either an index in Matchers::type, or -1
|
// Either an index in Matchers::type, or -1
|
||||||
MatcherIndex int
|
MatcherIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenNumber is used to create the C++ OpenNumberInfo structure
|
// TemplateNumber is used to create the C++ TemplateNumberInfo structure
|
||||||
type OpenNumber struct {
|
type TemplateNumber struct {
|
||||||
// Name of the open number (e.g. 'N')
|
// Name of the template number (e.g. 'N')
|
||||||
Name string
|
Name string
|
||||||
// Optional type matcher constraint.
|
// Optional type matcher constraint.
|
||||||
// Either an index in Matchers::type, or -1
|
// Either an index in Matchers::type, or -1
|
||||||
@ -83,14 +83,14 @@ type Parameter struct {
|
|||||||
type Overload struct {
|
type Overload struct {
|
||||||
// Total number of parameters for the overload
|
// Total number of parameters for the overload
|
||||||
NumParameters int
|
NumParameters int
|
||||||
// Total number of open types for the overload
|
// Total number of template types for the overload
|
||||||
NumOpenTypes int
|
NumTemplateTypes int
|
||||||
// Total number of open numbers for the overload
|
// Total number of template numbers for the overload
|
||||||
NumOpenNumbers int
|
NumTemplateNumbers int
|
||||||
// Index to the first open type in IntrinsicTable.OpenTypes
|
// Index to the first template type in IntrinsicTable.TemplateTypes
|
||||||
OpenTypesOffset *int
|
TemplateTypesOffset *int
|
||||||
// Index to the first open number in IntrinsicTable.OpenNumbers
|
// Index to the first template number in IntrinsicTable.TemplateNumbers
|
||||||
OpenNumbersOffset *int
|
TemplateNumbersOffset *int
|
||||||
// Index to the first parameter in IntrinsicTable.Parameters
|
// Index to the first parameter in IntrinsicTable.Parameters
|
||||||
ParametersOffset *int
|
ParametersOffset *int
|
||||||
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
||||||
@ -124,8 +124,8 @@ type IntrinsicTableBuilder struct {
|
|||||||
// These are packed (compressed) once all the entries have been added.
|
// These are packed (compressed) once all the entries have been added.
|
||||||
lut struct {
|
lut struct {
|
||||||
matcherIndices lut.LUT
|
matcherIndices lut.LUT
|
||||||
openTypes lut.LUT
|
templateTypes lut.LUT
|
||||||
openNumbers lut.LUT
|
templateNumbers lut.LUT
|
||||||
parameters lut.LUT
|
parameters lut.LUT
|
||||||
overloads lut.LUT
|
overloads lut.LUT
|
||||||
}
|
}
|
||||||
@ -134,14 +134,14 @@ type IntrinsicTableBuilder struct {
|
|||||||
// Helper for building a single overload
|
// Helper for building a single overload
|
||||||
type overloadBuilder struct {
|
type overloadBuilder struct {
|
||||||
*IntrinsicTableBuilder
|
*IntrinsicTableBuilder
|
||||||
// Maps TemplateParam to index in openTypes
|
// Maps TemplateParam to index in templateTypes
|
||||||
openTypeIndex map[sem.TemplateParam]int
|
templateTypeIndex map[sem.TemplateParam]int
|
||||||
// Maps TemplateParam to index in openNumbers
|
// Maps TemplateParam to index in templateNumbers
|
||||||
openNumberIndex map[sem.TemplateParam]int
|
templateNumberIndex map[sem.TemplateParam]int
|
||||||
// Open types used by the overload
|
// Template types used by the overload
|
||||||
openTypes []OpenType
|
templateTypes []TemplateType
|
||||||
// Open numbers used by the overload
|
// Template numbers used by the overload
|
||||||
openNumbers []OpenNumber
|
templateNumbers []TemplateNumber
|
||||||
// All parameters declared by the overload
|
// All parameters declared by the overload
|
||||||
parameters []Parameter
|
parameters []Parameter
|
||||||
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
||||||
@ -155,8 +155,8 @@ type overloadBuilder struct {
|
|||||||
// layoutMatchers assigns each of the TMatchers and NMatchers a unique index
|
// layoutMatchers assigns each of the TMatchers and NMatchers a unique index
|
||||||
// in the C++ Matchers::type and Matchers::number arrays, respectively.
|
// in the C++ Matchers::type and Matchers::number arrays, respectively.
|
||||||
func (b *IntrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
|
func (b *IntrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
|
||||||
// First MaxOpenTypes of TMatchers are open types
|
// First MaxTemplateTypes of TMatchers are template types
|
||||||
b.TMatchers = make([]sem.Named, s.MaxOpenTypes)
|
b.TMatchers = make([]sem.Named, s.MaxTemplateTypes)
|
||||||
for _, m := range s.Types {
|
for _, m := range s.Types {
|
||||||
b.TMatcherIndex[m] = len(b.TMatchers)
|
b.TMatcherIndex[m] = len(b.TMatchers)
|
||||||
b.TMatchers = append(b.TMatchers, m)
|
b.TMatchers = append(b.TMatchers, m)
|
||||||
@ -166,8 +166,8 @@ func (b *IntrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
|
|||||||
b.TMatchers = append(b.TMatchers, m)
|
b.TMatchers = append(b.TMatchers, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// First MaxOpenNumbers of NMatchers are open numbers
|
// First MaxTemplateNumbers of NMatchers are template numbers
|
||||||
b.NMatchers = make([]sem.Named, s.MaxOpenNumbers)
|
b.NMatchers = make([]sem.Named, s.MaxTemplateNumbers)
|
||||||
for _, m := range s.EnumMatchers {
|
for _, m := range s.EnumMatchers {
|
||||||
b.NMatcherIndex[m] = len(b.NMatchers)
|
b.NMatcherIndex[m] = len(b.NMatchers)
|
||||||
b.NMatchers = append(b.NMatchers, m)
|
b.NMatchers = append(b.NMatchers, m)
|
||||||
@ -178,14 +178,14 @@ func (b *IntrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
|
|||||||
func (b *IntrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error) {
|
func (b *IntrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error) {
|
||||||
ob := overloadBuilder{
|
ob := overloadBuilder{
|
||||||
IntrinsicTableBuilder: b,
|
IntrinsicTableBuilder: b,
|
||||||
openTypeIndex: map[sem.TemplateParam]int{},
|
templateTypeIndex: map[sem.TemplateParam]int{},
|
||||||
openNumberIndex: map[sem.TemplateParam]int{},
|
templateNumberIndex: map[sem.TemplateParam]int{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ob.buildOpenTypes(o); err != nil {
|
if err := ob.buildTemplateTypes(o); err != nil {
|
||||||
return Overload{}, err
|
return Overload{}, err
|
||||||
}
|
}
|
||||||
if err := ob.buildOpenNumbers(o); err != nil {
|
if err := ob.buildTemplateNumbers(o); err != nil {
|
||||||
return Overload{}, err
|
return Overload{}, err
|
||||||
}
|
}
|
||||||
if err := ob.buildParameters(o); err != nil {
|
if err := ob.buildParameters(o); err != nil {
|
||||||
@ -197,10 +197,10 @@ func (b *IntrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error)
|
|||||||
|
|
||||||
return Overload{
|
return Overload{
|
||||||
NumParameters: len(ob.parameters),
|
NumParameters: len(ob.parameters),
|
||||||
NumOpenTypes: len(ob.openTypes),
|
NumTemplateTypes: len(ob.templateTypes),
|
||||||
NumOpenNumbers: len(ob.openNumbers),
|
NumTemplateNumbers: len(ob.templateNumbers),
|
||||||
OpenTypesOffset: b.lut.openTypes.Add(ob.openTypes),
|
TemplateTypesOffset: b.lut.templateTypes.Add(ob.templateTypes),
|
||||||
OpenNumbersOffset: b.lut.openNumbers.Add(ob.openNumbers),
|
TemplateNumbersOffset: b.lut.templateNumbers.Add(ob.templateNumbers),
|
||||||
ParametersOffset: b.lut.parameters.Add(ob.parameters),
|
ParametersOffset: b.lut.parameters.Add(ob.parameters),
|
||||||
ReturnMatcherIndicesOffset: ob.returnTypeMatcherIndicesOffset,
|
ReturnMatcherIndicesOffset: ob.returnTypeMatcherIndicesOffset,
|
||||||
CanBeUsedInStage: o.CanBeUsedInStage,
|
CanBeUsedInStage: o.CanBeUsedInStage,
|
||||||
@ -209,12 +209,12 @@ func (b *IntrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildOpenTypes constructs the OpenTypes used by the overload, populating
|
// buildTemplateTypes constructs the TemplateTypes used by the overload, populating
|
||||||
// b.openTypes
|
// b.templateTypes
|
||||||
func (b *overloadBuilder) buildOpenTypes(o *sem.Overload) error {
|
func (b *overloadBuilder) buildTemplateTypes(o *sem.Overload) error {
|
||||||
b.openTypes = make([]OpenType, len(o.OpenTypes))
|
b.templateTypes = make([]TemplateType, len(o.TemplateTypes))
|
||||||
for i, t := range o.OpenTypes {
|
for i, t := range o.TemplateTypes {
|
||||||
b.openTypeIndex[t] = i
|
b.templateTypeIndex[t] = i
|
||||||
matcherIndex := -1
|
matcherIndex := -1
|
||||||
if t.Type != nil {
|
if t.Type != nil {
|
||||||
var err error
|
var err error
|
||||||
@ -223,7 +223,7 @@ func (b *overloadBuilder) buildOpenTypes(o *sem.Overload) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.openTypes[i] = OpenType{
|
b.templateTypes[i] = TemplateType{
|
||||||
Name: t.Name,
|
Name: t.Name,
|
||||||
MatcherIndex: matcherIndex,
|
MatcherIndex: matcherIndex,
|
||||||
}
|
}
|
||||||
@ -231,12 +231,12 @@ func (b *overloadBuilder) buildOpenTypes(o *sem.Overload) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildOpenNumbers constructs the OpenNumbers used by the overload, populating
|
// buildTemplateNumbers constructs the TemplateNumbers used by the overload, populating
|
||||||
// b.openNumbers
|
// b.templateNumbers
|
||||||
func (b *overloadBuilder) buildOpenNumbers(o *sem.Overload) error {
|
func (b *overloadBuilder) buildTemplateNumbers(o *sem.Overload) error {
|
||||||
b.openNumbers = make([]OpenNumber, len(o.OpenNumbers))
|
b.templateNumbers = make([]TemplateNumber, len(o.TemplateNumbers))
|
||||||
for i, t := range o.OpenNumbers {
|
for i, t := range o.TemplateNumbers {
|
||||||
b.openNumberIndex[t] = i
|
b.templateNumberIndex[t] = i
|
||||||
matcherIndex := -1
|
matcherIndex := -1
|
||||||
if e, ok := t.(*sem.TemplateEnumParam); ok && e.Matcher != nil {
|
if e, ok := t.(*sem.TemplateEnumParam); ok && e.Matcher != nil {
|
||||||
var err error
|
var err error
|
||||||
@ -245,7 +245,7 @@ func (b *overloadBuilder) buildOpenNumbers(o *sem.Overload) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.openNumbers[i] = OpenNumber{
|
b.templateNumbers[i] = TemplateNumber{
|
||||||
Name: t.GetName(),
|
Name: t.GetName(),
|
||||||
MatcherIndex: matcherIndex,
|
MatcherIndex: matcherIndex,
|
||||||
}
|
}
|
||||||
@ -295,25 +295,25 @@ func (b *overloadBuilder) matcherIndex(n sem.Named) (int, error) {
|
|||||||
}
|
}
|
||||||
return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
|
return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
|
||||||
case *sem.TemplateTypeParam:
|
case *sem.TemplateTypeParam:
|
||||||
if i, ok := b.openTypeIndex[n]; ok {
|
if i, ok := b.templateTypeIndex[n]; ok {
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("openTypeIndex missing entry for %v %T", n.Name, n)
|
return 0, fmt.Errorf("templateTypeIndex missing entry for %v %T", n.Name, n)
|
||||||
case *sem.EnumMatcher:
|
case *sem.EnumMatcher:
|
||||||
if i, ok := b.NMatcherIndex[n]; ok {
|
if i, ok := b.NMatcherIndex[n]; ok {
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
|
return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
|
||||||
case *sem.TemplateEnumParam:
|
case *sem.TemplateEnumParam:
|
||||||
if i, ok := b.openNumberIndex[n]; ok {
|
if i, ok := b.templateNumberIndex[n]; ok {
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("openNumberIndex missing entry for %v %T", n, n)
|
return 0, fmt.Errorf("templateNumberIndex missing entry for %v %T", n, n)
|
||||||
case *sem.TemplateNumberParam:
|
case *sem.TemplateNumberParam:
|
||||||
if i, ok := b.openNumberIndex[n]; ok {
|
if i, ok := b.templateNumberIndex[n]; ok {
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("openNumberIndex missing entry for %v %T", n, n)
|
return 0, fmt.Errorf("templateNumberIndex missing entry for %v %T", n, n)
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("overload.matcherIndex() does not handle %v %T", n, n)
|
return 0, fmt.Errorf("overload.matcherIndex() does not handle %v %T", n, n)
|
||||||
}
|
}
|
||||||
@ -359,8 +359,8 @@ func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
b.lut.matcherIndices = lut.New(list.Wrap(&b.MatcherIndices))
|
b.lut.matcherIndices = lut.New(list.Wrap(&b.MatcherIndices))
|
||||||
b.lut.openTypes = lut.New(list.Wrap(&b.OpenTypes))
|
b.lut.templateTypes = lut.New(list.Wrap(&b.TemplateTypes))
|
||||||
b.lut.openNumbers = lut.New(list.Wrap(&b.OpenNumbers))
|
b.lut.templateNumbers = lut.New(list.Wrap(&b.TemplateNumbers))
|
||||||
b.lut.parameters = lut.New(list.Wrap(&b.Parameters))
|
b.lut.parameters = lut.New(list.Wrap(&b.Parameters))
|
||||||
b.lut.overloads = lut.New(list.Wrap(&b.Overloads))
|
b.lut.overloads = lut.New(list.Wrap(&b.Overloads))
|
||||||
|
|
||||||
@ -397,8 +397,8 @@ func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.lut.matcherIndices.Compact()
|
b.lut.matcherIndices.Compact()
|
||||||
b.lut.openTypes.Compact()
|
b.lut.templateTypes.Compact()
|
||||||
b.lut.openNumbers.Compact()
|
b.lut.templateNumbers.Compact()
|
||||||
b.lut.parameters.Compact()
|
b.lut.parameters.Compact()
|
||||||
b.lut.overloads.Compact()
|
b.lut.overloads.Compact()
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ type Permuter struct {
|
|||||||
|
|
||||||
// buildPermuter returns a new initialized Permuter
|
// buildPermuter returns a new initialized Permuter
|
||||||
func buildPermuter(s *sem.Sem) (*Permuter, error) {
|
func buildPermuter(s *sem.Sem) (*Permuter, error) {
|
||||||
// allTypes are the list of FQNs that are used for open, unconstrained types
|
// allTypes are the list of FQNs that are used for unconstrained types
|
||||||
allTypes := []sem.FullyQualifiedName{}
|
allTypes := []sem.FullyQualifiedName{}
|
||||||
for _, ty := range s.Types {
|
for _, ty := range s.Types {
|
||||||
if len(ty.TemplateParams) > 0 {
|
if len(ty.TemplateParams) > 0 {
|
||||||
@ -59,8 +59,8 @@ type Permutation struct {
|
|||||||
func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
||||||
state := permutationState{
|
state := permutationState{
|
||||||
Permuter: p,
|
Permuter: p,
|
||||||
closedTypes: map[sem.TemplateParam]sem.FullyQualifiedName{},
|
templateTypes: map[sem.TemplateParam]sem.FullyQualifiedName{},
|
||||||
closedNumbers: map[sem.TemplateParam]interface{}{},
|
templateNumbers: map[sem.TemplateParam]interface{}{},
|
||||||
parameters: map[int]sem.FullyQualifiedName{},
|
parameters: map[int]sem.FullyQualifiedName{},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,15 +144,15 @@ func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
|||||||
var err error
|
var err error
|
||||||
types, err = state.permutateFQN(sem.FullyQualifiedName{Target: t.Type})
|
types, err = state.permutateFQN(sem.FullyQualifiedName{Target: t.Type})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("while permutating open types: %w", err)
|
return nil, fmt.Errorf("while permutating template types: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(types) == 0 {
|
if len(types) == 0 {
|
||||||
return nil, fmt.Errorf("open type %v has no permutations", t.Name)
|
return nil, fmt.Errorf("template type %v has no permutations", t.Name)
|
||||||
}
|
}
|
||||||
permutate = func() error {
|
permutate = func() error {
|
||||||
for _, ty := range types {
|
for _, ty := range types {
|
||||||
state.closedTypes[t] = ty
|
state.templateTypes[t] = ty
|
||||||
if err := next(); err != nil {
|
if err := next(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -168,14 +168,14 @@ func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
|||||||
permutations, err = state.permutateFQN(sem.FullyQualifiedName{Target: t.Enum})
|
permutations, err = state.permutateFQN(sem.FullyQualifiedName{Target: t.Enum})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("while permutating open numbers: %w", err)
|
return nil, fmt.Errorf("while permutating template numbers: %w", err)
|
||||||
}
|
}
|
||||||
if len(permutations) == 0 {
|
if len(permutations) == 0 {
|
||||||
return nil, fmt.Errorf("open type %v has no permutations", t.Name)
|
return nil, fmt.Errorf("template type %v has no permutations", t.Name)
|
||||||
}
|
}
|
||||||
permutate = func() error {
|
permutate = func() error {
|
||||||
for _, n := range permutations {
|
for _, n := range permutations {
|
||||||
state.closedNumbers[t] = n
|
state.templateNumbers[t] = n
|
||||||
if err := next(); err != nil {
|
if err := next(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -187,7 +187,7 @@ func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
|||||||
permutations := []int{2, 3, 4}
|
permutations := []int{2, 3, 4}
|
||||||
permutate = func() error {
|
permutate = func() error {
|
||||||
for _, n := range permutations {
|
for _, n := range permutations {
|
||||||
state.closedNumbers[t] = n
|
state.templateNumbers[t] = n
|
||||||
if err := next(); err != nil {
|
if err := next(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -206,19 +206,19 @@ func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
|||||||
|
|
||||||
type permutationState struct {
|
type permutationState struct {
|
||||||
*Permuter
|
*Permuter
|
||||||
closedTypes map[sem.TemplateParam]sem.FullyQualifiedName
|
templateTypes map[sem.TemplateParam]sem.FullyQualifiedName
|
||||||
closedNumbers map[sem.TemplateParam]interface{}
|
templateNumbers map[sem.TemplateParam]interface{}
|
||||||
parameters map[int]sem.FullyQualifiedName
|
parameters map[int]sem.FullyQualifiedName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s permutationState) String() string {
|
func (s permutationState) String() string {
|
||||||
sb := &strings.Builder{}
|
sb := &strings.Builder{}
|
||||||
sb.WriteString("Closed types:\n")
|
sb.WriteString("Template types:\n")
|
||||||
for ct, ty := range s.closedTypes {
|
for ct, ty := range s.templateTypes {
|
||||||
fmt.Fprintf(sb, " %v: %v\n", ct.GetName(), ty)
|
fmt.Fprintf(sb, " %v: %v\n", ct.GetName(), ty)
|
||||||
}
|
}
|
||||||
sb.WriteString("Closed numbers:\n")
|
sb.WriteString("Template numbers:\n")
|
||||||
for cn, v := range s.closedNumbers {
|
for cn, v := range s.templateNumbers {
|
||||||
fmt.Fprintf(sb, " %v: %v\n", cn.GetName(), v)
|
fmt.Fprintf(sb, " %v: %v\n", cn.GetName(), v)
|
||||||
}
|
}
|
||||||
return sb.String()
|
return sb.String()
|
||||||
@ -240,13 +240,13 @@ func (s *permutationState) permutateFQN(in sem.FullyQualifiedName) ([]sem.FullyQ
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case sem.TemplateParam:
|
case sem.TemplateParam:
|
||||||
if ty, ok := s.closedTypes[target]; ok {
|
if ty, ok := s.templateTypes[target]; ok {
|
||||||
permutate = func() error {
|
permutate = func() error {
|
||||||
out = append(out, ty)
|
out = append(out, ty)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("'%v' was not found in closedTypes", target.GetName())
|
return nil, fmt.Errorf("'%v' was not found in templateTypes", target.GetName())
|
||||||
}
|
}
|
||||||
case *sem.TypeMatcher:
|
case *sem.TypeMatcher:
|
||||||
permutate = func() error {
|
permutate = func() error {
|
||||||
@ -284,12 +284,12 @@ func (s *permutationState) permutateFQN(in sem.FullyQualifiedName) ([]sem.FullyQ
|
|||||||
case sem.FullyQualifiedName:
|
case sem.FullyQualifiedName:
|
||||||
switch target := arg.Target.(type) {
|
switch target := arg.Target.(type) {
|
||||||
case sem.TemplateParam:
|
case sem.TemplateParam:
|
||||||
if ty, ok := s.closedTypes[target]; ok {
|
if ty, ok := s.templateTypes[target]; ok {
|
||||||
args[i] = ty
|
args[i] = ty
|
||||||
} else if num, ok := s.closedNumbers[target]; ok {
|
} else if num, ok := s.templateNumbers[target]; ok {
|
||||||
args[i] = num
|
args[i] = num
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("'%v' was not found in closedTypes or closedNumbers", target.GetName())
|
return nil, fmt.Errorf("'%v' was not found in templateTypes or templateNumbers", target.GetName())
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
perms, err := s.permutateFQN(arg)
|
perms, err := s.permutateFQN(arg)
|
||||||
|
@ -328,22 +328,22 @@ func (r *resolver) intrinsic(
|
|||||||
intrinsic.Overloads = append(intrinsic.Overloads, overload)
|
intrinsic.Overloads = append(intrinsic.Overloads, overload)
|
||||||
|
|
||||||
// Sort the template parameters by resolved type. Append these to
|
// Sort the template parameters by resolved type. Append these to
|
||||||
// sem.Overload.OpenTypes or sem.Overload.OpenNumbers based on their kind.
|
// sem.Overload.TemplateTypes or sem.Overload.TemplateNumbers based on their kind.
|
||||||
for _, param := range templateParams {
|
for _, param := range templateParams {
|
||||||
switch param := param.(type) {
|
switch param := param.(type) {
|
||||||
case *sem.TemplateTypeParam:
|
case *sem.TemplateTypeParam:
|
||||||
overload.OpenTypes = append(overload.OpenTypes, param)
|
overload.TemplateTypes = append(overload.TemplateTypes, param)
|
||||||
case *sem.TemplateEnumParam, *sem.TemplateNumberParam:
|
case *sem.TemplateEnumParam, *sem.TemplateNumberParam:
|
||||||
overload.OpenNumbers = append(overload.OpenNumbers, param)
|
overload.TemplateNumbers = append(overload.TemplateNumbers, param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update high-water marks of open types / numbers
|
// Update high-water marks of template types and numbers
|
||||||
if r.s.MaxOpenTypes < len(overload.OpenTypes) {
|
if r.s.MaxTemplateTypes < len(overload.TemplateTypes) {
|
||||||
r.s.MaxOpenTypes = len(overload.OpenTypes)
|
r.s.MaxTemplateTypes = len(overload.TemplateTypes)
|
||||||
}
|
}
|
||||||
if r.s.MaxOpenNumbers < len(overload.OpenNumbers) {
|
if r.s.MaxTemplateNumbers < len(overload.TemplateNumbers) {
|
||||||
r.s.MaxOpenNumbers = len(overload.OpenNumbers)
|
r.s.MaxTemplateNumbers = len(overload.TemplateNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the parameters
|
// Resolve the parameters
|
||||||
|
@ -30,10 +30,10 @@ type Sem struct {
|
|||||||
UnaryOperators []*Intrinsic
|
UnaryOperators []*Intrinsic
|
||||||
BinaryOperators []*Intrinsic
|
BinaryOperators []*Intrinsic
|
||||||
ConstructorsAndConverters []*Intrinsic
|
ConstructorsAndConverters []*Intrinsic
|
||||||
// Maximum number of open-types used across all builtins
|
// Maximum number of template types used across all builtins
|
||||||
MaxOpenTypes int
|
MaxTemplateTypes int
|
||||||
// Maximum number of open-numbers used across all builtins
|
// Maximum number of template numbers used across all builtins
|
||||||
MaxOpenNumbers int
|
MaxTemplateNumbers int
|
||||||
// The alphabetically sorted list of unique parameter names
|
// The alphabetically sorted list of unique parameter names
|
||||||
UniqueParameterNames []string
|
UniqueParameterNames []string
|
||||||
}
|
}
|
||||||
@ -137,8 +137,8 @@ type Overload struct {
|
|||||||
Decl ast.IntrinsicDecl
|
Decl ast.IntrinsicDecl
|
||||||
Intrinsic *Intrinsic
|
Intrinsic *Intrinsic
|
||||||
TemplateParams []TemplateParam
|
TemplateParams []TemplateParam
|
||||||
OpenTypes []*TemplateTypeParam
|
TemplateTypes []*TemplateTypeParam
|
||||||
OpenNumbers []TemplateParam
|
TemplateNumbers []TemplateParam
|
||||||
ReturnType *FullyQualifiedName
|
ReturnType *FullyQualifiedName
|
||||||
Parameters []Parameter
|
Parameters []Parameter
|
||||||
CanBeUsedInStage StageUses
|
CanBeUsedInStage StageUses
|
||||||
|
Loading…
x
Reference in New Issue
Block a user