mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 14:43:31 +00:00
tint: Add operator support to intrinsic-gen
Adapt the builtin parsing and resolving to also support operators. Will be used to generate intrinsic table entries for operators. This will simplify maintenance of the operators, and will greatly simplify the [AbstractInt -> i32|u32] [AbstractFloat -> f32|f16] logic. Bug: tint:1504 Change-Id: Id75735ea24e501877418812185796f3fba88a521 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/89026 Commit-Queue: Ben Clayton <bclayton@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
d84daed72c
commit
e6e96def66
@ -762,9 +762,9 @@ struct OverloadInfo {
|
|||||||
bool is_deprecated;
|
bool is_deprecated;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// BuiltinInfo describes a builtin function
|
/// IntrinsicInfo describes a builtin function
|
||||||
struct BuiltinInfo {
|
struct IntrinsicInfo {
|
||||||
/// Number of overloads of the builtin function
|
/// Number of overloads of the intrinsic
|
||||||
const uint8_t num_overloads;
|
const uint8_t num_overloads;
|
||||||
/// Pointer to the start of the overloads for the function
|
/// Pointer to the start of the overloads for the function
|
||||||
OverloadInfo const* const overloads;
|
OverloadInfo const* const overloads;
|
||||||
@ -772,9 +772,8 @@ struct BuiltinInfo {
|
|||||||
|
|
||||||
#include "intrinsic_table.inl"
|
#include "intrinsic_table.inl"
|
||||||
|
|
||||||
/// BuiltinPrototype describes a fully matched builtin function, which is
|
/// IntrinsicPrototype describes a fully matched intrinsic.
|
||||||
/// used as a lookup for building unique sem::Builtin instances.
|
struct IntrinsicPrototype {
|
||||||
struct BuiltinPrototype {
|
|
||||||
/// Parameter describes a single parameter
|
/// Parameter describes a single parameter
|
||||||
struct Parameter {
|
struct Parameter {
|
||||||
/// Parameter type
|
/// Parameter type
|
||||||
@ -783,11 +782,11 @@ struct BuiltinPrototype {
|
|||||||
ParameterUsage const usage = ParameterUsage::kNone;
|
ParameterUsage const usage = ParameterUsage::kNone;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Hasher provides a hash function for the BuiltinPrototype
|
/// Hasher provides a hash function for the IntrinsicPrototype
|
||||||
struct Hasher {
|
struct Hasher {
|
||||||
/// @param i the BuiltinPrototype to create a hash for
|
/// @param i the IntrinsicPrototype to create a hash for
|
||||||
/// @return the hash value
|
/// @return the hash value
|
||||||
inline std::size_t operator()(const BuiltinPrototype& i) const {
|
inline std::size_t operator()(const IntrinsicPrototype& i) const {
|
||||||
size_t hash = utils::Hash(i.parameters.size());
|
size_t hash = utils::Hash(i.parameters.size());
|
||||||
for (auto& p : i.parameters) {
|
for (auto& p : i.parameters) {
|
||||||
utils::HashCombine(&hash, p.type, p.usage);
|
utils::HashCombine(&hash, p.type, p.usage);
|
||||||
@ -803,8 +802,8 @@ struct BuiltinPrototype {
|
|||||||
bool is_deprecated = false;
|
bool is_deprecated = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Equality operator for BuiltinPrototype
|
/// Equality operator for IntrinsicPrototype
|
||||||
bool operator==(const BuiltinPrototype& a, const BuiltinPrototype& b) {
|
bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) {
|
||||||
if (a.type != b.type || a.supported_stages != b.supported_stages ||
|
if (a.type != b.type || a.supported_stages != b.supported_stages ||
|
||||||
a.return_type != b.return_type || a.is_deprecated != b.is_deprecated ||
|
a.return_type != b.return_type || a.is_deprecated != b.is_deprecated ||
|
||||||
a.parameters.size() != b.parameters.size()) {
|
a.parameters.size() != b.parameters.size()) {
|
||||||
@ -845,7 +844,7 @@ class Impl : public IntrinsicTable {
|
|||||||
|
|
||||||
ProgramBuilder& builder;
|
ProgramBuilder& builder;
|
||||||
Matchers matchers;
|
Matchers matchers;
|
||||||
std::unordered_map<BuiltinPrototype, sem::Builtin*, BuiltinPrototype::Hasher> builtins;
|
std::unordered_map<IntrinsicPrototype, sem::Builtin*, IntrinsicPrototype::Hasher> builtins;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @return a string representing a call to a builtin with the given argument
|
/// @return a string representing a call to a builtin with the given argument
|
||||||
@ -949,7 +948,7 @@ const sem::Builtin* Impl::Match(sem::BuiltinType builtin_type,
|
|||||||
|
|
||||||
ClosedState closed(builder);
|
ClosedState closed(builder);
|
||||||
|
|
||||||
std::vector<BuiltinPrototype::Parameter> parameters;
|
std::vector<IntrinsicPrototype::Parameter> parameters;
|
||||||
|
|
||||||
auto num_params = std::min(num_parameters, num_arguments);
|
auto num_params = std::min(num_parameters, num_arguments);
|
||||||
for (uint32_t p = 0; p < num_params; p++) {
|
for (uint32_t p = 0; p < num_params; p++) {
|
||||||
@ -957,7 +956,7 @@ const sem::Builtin* Impl::Match(sem::BuiltinType builtin_type,
|
|||||||
auto* indices = parameter.matcher_indices;
|
auto* indices = parameter.matcher_indices;
|
||||||
auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
|
auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
|
||||||
if (type) {
|
if (type) {
|
||||||
parameters.emplace_back(BuiltinPrototype::Parameter{type, parameter.usage});
|
parameters.emplace_back(IntrinsicPrototype::Parameter{type, parameter.usage});
|
||||||
match_score += kScorePerMatchedParam;
|
match_score += kScorePerMatchedParam;
|
||||||
} else {
|
} else {
|
||||||
overload_matched = false;
|
overload_matched = false;
|
||||||
@ -1014,7 +1013,7 @@ const sem::Builtin* Impl::Match(sem::BuiltinType builtin_type,
|
|||||||
return_type = builder.create<sem::Void>();
|
return_type = builder.create<sem::Void>();
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinPrototype builtin;
|
IntrinsicPrototype builtin;
|
||||||
builtin.type = builtin_type;
|
builtin.type = builtin_type;
|
||||||
builtin.return_type = return_type;
|
builtin.return_type = return_type;
|
||||||
builtin.parameters = std::move(parameters);
|
builtin.parameters = std::move(parameters);
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// File generated by tools/builtin-gen
|
// File generated by tools/intrinsic-gen
|
||||||
// using the template:
|
// using the template:
|
||||||
// src/tint/builtin_table.inl.tmpl
|
// src/tint/resolver/intrinsic_table.inl.tmpl
|
||||||
// and the builtin defintion file:
|
// and the intrinsic defintion file:
|
||||||
// src/tint/builtins.def
|
// src/tint/intrinsics.def
|
||||||
//
|
//
|
||||||
// Do not modify this file directly
|
// Do not modify this file directly
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -25,7 +25,7 @@
|
|||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
/// TypeMatcher for 'type bool'
|
/// TypeMatcher for 'type bool'
|
||||||
/// @see src/tint/builtins.def:68:6
|
/// @see src/tint/intrinsics.def:68:6
|
||||||
class Bool : public TypeMatcher {
|
class Bool : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -52,7 +52,7 @@ std::string Bool::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type f32'
|
/// TypeMatcher for 'type f32'
|
||||||
/// @see src/tint/builtins.def:69:6
|
/// @see src/tint/intrinsics.def:69:6
|
||||||
class F32 : public TypeMatcher {
|
class F32 : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -79,7 +79,7 @@ std::string F32::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type i32'
|
/// TypeMatcher for 'type i32'
|
||||||
/// @see src/tint/builtins.def:70:6
|
/// @see src/tint/intrinsics.def:70:6
|
||||||
class I32 : public TypeMatcher {
|
class I32 : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -106,7 +106,7 @@ std::string I32::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type u32'
|
/// TypeMatcher for 'type u32'
|
||||||
/// @see src/tint/builtins.def:71:6
|
/// @see src/tint/intrinsics.def:71:6
|
||||||
class U32 : public TypeMatcher {
|
class U32 : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -133,7 +133,7 @@ std::string U32::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type vec2'
|
/// TypeMatcher for 'type vec2'
|
||||||
/// @see src/tint/builtins.def:72:6
|
/// @see src/tint/intrinsics.def:72:6
|
||||||
class Vec2 : public TypeMatcher {
|
class Vec2 : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -166,7 +166,7 @@ std::string Vec2::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type vec3'
|
/// TypeMatcher for 'type vec3'
|
||||||
/// @see src/tint/builtins.def:73:6
|
/// @see src/tint/intrinsics.def:73:6
|
||||||
class Vec3 : public TypeMatcher {
|
class Vec3 : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -199,7 +199,7 @@ std::string Vec3::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type vec4'
|
/// TypeMatcher for 'type vec4'
|
||||||
/// @see src/tint/builtins.def:74:6
|
/// @see src/tint/intrinsics.def:74:6
|
||||||
class Vec4 : public TypeMatcher {
|
class Vec4 : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -232,7 +232,7 @@ std::string Vec4::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type vec'
|
/// TypeMatcher for 'type vec'
|
||||||
/// @see src/tint/builtins.def:75:37
|
/// @see src/tint/intrinsics.def:75:37
|
||||||
class Vec : public TypeMatcher {
|
class Vec : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -273,7 +273,7 @@ std::string Vec::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type mat'
|
/// TypeMatcher for 'type mat'
|
||||||
/// @see src/tint/builtins.def:76:37
|
/// @see src/tint/intrinsics.def:76:37
|
||||||
class Mat : public TypeMatcher {
|
class Mat : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -320,7 +320,7 @@ std::string Mat::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type ptr'
|
/// TypeMatcher for 'type ptr'
|
||||||
/// @see src/tint/builtins.def:77:6
|
/// @see src/tint/intrinsics.def:77:6
|
||||||
class Ptr : public TypeMatcher {
|
class Ptr : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -365,7 +365,7 @@ std::string Ptr::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type atomic'
|
/// TypeMatcher for 'type atomic'
|
||||||
/// @see src/tint/builtins.def:78:6
|
/// @see src/tint/intrinsics.def:78:6
|
||||||
class Atomic : public TypeMatcher {
|
class Atomic : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -398,7 +398,7 @@ std::string Atomic::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type array'
|
/// TypeMatcher for 'type array'
|
||||||
/// @see src/tint/builtins.def:79:6
|
/// @see src/tint/intrinsics.def:79:6
|
||||||
class Array : public TypeMatcher {
|
class Array : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -431,7 +431,7 @@ std::string Array::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type sampler'
|
/// TypeMatcher for 'type sampler'
|
||||||
/// @see src/tint/builtins.def:80:6
|
/// @see src/tint/intrinsics.def:80:6
|
||||||
class Sampler : public TypeMatcher {
|
class Sampler : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -458,7 +458,7 @@ std::string Sampler::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type sampler_comparison'
|
/// TypeMatcher for 'type sampler_comparison'
|
||||||
/// @see src/tint/builtins.def:81:6
|
/// @see src/tint/intrinsics.def:81:6
|
||||||
class SamplerComparison : public TypeMatcher {
|
class SamplerComparison : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -485,7 +485,7 @@ std::string SamplerComparison::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_1d'
|
/// TypeMatcher for 'type texture_1d'
|
||||||
/// @see src/tint/builtins.def:82:6
|
/// @see src/tint/intrinsics.def:82:6
|
||||||
class Texture1D : public TypeMatcher {
|
class Texture1D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -518,7 +518,7 @@ std::string Texture1D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_2d'
|
/// TypeMatcher for 'type texture_2d'
|
||||||
/// @see src/tint/builtins.def:83:6
|
/// @see src/tint/intrinsics.def:83:6
|
||||||
class Texture2D : public TypeMatcher {
|
class Texture2D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -551,7 +551,7 @@ std::string Texture2D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_2d_array'
|
/// TypeMatcher for 'type texture_2d_array'
|
||||||
/// @see src/tint/builtins.def:84:6
|
/// @see src/tint/intrinsics.def:84:6
|
||||||
class Texture2DArray : public TypeMatcher {
|
class Texture2DArray : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -584,7 +584,7 @@ std::string Texture2DArray::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_3d'
|
/// TypeMatcher for 'type texture_3d'
|
||||||
/// @see src/tint/builtins.def:85:6
|
/// @see src/tint/intrinsics.def:85:6
|
||||||
class Texture3D : public TypeMatcher {
|
class Texture3D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -617,7 +617,7 @@ std::string Texture3D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_cube'
|
/// TypeMatcher for 'type texture_cube'
|
||||||
/// @see src/tint/builtins.def:86:6
|
/// @see src/tint/intrinsics.def:86:6
|
||||||
class TextureCube : public TypeMatcher {
|
class TextureCube : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -650,7 +650,7 @@ std::string TextureCube::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_cube_array'
|
/// TypeMatcher for 'type texture_cube_array'
|
||||||
/// @see src/tint/builtins.def:87:6
|
/// @see src/tint/intrinsics.def:87:6
|
||||||
class TextureCubeArray : public TypeMatcher {
|
class TextureCubeArray : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -683,7 +683,7 @@ std::string TextureCubeArray::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_multisampled_2d'
|
/// TypeMatcher for 'type texture_multisampled_2d'
|
||||||
/// @see src/tint/builtins.def:88:6
|
/// @see src/tint/intrinsics.def:88:6
|
||||||
class TextureMultisampled2D : public TypeMatcher {
|
class TextureMultisampled2D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -716,7 +716,7 @@ std::string TextureMultisampled2D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_depth_2d'
|
/// TypeMatcher for 'type texture_depth_2d'
|
||||||
/// @see src/tint/builtins.def:89:6
|
/// @see src/tint/intrinsics.def:89:6
|
||||||
class TextureDepth2D : public TypeMatcher {
|
class TextureDepth2D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -743,7 +743,7 @@ std::string TextureDepth2D::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_depth_2d_array'
|
/// TypeMatcher for 'type texture_depth_2d_array'
|
||||||
/// @see src/tint/builtins.def:90:6
|
/// @see src/tint/intrinsics.def:90:6
|
||||||
class TextureDepth2DArray : public TypeMatcher {
|
class TextureDepth2DArray : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -770,7 +770,7 @@ std::string TextureDepth2DArray::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_depth_cube'
|
/// TypeMatcher for 'type texture_depth_cube'
|
||||||
/// @see src/tint/builtins.def:91:6
|
/// @see src/tint/intrinsics.def:91:6
|
||||||
class TextureDepthCube : public TypeMatcher {
|
class TextureDepthCube : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -797,7 +797,7 @@ std::string TextureDepthCube::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_depth_cube_array'
|
/// TypeMatcher for 'type texture_depth_cube_array'
|
||||||
/// @see src/tint/builtins.def:92:6
|
/// @see src/tint/intrinsics.def:92:6
|
||||||
class TextureDepthCubeArray : public TypeMatcher {
|
class TextureDepthCubeArray : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -824,7 +824,7 @@ std::string TextureDepthCubeArray::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_depth_multisampled_2d'
|
/// TypeMatcher for 'type texture_depth_multisampled_2d'
|
||||||
/// @see src/tint/builtins.def:93:6
|
/// @see src/tint/intrinsics.def:93:6
|
||||||
class TextureDepthMultisampled2D : public TypeMatcher {
|
class TextureDepthMultisampled2D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -851,7 +851,7 @@ std::string TextureDepthMultisampled2D::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_storage_1d'
|
/// TypeMatcher for 'type texture_storage_1d'
|
||||||
/// @see src/tint/builtins.def:94:6
|
/// @see src/tint/intrinsics.def:94:6
|
||||||
class TextureStorage1D : public TypeMatcher {
|
class TextureStorage1D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -890,7 +890,7 @@ std::string TextureStorage1D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_storage_2d'
|
/// TypeMatcher for 'type texture_storage_2d'
|
||||||
/// @see src/tint/builtins.def:95:6
|
/// @see src/tint/intrinsics.def:95:6
|
||||||
class TextureStorage2D : public TypeMatcher {
|
class TextureStorage2D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -929,7 +929,7 @@ std::string TextureStorage2D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_storage_2d_array'
|
/// TypeMatcher for 'type texture_storage_2d_array'
|
||||||
/// @see src/tint/builtins.def:96:6
|
/// @see src/tint/intrinsics.def:96:6
|
||||||
class TextureStorage2DArray : public TypeMatcher {
|
class TextureStorage2DArray : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -968,7 +968,7 @@ std::string TextureStorage2DArray::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_storage_3d'
|
/// TypeMatcher for 'type texture_storage_3d'
|
||||||
/// @see src/tint/builtins.def:97:6
|
/// @see src/tint/intrinsics.def:97:6
|
||||||
class TextureStorage3D : public TypeMatcher {
|
class TextureStorage3D : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -1007,7 +1007,7 @@ std::string TextureStorage3D::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type texture_external'
|
/// TypeMatcher for 'type texture_external'
|
||||||
/// @see src/tint/builtins.def:98:6
|
/// @see src/tint/intrinsics.def:98:6
|
||||||
class TextureExternal : public TypeMatcher {
|
class TextureExternal : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -1034,7 +1034,7 @@ std::string TextureExternal::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type __modf_result'
|
/// TypeMatcher for 'type __modf_result'
|
||||||
/// @see src/tint/builtins.def:100:6
|
/// @see src/tint/intrinsics.def:100:6
|
||||||
class ModfResult : public TypeMatcher {
|
class ModfResult : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -1061,7 +1061,7 @@ std::string ModfResult::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type __modf_result_vec'
|
/// TypeMatcher for 'type __modf_result_vec'
|
||||||
/// @see src/tint/builtins.def:101:42
|
/// @see src/tint/intrinsics.def:101:42
|
||||||
class ModfResultVec : public TypeMatcher {
|
class ModfResultVec : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -1096,7 +1096,7 @@ std::string ModfResultVec::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type __frexp_result'
|
/// TypeMatcher for 'type __frexp_result'
|
||||||
/// @see src/tint/builtins.def:102:6
|
/// @see src/tint/intrinsics.def:102:6
|
||||||
class FrexpResult : public TypeMatcher {
|
class FrexpResult : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -1123,7 +1123,7 @@ std::string FrexpResult::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'type __frexp_result_vec'
|
/// TypeMatcher for 'type __frexp_result_vec'
|
||||||
/// @see src/tint/builtins.def:103:43
|
/// @see src/tint/intrinsics.def:103:43
|
||||||
class FrexpResultVec : public TypeMatcher {
|
class FrexpResultVec : public TypeMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given type matches the matcher rules.
|
/// Checks whether the given type matches the matcher rules.
|
||||||
@ -1158,7 +1158,7 @@ std::string FrexpResultVec::String(MatchState& state) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'match fiu32'
|
/// TypeMatcher for 'match fiu32'
|
||||||
/// @see src/tint/builtins.def:111:7
|
/// @see src/tint/intrinsics.def:111:7
|
||||||
class Fiu32 : public TypeMatcher {
|
class Fiu32 : 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
|
||||||
@ -1192,7 +1192,7 @@ std::string Fiu32::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'match iu32'
|
/// TypeMatcher for 'match iu32'
|
||||||
/// @see src/tint/builtins.def:112:7
|
/// @see src/tint/intrinsics.def:112:7
|
||||||
class Iu32 : public TypeMatcher {
|
class Iu32 : 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
|
||||||
@ -1223,7 +1223,7 @@ std::string Iu32::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TypeMatcher for 'match scalar'
|
/// TypeMatcher for 'match scalar'
|
||||||
/// @see src/tint/builtins.def:113:7
|
/// @see src/tint/intrinsics.def:113:7
|
||||||
class Scalar : public TypeMatcher {
|
class Scalar : 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
|
||||||
@ -1260,7 +1260,7 @@ std::string Scalar::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// EnumMatcher for 'match f32_texel_format'
|
/// EnumMatcher for 'match f32_texel_format'
|
||||||
/// @see src/tint/builtins.def:124:7
|
/// @see src/tint/intrinsics.def:124:7
|
||||||
class F32TexelFormat : public NumberMatcher {
|
class F32TexelFormat : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
@ -1293,7 +1293,7 @@ std::string F32TexelFormat::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// EnumMatcher for 'match i32_texel_format'
|
/// EnumMatcher for 'match i32_texel_format'
|
||||||
/// @see src/tint/builtins.def:126:7
|
/// @see src/tint/intrinsics.def:126:7
|
||||||
class I32TexelFormat : public NumberMatcher {
|
class I32TexelFormat : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
@ -1325,7 +1325,7 @@ std::string I32TexelFormat::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// EnumMatcher for 'match u32_texel_format'
|
/// EnumMatcher for 'match u32_texel_format'
|
||||||
/// @see src/tint/builtins.def:128:7
|
/// @see src/tint/intrinsics.def:128:7
|
||||||
class U32TexelFormat : public NumberMatcher {
|
class U32TexelFormat : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
@ -1357,7 +1357,7 @@ std::string U32TexelFormat::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// EnumMatcher for 'match write_only'
|
/// EnumMatcher for 'match write_only'
|
||||||
/// @see src/tint/builtins.def:131:7
|
/// @see src/tint/intrinsics.def:131:7
|
||||||
class WriteOnly : public NumberMatcher {
|
class WriteOnly : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
@ -1383,7 +1383,7 @@ std::string WriteOnly::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// EnumMatcher for 'match function_private_workgroup'
|
/// EnumMatcher for 'match function_private_workgroup'
|
||||||
/// @see src/tint/builtins.def:133:7
|
/// @see src/tint/intrinsics.def:133:7
|
||||||
class FunctionPrivateWorkgroup : public NumberMatcher {
|
class FunctionPrivateWorkgroup : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
@ -1413,7 +1413,7 @@ std::string FunctionPrivateWorkgroup::String(MatchState&) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// EnumMatcher for 'match workgroup_or_storage'
|
/// EnumMatcher for 'match workgroup_or_storage'
|
||||||
/// @see src/tint/builtins.def:134:7
|
/// @see src/tint/intrinsics.def:134:7
|
||||||
class WorkgroupOrStorage : public NumberMatcher {
|
class WorkgroupOrStorage : public NumberMatcher {
|
||||||
public:
|
public:
|
||||||
/// Checks whether the given number matches the enum matcher rules.
|
/// Checks whether the given number matches the enum matcher rules.
|
||||||
@ -8814,7 +8814,7 @@ constexpr OverloadInfo kOverloads[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr BuiltinInfo kBuiltins[] = {
|
constexpr IntrinsicInfo kBuiltins[] = {
|
||||||
{
|
{
|
||||||
/* [0] */
|
/* [0] */
|
||||||
/* fn abs<T : fiu32>(T) -> T */
|
/* fn abs<T : fiu32>(T) -> T */
|
||||||
|
@ -23,7 +23,7 @@ See:
|
|||||||
{{ end -}}
|
{{ end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
{{- with BuiltinTable -}}
|
{{- with IntrinsicTable -}}
|
||||||
{{- template "Matchers" . }}
|
{{- template "Matchers" . }}
|
||||||
|
|
||||||
constexpr MatcherIndex kMatcherIndices[] = {
|
constexpr MatcherIndex kMatcherIndices[] = {
|
||||||
@ -106,15 +106,15 @@ constexpr OverloadInfo kOverloads[] = {
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr BuiltinInfo kBuiltins[] = {
|
constexpr IntrinsicInfo kBuiltins[] = {
|
||||||
{{- range $i, $f := .Functions }}
|
{{- range $i, $b := .Builtins }}
|
||||||
{
|
{
|
||||||
/* [{{$i}}] */
|
/* [{{$i}}] */
|
||||||
{{- range $f.OverloadDescriptions }}
|
{{- range $b.OverloadDescriptions }}
|
||||||
/* {{.}} */
|
/* {{.}} */
|
||||||
{{- end }}
|
{{- end }}
|
||||||
/* num overloads */ {{$f.NumOverloads}},
|
/* num overloads */ {{$b.NumOverloads}},
|
||||||
/* overloads */ &kOverloads[{{$f.OverloadsOffset}}],
|
/* overloads */ &kOverloads[{{$b.OverloadsOffset}}],
|
||||||
},
|
},
|
||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@ See:
|
|||||||
namespace tint::sem {
|
namespace tint::sem {
|
||||||
|
|
||||||
BuiltinType ParseBuiltinType(const std::string& name) {
|
BuiltinType ParseBuiltinType(const std::string& name) {
|
||||||
{{- range .Sem.Functions }}
|
{{- range .Sem.Builtins }}
|
||||||
if (name == "{{.Name}}") {
|
if (name == "{{.Name}}") {
|
||||||
return BuiltinType::k{{Title .Name}};
|
return BuiltinType::k{{Title .Name}};
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ const char* str(BuiltinType i) {
|
|||||||
switch (i) {
|
switch (i) {
|
||||||
case BuiltinType::kNone:
|
case BuiltinType::kNone:
|
||||||
return "<none>";
|
return "<none>";
|
||||||
{{- range .Sem.Functions }}
|
{{- range .Sem.Builtins }}
|
||||||
case BuiltinType::k{{Title .Name}}:
|
case BuiltinType::k{{Title .Name}}:
|
||||||
return "{{.Name}}";
|
return "{{.Name}}";
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
@ -19,7 +19,7 @@ namespace tint::sem {
|
|||||||
/// Enumerator of all builtin functions
|
/// Enumerator of all builtin functions
|
||||||
enum class BuiltinType {
|
enum class BuiltinType {
|
||||||
kNone = -1,
|
kNone = -1,
|
||||||
{{- range .Sem.Functions }}
|
{{- range .Sem.Builtins }}
|
||||||
k{{Title .Name}},
|
k{{Title .Name}},
|
||||||
{{- end }}
|
{{- end }}
|
||||||
};
|
};
|
||||||
|
@ -9,15 +9,15 @@ See:
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
*/ -}}
|
*/ -}}
|
||||||
|
|
||||||
{{- /* For each permutation of each overload of each function... */ -}}
|
{{- /* For each permutation of each overload of each builtin... */ -}}
|
||||||
{{- range .Sem.Functions -}}
|
{{- range .Sem.Builtins -}}
|
||||||
{{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from builtins.def */}}
|
{{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from builtins.def */}}
|
||||||
{{- if not (eq .Name "smoothStep") }}
|
{{- if not (eq .Name "smoothStep") }}
|
||||||
{{- range .Overloads -}}
|
{{- range .Overloads -}}
|
||||||
{{- range Permute . -}}
|
{{- range Permute . -}}
|
||||||
{{- /* Generate a ./gen/<function>/<permuataion-hash>.wgsl file using
|
{{- /* Generate a ./gen/<function>/<permuataion-hash>.wgsl file using
|
||||||
the Permutation macro defined below */ -}}
|
the Permutation macro defined below */ -}}
|
||||||
{{- $file := printf "./gen/%v/%v.wgsl" .Function.Name .Hash -}}
|
{{- $file := printf "./gen/%v/%v.wgsl" .Intrinsic.Name .Hash -}}
|
||||||
{{- $content := Eval "Permutation" . -}}
|
{{- $content := Eval "Permutation" . -}}
|
||||||
{{- WriteFile $file $content -}}
|
{{- WriteFile $file $content -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@ -30,8 +30,8 @@ See:
|
|||||||
{{- define "Permutation" -}}
|
{{- define "Permutation" -}}
|
||||||
{{- /* Emits the body of the intrinsic permuation .wgsl file */ -}}
|
{{- /* Emits the body of the intrinsic permuation .wgsl file */ -}}
|
||||||
{{- /* ------------------------------------------------------------------ */ -}}
|
{{- /* ------------------------------------------------------------------ */ -}}
|
||||||
{{- $function := .Function.Name -}}
|
{{- $builtin := .Intrinsic.Name -}}
|
||||||
{{- $permutation := printf "%v_%v" $function .Hash -}}
|
{{- $permutation := printf "%v_%v" $builtin .Hash -}}
|
||||||
{{- $args := Map -}}
|
{{- $args := Map -}}
|
||||||
|
|
||||||
{{- /* Generate RW storage buffer parameters */ -}}
|
{{- /* Generate RW storage buffer parameters */ -}}
|
||||||
@ -125,7 +125,7 @@ fn {{$permutation}}() {
|
|||||||
{{- if .ReturnType -}}
|
{{- if .ReturnType -}}
|
||||||
var res{{if IsDeclarable .ReturnType}}: {{template "Type" .ReturnType}}{{end}} = {{/* preserve space after = */ -}}
|
var res{{if IsDeclarable .ReturnType}}: {{template "Type" .ReturnType}}{{end}} = {{/* preserve space after = */ -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{$function}}(
|
{{$builtin}}(
|
||||||
{{- range $i, $p := .Parameters -}}
|
{{- range $i, $p := .Parameters -}}
|
||||||
{{- if $i -}}, {{end}}{{$args.Get $i -}}
|
{{- if $i -}}, {{end}}{{$args.Get $i -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
@ -28,7 +28,8 @@ type AST struct {
|
|||||||
Enums []EnumDecl
|
Enums []EnumDecl
|
||||||
Types []TypeDecl
|
Types []TypeDecl
|
||||||
Matchers []MatcherDecl
|
Matchers []MatcherDecl
|
||||||
Functions []FunctionDecl
|
Builtins []IntrinsicDecl
|
||||||
|
Operators []IntrinsicDecl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AST) String() string {
|
func (a AST) String() string {
|
||||||
@ -45,8 +46,12 @@ func (a AST) String() string {
|
|||||||
fmt.Fprintf(&sb, "%v", m)
|
fmt.Fprintf(&sb, "%v", m)
|
||||||
fmt.Fprintln(&sb)
|
fmt.Fprintln(&sb)
|
||||||
}
|
}
|
||||||
for _, f := range a.Functions {
|
for _, b := range a.Builtins {
|
||||||
fmt.Fprintf(&sb, "%v", f)
|
fmt.Fprintf(&sb, "%v", b)
|
||||||
|
fmt.Fprintln(&sb)
|
||||||
|
}
|
||||||
|
for _, o := range a.Operators {
|
||||||
|
fmt.Fprintf(&sb, "%v", o)
|
||||||
fmt.Fprintln(&sb)
|
fmt.Fprintln(&sb)
|
||||||
}
|
}
|
||||||
return sb.String()
|
return sb.String()
|
||||||
@ -98,9 +103,18 @@ func (m MatcherDecl) Format(w fmt.State, verb rune) {
|
|||||||
m.Options.Format(w, verb)
|
m.Options.Format(w, verb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FunctionDecl describes a function declaration
|
// IntrinsicKind is either a Builtin or Operator
|
||||||
type FunctionDecl struct {
|
type IntrinsicKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Builtin IntrinsicKind = "builtin"
|
||||||
|
Operator IntrinsicKind = "operator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IntrinsicDecl describes a builtin or operator declaration
|
||||||
|
type IntrinsicDecl struct {
|
||||||
Source tok.Source
|
Source tok.Source
|
||||||
|
Kind IntrinsicKind
|
||||||
Name string
|
Name string
|
||||||
Decorations Decorations
|
Decorations Decorations
|
||||||
TemplateParams TemplateParams
|
TemplateParams TemplateParams
|
||||||
@ -109,13 +123,19 @@ type FunctionDecl struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format implements the fmt.Formatter interface
|
// Format implements the fmt.Formatter interface
|
||||||
func (f FunctionDecl) Format(w fmt.State, verb rune) {
|
func (i IntrinsicDecl) Format(w fmt.State, verb rune) {
|
||||||
fmt.Fprintf(w, "fn %v", f.Name)
|
switch i.Kind {
|
||||||
f.TemplateParams.Format(w, verb)
|
case Builtin:
|
||||||
f.Parameters.Format(w, verb)
|
fmt.Fprintf(w, "fn ")
|
||||||
if f.ReturnType != nil {
|
case Operator:
|
||||||
|
fmt.Fprintf(w, "op ")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "%v", i.Name)
|
||||||
|
i.TemplateParams.Format(w, verb)
|
||||||
|
i.Parameters.Format(w, verb)
|
||||||
|
if i.ReturnType != nil {
|
||||||
fmt.Fprintf(w, " -> ")
|
fmt.Fprintf(w, " -> ")
|
||||||
f.ReturnType.Format(w, verb)
|
i.ReturnType.Format(w, verb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ import (
|
|||||||
"dawn.googlesource.com/dawn/tools/src/lut"
|
"dawn.googlesource.com/dawn/tools/src/lut"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BuiltinTable holds data specific to the intrinsic_table.inl.tmpl template
|
// IntrinsicTable holds data specific to the intrinsic_table.inl.tmpl template
|
||||||
type BuiltinTable struct {
|
type IntrinsicTable struct {
|
||||||
// The semantic info
|
// The semantic info
|
||||||
Sem *sem.Sem
|
Sem *sem.Sem
|
||||||
|
|
||||||
@ -42,7 +42,8 @@ type BuiltinTable struct {
|
|||||||
OpenNumbers []OpenNumber // kOpenNumbers table content
|
OpenNumbers []OpenNumber // kOpenNumbers table content
|
||||||
Parameters []Parameter // kParameters table content
|
Parameters []Parameter // kParameters table content
|
||||||
Overloads []Overload // kOverloads table content
|
Overloads []Overload // kOverloads table content
|
||||||
Functions []Function // kBuiltins table content
|
Builtins []Intrinsic // kBuiltins table content
|
||||||
|
Operators []Intrinsic // kOperators table content
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenType is used to create the C++ OpenTypeInfo structure
|
// OpenType is used to create the C++ OpenTypeInfo structure
|
||||||
@ -68,9 +69,9 @@ type Parameter struct {
|
|||||||
// The parameter usage (parameter name)
|
// The parameter usage (parameter name)
|
||||||
Usage string
|
Usage string
|
||||||
|
|
||||||
// Index into BuiltinTable.MatcherIndices, beginning the list of matchers
|
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
||||||
// required to match the parameter type. The matcher indices index
|
// required to match the parameter type. The matcher indices index
|
||||||
// into BuiltinTable::TMatchers and / or BuiltinTable::NMatchers.
|
// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
|
||||||
// These indices are consumed by the matchers themselves.
|
// These indices are consumed by the matchers themselves.
|
||||||
// The first index is always a TypeMatcher.
|
// The first index is always a TypeMatcher.
|
||||||
MatcherIndicesOffset *int
|
MatcherIndicesOffset *int
|
||||||
@ -84,15 +85,15 @@ type Overload struct {
|
|||||||
NumOpenTypes int
|
NumOpenTypes int
|
||||||
// Total number of open numbers for the overload
|
// Total number of open numbers for the overload
|
||||||
NumOpenNumbers int
|
NumOpenNumbers int
|
||||||
// Index to the first open type in BuiltinTable.OpenTypes
|
// Index to the first open type in IntrinsicTable.OpenTypes
|
||||||
OpenTypesOffset *int
|
OpenTypesOffset *int
|
||||||
// Index to the first open number in BuiltinTable.OpenNumbers
|
// Index to the first open number in IntrinsicTable.OpenNumbers
|
||||||
OpenNumbersOffset *int
|
OpenNumbersOffset *int
|
||||||
// Index to the first parameter in BuiltinTable.Parameters
|
// Index to the first parameter in IntrinsicTable.Parameters
|
||||||
ParametersOffset *int
|
ParametersOffset *int
|
||||||
// Index into BuiltinTable.MatcherIndices, beginning the list of matchers
|
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
||||||
// required to match the return type. The matcher indices index
|
// required to match the return type. The matcher indices index
|
||||||
// into BuiltinTable::TMatchers and / or BuiltinTable::NMatchers.
|
// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
|
||||||
// These indices are consumed by the matchers themselves.
|
// These indices are consumed by the matchers themselves.
|
||||||
// The first index is always a TypeMatcher.
|
// The first index is always a TypeMatcher.
|
||||||
ReturnMatcherIndicesOffset *int
|
ReturnMatcherIndicesOffset *int
|
||||||
@ -102,17 +103,18 @@ type Overload struct {
|
|||||||
IsDeprecated bool
|
IsDeprecated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function is used to create the C++ IntrinsicInfo structure
|
// Intrinsic is used to create the C++ IntrinsicInfo structure
|
||||||
type Function struct {
|
type Intrinsic struct {
|
||||||
|
Name string
|
||||||
OverloadDescriptions []string
|
OverloadDescriptions []string
|
||||||
NumOverloads int
|
NumOverloads int
|
||||||
OverloadsOffset *int
|
OverloadsOffset *int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for building the BuiltinTable
|
// Helper for building the IntrinsicTable
|
||||||
type BuiltinTableBuilder struct {
|
type IntrinsicTableBuilder struct {
|
||||||
// The output of the builder
|
// The output of the builder
|
||||||
BuiltinTable
|
IntrinsicTable
|
||||||
|
|
||||||
// Lookup tables.
|
// Lookup tables.
|
||||||
// These are packed (compressed) once all the entries have been added.
|
// These are packed (compressed) once all the entries have been added.
|
||||||
@ -127,7 +129,7 @@ type BuiltinTableBuilder struct {
|
|||||||
|
|
||||||
// Helper for building a single overload
|
// Helper for building a single overload
|
||||||
type overloadBuilder struct {
|
type overloadBuilder struct {
|
||||||
*BuiltinTableBuilder
|
*IntrinsicTableBuilder
|
||||||
// Maps TemplateParam to index in openTypes
|
// Maps TemplateParam to index in openTypes
|
||||||
openTypeIndex map[sem.TemplateParam]int
|
openTypeIndex map[sem.TemplateParam]int
|
||||||
// Maps TemplateParam to index in openNumbers
|
// Maps TemplateParam to index in openNumbers
|
||||||
@ -138,9 +140,9 @@ type overloadBuilder struct {
|
|||||||
openNumbers []OpenNumber
|
openNumbers []OpenNumber
|
||||||
// All parameters declared by the overload
|
// All parameters declared by the overload
|
||||||
parameters []Parameter
|
parameters []Parameter
|
||||||
// Index into BuiltinTable.MatcherIndices, beginning the list of matchers
|
// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
|
||||||
// required to match the return type. The matcher indices index
|
// required to match the return type. The matcher indices index
|
||||||
// into BuiltinTable::TMatchers and / or BuiltinTable::NMatchers.
|
// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
|
||||||
// These indices are consumed by the matchers themselves.
|
// These indices are consumed by the matchers themselves.
|
||||||
// The first index is always a TypeMatcher.
|
// The first index is always a TypeMatcher.
|
||||||
returnTypeMatcherIndicesOffset *int
|
returnTypeMatcherIndicesOffset *int
|
||||||
@ -148,7 +150,7 @@ 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 *BuiltinTableBuilder) layoutMatchers(s *sem.Sem) {
|
func (b *IntrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
|
||||||
// First MaxOpenTypes of TMatchers are open types
|
// First MaxOpenTypes of TMatchers are open types
|
||||||
b.TMatchers = make([]sem.Named, s.MaxOpenTypes)
|
b.TMatchers = make([]sem.Named, s.MaxOpenTypes)
|
||||||
for _, m := range s.Types {
|
for _, m := range s.Types {
|
||||||
@ -169,9 +171,9 @@ func (b *BuiltinTableBuilder) layoutMatchers(s *sem.Sem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildOverload constructs an Overload for a sem.Overload
|
// buildOverload constructs an Overload for a sem.Overload
|
||||||
func (b *BuiltinTableBuilder) buildOverload(o *sem.Overload) (Overload, error) {
|
func (b *IntrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error) {
|
||||||
ob := overloadBuilder{
|
ob := overloadBuilder{
|
||||||
BuiltinTableBuilder: b,
|
IntrinsicTableBuilder: b,
|
||||||
openTypeIndex: map[sem.TemplateParam]int{},
|
openTypeIndex: map[sem.TemplateParam]int{},
|
||||||
openNumberIndex: map[sem.TemplateParam]int{},
|
openNumberIndex: map[sem.TemplateParam]int{},
|
||||||
}
|
}
|
||||||
@ -279,7 +281,7 @@ func (b *overloadBuilder) buildReturnType(o *sem.Overload) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// matcherIndex returns the index of TMatcher or NMatcher in
|
// matcherIndex returns the index of TMatcher or NMatcher in
|
||||||
// BuiltinTable.TMatcher or BuiltinTable.NMatcher, respectively.
|
// IntrinsicTable.TMatcher or IntrinsicTable.NMatcher, respectively.
|
||||||
func (b *overloadBuilder) matcherIndex(n sem.Named) (int, error) {
|
func (b *overloadBuilder) matcherIndex(n sem.Named) (int, error) {
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
case *sem.Type, *sem.TypeMatcher:
|
case *sem.Type, *sem.TypeMatcher:
|
||||||
@ -342,10 +344,10 @@ func (b *overloadBuilder) collectMatcherIndices(fqn sem.FullyQualifiedName) ([]i
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildBuiltinTable builds the BuiltinTable from the semantic info
|
// buildIntrinsicTable builds the IntrinsicTable from the semantic info
|
||||||
func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) {
|
func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
|
||||||
b := BuiltinTableBuilder{
|
b := IntrinsicTableBuilder{
|
||||||
BuiltinTable: BuiltinTable{
|
IntrinsicTable: IntrinsicTable{
|
||||||
Sem: s,
|
Sem: s,
|
||||||
TMatcherIndex: map[sem.Named]int{},
|
TMatcherIndex: map[sem.Named]int{},
|
||||||
NMatcherIndex: map[sem.Named]int{},
|
NMatcherIndex: map[sem.Named]int{},
|
||||||
@ -359,7 +361,9 @@ func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) {
|
|||||||
|
|
||||||
b.layoutMatchers(s)
|
b.layoutMatchers(s)
|
||||||
|
|
||||||
for _, f := range s.Functions {
|
buildIntrinsics := func(in []*sem.Intrinsic) ([]Intrinsic, error) {
|
||||||
|
out := make([]Intrinsic, len(in))
|
||||||
|
for i, f := range in {
|
||||||
overloads := make([]Overload, len(f.Overloads))
|
overloads := make([]Overload, len(f.Overloads))
|
||||||
overloadDescriptions := make([]string, len(f.Overloads))
|
overloadDescriptions := make([]string, len(f.Overloads))
|
||||||
for i, o := range f.Overloads {
|
for i, o := range f.Overloads {
|
||||||
@ -369,12 +373,22 @@ func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out[i] = Intrinsic{
|
||||||
b.Functions = append(b.Functions, Function{
|
Name: f.Name,
|
||||||
OverloadDescriptions: overloadDescriptions,
|
OverloadDescriptions: overloadDescriptions,
|
||||||
NumOverloads: len(overloads),
|
NumOverloads: len(overloads),
|
||||||
OverloadsOffset: b.lut.overloads.Add(overloads),
|
OverloadsOffset: b.lut.overloads.Add(overloads),
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if b.Builtins, err = buildIntrinsics(s.Builtins); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if b.Operators, err = buildIntrinsics(s.Operators); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.lut.matcherIndices.Compact()
|
b.lut.matcherIndices.Compact()
|
||||||
@ -383,5 +397,5 @@ func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) {
|
|||||||
b.lut.parameters.Compact()
|
b.lut.parameters.Compact()
|
||||||
b.lut.overloads.Compact()
|
b.lut.overloads.Compact()
|
||||||
|
|
||||||
return &b.BuiltinTable, nil
|
return &b.IntrinsicTable, nil
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ type generator struct {
|
|||||||
s *sem.Sem
|
s *sem.Sem
|
||||||
t *template.Template
|
t *template.Template
|
||||||
cached struct {
|
cached struct {
|
||||||
builtinTable *BuiltinTable // lazily built by builtinTable()
|
intrinsicTable *IntrinsicTable // lazily built by intrinsicTable()
|
||||||
permuter *Permuter // lazily built by permute()
|
permuter *Permuter // lazily built by permute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ func (g *generator) generate(tmpl string, w io.Writer, writeFile WriteFile) erro
|
|||||||
"IsDeclarable": isDeclarable,
|
"IsDeclarable": isDeclarable,
|
||||||
"IsFirstIn": isFirstIn,
|
"IsFirstIn": isFirstIn,
|
||||||
"IsLastIn": isLastIn,
|
"IsLastIn": isLastIn,
|
||||||
"BuiltinTable": g.builtinTable,
|
"IntrinsicTable": g.intrinsicTable,
|
||||||
"Permute": g.permute,
|
"Permute": g.permute,
|
||||||
"Eval": g.eval,
|
"Eval": g.eval,
|
||||||
"WriteFile": func(relpath, content string) (string, error) { return "", writeFile(relpath, content) },
|
"WriteFile": func(relpath, content string) (string, error) { return "", writeFile(relpath, content) },
|
||||||
@ -121,17 +121,17 @@ func (g *generator) eval(template string, args ...interface{}) (string, error) {
|
|||||||
return sb.String(), nil
|
return sb.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// builtinTable lazily calls and returns the result of buildBuiltinTable(),
|
// intrinsicTable lazily calls and returns the result of buildIntrinsicTable(),
|
||||||
// caching the result for repeated calls.
|
// caching the result for repeated calls.
|
||||||
func (g *generator) builtinTable() (*BuiltinTable, error) {
|
func (g *generator) intrinsicTable() (*IntrinsicTable, error) {
|
||||||
if g.cached.builtinTable == nil {
|
if g.cached.intrinsicTable == nil {
|
||||||
var err error
|
var err error
|
||||||
g.cached.builtinTable, err = buildBuiltinTable(g.s)
|
g.cached.intrinsicTable, err = buildIntrinsicTable(g.s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return g.cached.builtinTable, nil
|
return g.cached.intrinsicTable, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// permute lazily calls buildPermuter(), caching the result for repeated
|
// permute lazily calls buildPermuter(), caching the result for repeated
|
||||||
|
@ -74,7 +74,7 @@ func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) {
|
|||||||
permutate := func() error {
|
permutate := func() error {
|
||||||
o := sem.Overload{
|
o := sem.Overload{
|
||||||
Decl: overload.Decl,
|
Decl: overload.Decl,
|
||||||
Function: overload.Function,
|
Intrinsic: overload.Intrinsic,
|
||||||
CanBeUsedInStage: overload.CanBeUsedInStage,
|
CanBeUsedInStage: overload.CanBeUsedInStage,
|
||||||
}
|
}
|
||||||
for i, p := range overload.Parameters {
|
for i, p := range overload.Parameters {
|
||||||
|
@ -52,10 +52,6 @@ func (l *lexer) lex() error {
|
|||||||
l.next()
|
l.next()
|
||||||
case '\n':
|
case '\n':
|
||||||
l.next()
|
l.next()
|
||||||
case '<':
|
|
||||||
l.tok(1, tok.Lt)
|
|
||||||
case '>':
|
|
||||||
l.tok(1, tok.Gt)
|
|
||||||
case '(':
|
case '(':
|
||||||
l.tok(1, tok.Lparen)
|
l.tok(1, tok.Lparen)
|
||||||
case ')':
|
case ')':
|
||||||
@ -68,8 +64,14 @@ func (l *lexer) lex() error {
|
|||||||
l.tok(1, tok.Colon)
|
l.tok(1, tok.Colon)
|
||||||
case ',':
|
case ',':
|
||||||
l.tok(1, tok.Comma)
|
l.tok(1, tok.Comma)
|
||||||
case '|':
|
case '*':
|
||||||
l.tok(1, tok.Or)
|
l.tok(1, tok.Star)
|
||||||
|
case '+':
|
||||||
|
l.tok(1, tok.Plus)
|
||||||
|
case '%':
|
||||||
|
l.tok(1, tok.Modulo)
|
||||||
|
case '^':
|
||||||
|
l.tok(1, tok.Xor)
|
||||||
case '"':
|
case '"':
|
||||||
start := l.loc
|
start := l.loc
|
||||||
l.next() // Skip opening quote
|
l.next() // Skip opening quote
|
||||||
@ -81,13 +83,16 @@ func (l *lexer) lex() error {
|
|||||||
l.next() // Skip closing quote
|
l.next() // Skip closing quote
|
||||||
default:
|
default:
|
||||||
switch {
|
switch {
|
||||||
case l.peek(1) == '/':
|
case l.peek(0) == '/' && l.peek(1) == '/':
|
||||||
l.skip(l.count(toFirst('\n')))
|
l.skip(l.count(toFirst('\n')))
|
||||||
l.next() // Consume newline
|
l.next() // Consume newline
|
||||||
|
case l.match("/", tok.Divide):
|
||||||
case l.match("[[", tok.Ldeco):
|
case l.match("[[", tok.Ldeco):
|
||||||
case l.match("]]", tok.Rdeco):
|
case l.match("]]", tok.Rdeco):
|
||||||
case l.match("->", tok.Arrow):
|
case l.match("->", tok.Arrow):
|
||||||
|
case l.match("-", tok.Minus):
|
||||||
case l.match("fn", tok.Function):
|
case l.match("fn", tok.Function):
|
||||||
|
case l.match("op", tok.Operator):
|
||||||
case l.match("enum", tok.Enum):
|
case l.match("enum", tok.Enum):
|
||||||
case l.match("type", tok.Type):
|
case l.match("type", tok.Type):
|
||||||
case l.match("match", tok.Match):
|
case l.match("match", tok.Match):
|
||||||
@ -95,6 +100,19 @@ func (l *lexer) lex() error {
|
|||||||
l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier)
|
l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier)
|
||||||
case unicode.IsNumber(l.peek(0)):
|
case unicode.IsNumber(l.peek(0)):
|
||||||
l.tok(l.count(unicode.IsNumber), tok.Integer)
|
l.tok(l.count(unicode.IsNumber), tok.Integer)
|
||||||
|
case l.match("&&", tok.AndAnd):
|
||||||
|
case l.match("&", tok.And):
|
||||||
|
case l.match("||", tok.OrOr):
|
||||||
|
case l.match("|", tok.Or):
|
||||||
|
case l.match("!=", tok.NotEqual):
|
||||||
|
case l.match("==", tok.Equal):
|
||||||
|
case l.match("=", tok.Assign):
|
||||||
|
case l.match("<<", tok.Shl):
|
||||||
|
case l.match("<=", tok.Le):
|
||||||
|
case l.match("<", tok.Lt):
|
||||||
|
case l.match(">=", tok.Ge):
|
||||||
|
case l.match(">>", tok.Shr):
|
||||||
|
case l.match(">", tok.Gt):
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%v: unexpected '%v'", l.loc, string(l.runes[0]))
|
return fmt.Errorf("%v: unexpected '%v'", l.loc, string(l.runes[0]))
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,9 @@ func TestLexTokens(t *testing.T) {
|
|||||||
{"fn", tok.Token{Kind: tok.Function, Runes: []rune("fn"), Source: tok.Source{
|
{"fn", tok.Token{Kind: tok.Function, Runes: []rune("fn"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
}}},
|
}}},
|
||||||
|
{"op", tok.Token{Kind: tok.Operator, Runes: []rune("op"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
{"type", tok.Token{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
|
{"type", tok.Token{Kind: tok.Type, Runes: []rune("type"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
S: loc(1, 1, 0), E: loc(1, 5, 4),
|
||||||
}}},
|
}}},
|
||||||
@ -76,6 +79,45 @@ func TestLexTokens(t *testing.T) {
|
|||||||
{"}", tok.Token{Kind: tok.Rbrace, Runes: []rune("}"), Source: tok.Source{
|
{"}", tok.Token{Kind: tok.Rbrace, Runes: []rune("}"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
}}},
|
}}},
|
||||||
|
{"&&", tok.Token{Kind: tok.AndAnd, Runes: []rune("&&"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{"&", tok.Token{Kind: tok.And, Runes: []rune("&"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
|
}}},
|
||||||
|
{"||", tok.Token{Kind: tok.OrOr, Runes: []rune("||"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{"|", tok.Token{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
|
}}},
|
||||||
|
{"!=", tok.Token{Kind: tok.NotEqual, Runes: []rune("!="), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{"==", tok.Token{Kind: tok.Equal, Runes: []rune("=="), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{"=", tok.Token{Kind: tok.Assign, Runes: []rune("="), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
|
}}},
|
||||||
|
{"<<", tok.Token{Kind: tok.Shl, Runes: []rune("<<"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{"<=", tok.Token{Kind: tok.Le, Runes: []rune("<="), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{"<", tok.Token{Kind: tok.Lt, Runes: []rune("<"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
|
}}},
|
||||||
|
{">=", tok.Token{Kind: tok.Ge, Runes: []rune(">="), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{">>", tok.Token{Kind: tok.Shr, Runes: []rune(">>"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
|
}}},
|
||||||
|
{">", tok.Token{Kind: tok.Gt, Runes: []rune(">"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
|
}}},
|
||||||
{"[[", tok.Token{Kind: tok.Ldeco, Runes: []rune("[["), Source: tok.Source{
|
{"[[", tok.Token{Kind: tok.Ldeco, Runes: []rune("[["), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
}}},
|
}}},
|
||||||
@ -91,6 +133,9 @@ func TestLexTokens(t *testing.T) {
|
|||||||
{"|", tok.Token{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
|
{"|", tok.Token{Kind: tok.Or, Runes: []rune("|"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
}}},
|
}}},
|
||||||
|
{"*", tok.Token{Kind: tok.Star, Runes: []rune("*"), Source: tok.Source{
|
||||||
|
S: loc(1, 1, 0), E: loc(1, 2, 1),
|
||||||
|
}}},
|
||||||
{"->", tok.Token{Kind: tok.Arrow, Runes: []rune("->"), Source: tok.Source{
|
{"->", tok.Token{Kind: tok.Arrow, Runes: []rune("->"), Source: tok.Source{
|
||||||
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
S: loc(1, 1, 0), E: loc(1, 3, 2),
|
||||||
}}},
|
}}},
|
||||||
@ -134,10 +179,14 @@ func TestErrors(t *testing.T) {
|
|||||||
for _, test := range []test{
|
for _, test := range []test{
|
||||||
{" \"abc", "test.txt:1:2 unterminated string"},
|
{" \"abc", "test.txt:1:2 unterminated string"},
|
||||||
{" \"abc\n", "test.txt:1:2 unterminated string"},
|
{" \"abc\n", "test.txt:1:2 unterminated string"},
|
||||||
{"*", "test.txt:1:1: unexpected '*'"},
|
{"£", "test.txt:1:1: unexpected '£'"},
|
||||||
} {
|
} {
|
||||||
got, err := lexer.Lex([]rune(test.src), "test.txt")
|
got, err := lexer.Lex([]rune(test.src), "test.txt")
|
||||||
if gotErr := err.Error(); test.expect != gotErr {
|
gotErr := "<nil>"
|
||||||
|
if err != nil {
|
||||||
|
gotErr = err.Error()
|
||||||
|
}
|
||||||
|
if test.expect != gotErr {
|
||||||
t.Errorf(`Lex() returned error "%+v", expected error "%+v"`, gotErr, test.expect)
|
t.Errorf(`Lex() returned error "%+v", expected error "%+v"`, gotErr, test.expect)
|
||||||
}
|
}
|
||||||
if got != nil {
|
if got != nil {
|
||||||
|
@ -66,7 +66,10 @@ func (p *parser) parse() (*ast.AST, error) {
|
|||||||
out.Types = append(out.Types, p.typeDecl(decorations))
|
out.Types = append(out.Types, p.typeDecl(decorations))
|
||||||
decorations = nil
|
decorations = nil
|
||||||
case tok.Function:
|
case tok.Function:
|
||||||
out.Functions = append(out.Functions, p.functionDecl(decorations))
|
out.Builtins = append(out.Builtins, p.builtinDecl(decorations))
|
||||||
|
decorations = nil
|
||||||
|
case tok.Operator:
|
||||||
|
out.Operators = append(out.Operators, p.operatorDecl(decorations))
|
||||||
decorations = nil
|
decorations = nil
|
||||||
default:
|
default:
|
||||||
p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
|
p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
|
||||||
@ -153,11 +156,12 @@ func (p *parser) decorations() ast.Decorations {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) functionDecl(decos ast.Decorations) ast.FunctionDecl {
|
func (p *parser) builtinDecl(decos ast.Decorations) ast.IntrinsicDecl {
|
||||||
p.expect(tok.Function, "function declaration")
|
p.expect(tok.Function, "function declaration")
|
||||||
name := p.expect(tok.Identifier, "function name")
|
name := p.expect(tok.Identifier, "function name")
|
||||||
f := ast.FunctionDecl{
|
f := ast.IntrinsicDecl{
|
||||||
Source: name.Source,
|
Source: name.Source,
|
||||||
|
Kind: ast.Builtin,
|
||||||
Decorations: decos,
|
Decorations: decos,
|
||||||
Name: string(name.Runes),
|
Name: string(name.Runes),
|
||||||
}
|
}
|
||||||
@ -172,6 +176,25 @@ func (p *parser) functionDecl(decos ast.Decorations) ast.FunctionDecl {
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *parser) operatorDecl(decos ast.Decorations) ast.IntrinsicDecl {
|
||||||
|
p.expect(tok.Operator, "operator declaration")
|
||||||
|
name := p.next()
|
||||||
|
f := ast.IntrinsicDecl{
|
||||||
|
Source: name.Source,
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Decorations: decos,
|
||||||
|
Name: string(name.Runes),
|
||||||
|
}
|
||||||
|
if p.peekIs(0, tok.Lt) {
|
||||||
|
f.TemplateParams = p.templateParams()
|
||||||
|
}
|
||||||
|
f.Parameters = p.parameters()
|
||||||
|
if p.match(tok.Arrow) != nil {
|
||||||
|
ret := p.templatedName()
|
||||||
|
f.ReturnType = &ret
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
func (p *parser) parameters() ast.Parameters {
|
func (p *parser) parameters() ast.Parameters {
|
||||||
l := ast.Parameters{}
|
l := ast.Parameters{}
|
||||||
p.expect(tok.Lparen, "function parameter list")
|
p.expect(tok.Lparen, "function parameter list")
|
||||||
@ -270,20 +293,6 @@ func (p *parser) ident(use string) string {
|
|||||||
return string(p.expect(tok.Identifier, use).Runes)
|
return string(p.expect(tok.Identifier, use).Runes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bclayton): Currently unused, but will be needed for integer bounds
|
|
||||||
// func (p *parser) integer(use string) int {
|
|
||||||
// t := p.expect(tok.Integer, use)
|
|
||||||
// if t.Kind != tok.Integer {
|
|
||||||
// return 0
|
|
||||||
// }
|
|
||||||
// i, err := strconv.Atoi(string(t.Runes))
|
|
||||||
// if err != nil {
|
|
||||||
// p.err = err
|
|
||||||
// return 0
|
|
||||||
// }
|
|
||||||
// return i
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (p *parser) match(kind tok.Kind) *tok.Token {
|
func (p *parser) match(kind tok.Kind) *tok.Token {
|
||||||
if p.err != nil || len(p.tokens) == 0 {
|
if p.err != nil || len(p.tokens) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -296,6 +305,18 @@ func (p *parser) match(kind tok.Kind) *tok.Token {
|
|||||||
return &t
|
return &t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *parser) next() *tok.Token {
|
||||||
|
if p.err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(p.tokens) == 0 {
|
||||||
|
p.err = fmt.Errorf("reached end of file")
|
||||||
|
}
|
||||||
|
t := p.tokens[0]
|
||||||
|
p.tokens = p.tokens[1:]
|
||||||
|
return &t
|
||||||
|
}
|
||||||
|
|
||||||
func (p *parser) peekIs(i int, kind tok.Kind) bool {
|
func (p *parser) peekIs(i int, kind tok.Kind) bool {
|
||||||
t := p.peek(i)
|
t := p.peek(i)
|
||||||
if t == nil {
|
if t == nil {
|
||||||
|
@ -19,35 +19,57 @@ import (
|
|||||||
|
|
||||||
"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/ast"
|
"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/ast"
|
||||||
"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/parser"
|
"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/parser"
|
||||||
|
"dawn.googlesource.com/dawn/tools/src/utils"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ignoreSource = cmp.FilterPath(func(p cmp.Path) bool {
|
||||||
|
return p.Last().String() == ".Source"
|
||||||
|
}, cmp.Ignore())
|
||||||
|
|
||||||
func TestParser(t *testing.T) {
|
func TestParser(t *testing.T) {
|
||||||
type test struct {
|
type test struct {
|
||||||
|
location string
|
||||||
src string
|
src string
|
||||||
expect ast.AST
|
expect ast.AST
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range []test{
|
for _, test := range []test{
|
||||||
{"enum E {}", ast.AST{
|
{
|
||||||
|
utils.ThisLine(),
|
||||||
|
"enum E {}",
|
||||||
|
ast.AST{
|
||||||
Enums: []ast.EnumDecl{{Name: "E"}},
|
Enums: []ast.EnumDecl{{Name: "E"}},
|
||||||
}},
|
},
|
||||||
{"enum E { A [[deco]] B C }", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"enum E { A [[deco]] B C }",
|
||||||
|
ast.AST{
|
||||||
Enums: []ast.EnumDecl{{
|
Enums: []ast.EnumDecl{{
|
||||||
Name: "E",
|
Name: "E",
|
||||||
Entries: []ast.EnumEntry{
|
Entries: []ast.EnumEntry{
|
||||||
{Name: "A"},
|
{Name: "A"},
|
||||||
{
|
{
|
||||||
Decorations: ast.Decorations{{Name: "deco"}},
|
Decorations: ast.Decorations{{
|
||||||
|
Name: "deco",
|
||||||
|
Values: []string{},
|
||||||
|
}},
|
||||||
Name: "B",
|
Name: "B",
|
||||||
},
|
},
|
||||||
{Name: "C"},
|
{Name: "C"},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"type T", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"type T",
|
||||||
|
ast.AST{
|
||||||
Types: []ast.TypeDecl{{Name: "T"}},
|
Types: []ast.TypeDecl{{Name: "T"}},
|
||||||
}},
|
},
|
||||||
{"type T<A, B, C>", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"type T<A, B, C>",
|
||||||
|
ast.AST{
|
||||||
Types: []ast.TypeDecl{{
|
Types: []ast.TypeDecl{{
|
||||||
Name: "T",
|
Name: "T",
|
||||||
TemplateParams: ast.TemplateParams{
|
TemplateParams: ast.TemplateParams{
|
||||||
@ -56,32 +78,43 @@ func TestParser(t *testing.T) {
|
|||||||
{Name: "C"},
|
{Name: "C"},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"[[deco]] type T", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"[[deco]] type T",
|
||||||
|
ast.AST{
|
||||||
Types: []ast.TypeDecl{{
|
Types: []ast.TypeDecl{{
|
||||||
Decorations: ast.Decorations{
|
Decorations: ast.Decorations{
|
||||||
{Name: "deco"},
|
{Name: "deco", Values: []string{}},
|
||||||
},
|
},
|
||||||
Name: "T",
|
Name: "T",
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{`[[deco("a", "b")]] type T`, ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
`[[deco("a", "b")]] type T`, ast.AST{
|
||||||
Types: []ast.TypeDecl{{
|
Types: []ast.TypeDecl{{
|
||||||
Decorations: ast.Decorations{
|
Decorations: ast.Decorations{
|
||||||
{Name: "deco", Values: []string{"a", "b"}},
|
{Name: "deco", Values: []string{"a", "b"}},
|
||||||
},
|
},
|
||||||
Name: "T",
|
Name: "T",
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"match M : A", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"match M : A",
|
||||||
|
ast.AST{
|
||||||
Matchers: []ast.MatcherDecl{{
|
Matchers: []ast.MatcherDecl{{
|
||||||
Name: "M",
|
Name: "M",
|
||||||
Options: ast.MatcherOptions{
|
Options: ast.MatcherOptions{
|
||||||
ast.TemplatedName{Name: "A"},
|
ast.TemplatedName{Name: "A"},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"match M : A | B", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"match M : A | B",
|
||||||
|
ast.AST{
|
||||||
Matchers: []ast.MatcherDecl{{
|
Matchers: []ast.MatcherDecl{{
|
||||||
Name: "M",
|
Name: "M",
|
||||||
Options: ast.MatcherOptions{
|
Options: ast.MatcherOptions{
|
||||||
@ -89,47 +122,73 @@ func TestParser(t *testing.T) {
|
|||||||
ast.TemplatedName{Name: "B"},
|
ast.TemplatedName{Name: "B"},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F()", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F()",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"[[deco]] fn F()", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"[[deco]] fn F()",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
Decorations: ast.Decorations{
|
Decorations: ast.Decorations{
|
||||||
{Name: "deco"},
|
{Name: "deco", Values: []string{}},
|
||||||
},
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F(a)", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F(a)",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
Parameters: ast.Parameters{
|
Parameters: ast.Parameters{
|
||||||
{Type: ast.TemplatedName{Name: "a"}},
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F(a: T)", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F(a: T)",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
Parameters: ast.Parameters{
|
Parameters: ast.Parameters{
|
||||||
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F(a, b)", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F(a, b)",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
Parameters: ast.Parameters{
|
Parameters: ast.Parameters{
|
||||||
{Type: ast.TemplatedName{Name: "a"}},
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
{Type: ast.TemplatedName{Name: "b"}},
|
{Type: ast.TemplatedName{Name: "b"}},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F<A : B<C>>()", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F<A : B<C> >()",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
TemplateParams: ast.TemplateParams{
|
TemplateParams: ast.TemplateParams{
|
||||||
{
|
{
|
||||||
@ -141,10 +200,15 @@ func TestParser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F<T>(a: X, b: Y<T>)", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F<T>(a: X, b: Y<T>)",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
TemplateParams: ast.TemplateParams{
|
TemplateParams: ast.TemplateParams{
|
||||||
{Name: "T"},
|
{Name: "T"},
|
||||||
@ -157,32 +221,167 @@ func TestParser(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F() -> X", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F() -> X",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
ReturnType: &ast.TemplatedName{Name: "X"},
|
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
}},
|
}},
|
||||||
}},
|
},
|
||||||
{"fn F() -> X<T>", ast.AST{
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
Functions: []ast.FunctionDecl{{
|
utils.ThisLine(),
|
||||||
|
"fn F() -> X<T>",
|
||||||
|
ast.AST{
|
||||||
|
Builtins: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Builtin,
|
||||||
Name: "F",
|
Name: "F",
|
||||||
ReturnType: &ast.TemplatedName{
|
ReturnType: &ast.TemplatedName{
|
||||||
Name: "X",
|
Name: "X",
|
||||||
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
},
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F()",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"[[deco]] op F()",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
Decorations: ast.Decorations{
|
||||||
|
{Name: "deco", Values: []string{}},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F(a)",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F(a: T)",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Name: "a", Type: ast.TemplatedName{Name: "T"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F(a, b)",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Type: ast.TemplatedName{Name: "a"}},
|
||||||
|
{Type: ast.TemplatedName{Name: "b"}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F<A : B<C> >()",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
TemplateParams: ast.TemplateParams{
|
||||||
|
{
|
||||||
|
Name: "A", Type: ast.TemplatedName{
|
||||||
|
Name: "B",
|
||||||
|
TemplateArgs: ast.TemplatedNames{
|
||||||
|
{Name: "C"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F<T>(a: X, b: Y<T>)",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
TemplateParams: ast.TemplateParams{
|
||||||
|
{Name: "T"},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{
|
||||||
|
{Name: "a", Type: ast.TemplatedName{Name: "X"}},
|
||||||
|
{Name: "b", Type: ast.TemplatedName{
|
||||||
|
Name: "Y",
|
||||||
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F() -> X",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
ReturnType: &ast.TemplatedName{Name: "X"},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}, { ///////////////////////////////////////////////////////////////////
|
||||||
|
utils.ThisLine(),
|
||||||
|
"op F() -> X<T>",
|
||||||
|
ast.AST{
|
||||||
|
Operators: []ast.IntrinsicDecl{{
|
||||||
|
Kind: ast.Operator,
|
||||||
|
Name: "F",
|
||||||
|
ReturnType: &ast.TemplatedName{
|
||||||
|
Name: "X",
|
||||||
|
TemplateArgs: []ast.TemplatedName{{Name: "T"}},
|
||||||
|
},
|
||||||
|
Parameters: ast.Parameters{},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
} {
|
} {
|
||||||
got, err := parser.Parse(test.src, "file.txt")
|
got, err := parser.Parse(test.src, "file.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("While parsing:\n%s\nParse() returned error: %v", test.src, err)
|
t.Errorf("\n%v\nWhile parsing:\n%s\nParse() returned error: %v",
|
||||||
|
test.location, test.src, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
gotStr, expectStr := got.String(), test.expect.String()
|
if diff := cmp.Diff(got, &test.expect, ignoreSource); diff != "" {
|
||||||
if gotStr != expectStr {
|
t.Errorf("\n%v\nWhile parsing:\n%s\n\n%s",
|
||||||
t.Errorf("While parsing:\n%s\nGot:\n%s\nExpected:\n%s", test.src, gotStr, expectStr)
|
test.location, test.src, diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,10 +393,22 @@ func TestErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range []test{
|
for _, test := range []test{
|
||||||
{"+", "test.txt:1:1: unexpected '+'"},
|
{
|
||||||
{"123", "test.txt:1:1 unexpected token 'integer'"},
|
"£",
|
||||||
{"[[123]]", "test.txt:1:3 expected 'ident' for decoration name, got 'integer'"},
|
"test.txt:1:1: unexpected '£'",
|
||||||
{"[[abc", "expected ']]' for decoration list, but reached end of file"},
|
},
|
||||||
|
{
|
||||||
|
"123",
|
||||||
|
"test.txt:1:1 unexpected token 'integer'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"[[123]]",
|
||||||
|
"test.txt:1:3 expected 'ident' for decoration name, got 'integer'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"[[abc",
|
||||||
|
"expected ']]' for decoration list, but reached end of file",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
got, err := parser.Parse(test.src, "test.txt")
|
got, err := parser.Parse(test.src, "test.txt")
|
||||||
if gotErr := err.Error(); test.expect != gotErr {
|
if gotErr := err.Error(); test.expect != gotErr {
|
||||||
|
@ -28,7 +28,8 @@ type resolver struct {
|
|||||||
s *sem.Sem
|
s *sem.Sem
|
||||||
|
|
||||||
globals scope
|
globals scope
|
||||||
functions map[string]*sem.Function
|
builtins map[string]*sem.Intrinsic
|
||||||
|
operators map[string]*sem.Intrinsic
|
||||||
enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
|
enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +39,8 @@ func Resolve(a *ast.AST) (*sem.Sem, error) {
|
|||||||
a: a,
|
a: a,
|
||||||
s: sem.New(),
|
s: sem.New(),
|
||||||
globals: newScope(nil),
|
globals: newScope(nil),
|
||||||
functions: map[string]*sem.Function{},
|
builtins: map[string]*sem.Intrinsic{},
|
||||||
|
operators: map[string]*sem.Intrinsic{},
|
||||||
enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
|
enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
|
||||||
}
|
}
|
||||||
// Declare and resolve all the enumerators
|
// Declare and resolve all the enumerators
|
||||||
@ -59,9 +61,15 @@ func Resolve(a *ast.AST) (*sem.Sem, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Declare and resolve the functions
|
// Declare and resolve the builtins
|
||||||
for _, f := range a.Functions {
|
for _, f := range a.Builtins {
|
||||||
if err := r.function(f); err != nil {
|
if err := r.intrinsic(f, r.builtins, &r.s.Builtins); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Declare and resolve the operators
|
||||||
|
for _, o := range a.Operators {
|
||||||
|
if err := r.intrinsic(o, r.operators, &r.s.Operators); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,18 +228,21 @@ func (r *resolver) matcher(a ast.MatcherDecl) error {
|
|||||||
return fmt.Errorf("'%v' cannot be used for matcher", a.Name)
|
return fmt.Errorf("'%v' cannot be used for matcher", a.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// function() resolves a function overload declaration.
|
// intrinsic() resolves a intrinsic overload declaration.
|
||||||
// The the first overload for the function creates and appends the sem.Function
|
// The the first overload for the intrinsic creates and appends the sem.Intrinsic
|
||||||
// to Sem.Functions. Subsequent overloads append their resolved overload to the
|
// to Sem.Intrinsics. Subsequent overloads append their resolved overload to the
|
||||||
// sem.Function.Overloads list.
|
// sem.intrinsic.Overloads list.
|
||||||
func (r *resolver) function(a ast.FunctionDecl) error {
|
func (r *resolver) intrinsic(
|
||||||
// If this is the first overload of the function, create and register the
|
a ast.IntrinsicDecl,
|
||||||
// semantic function.
|
intrinsicsByName map[string]*sem.Intrinsic,
|
||||||
f := r.functions[a.Name]
|
semIntrinsics *[]*sem.Intrinsic) error {
|
||||||
if f == nil {
|
// If this is the first overload of the intrinsic, create and register the
|
||||||
f = &sem.Function{Name: a.Name}
|
// semantic intrinsic.
|
||||||
r.functions[a.Name] = f
|
intrinsic := intrinsicsByName[a.Name]
|
||||||
r.s.Functions = append(r.s.Functions, f)
|
if intrinsic == nil {
|
||||||
|
intrinsic = &sem.Intrinsic{Name: a.Name}
|
||||||
|
intrinsicsByName[a.Name] = intrinsic
|
||||||
|
*semIntrinsics = append(*semIntrinsics, intrinsic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new scope for resolving template parameters
|
// Create a new scope for resolving template parameters
|
||||||
@ -246,7 +257,7 @@ func (r *resolver) function(a ast.FunctionDecl) error {
|
|||||||
// Construct the semantic overload
|
// Construct the semantic overload
|
||||||
overload := &sem.Overload{
|
overload := &sem.Overload{
|
||||||
Decl: a,
|
Decl: a,
|
||||||
Function: f,
|
Intrinsic: intrinsic,
|
||||||
Parameters: make([]sem.Parameter, len(a.Parameters)),
|
Parameters: make([]sem.Parameter, len(a.Parameters)),
|
||||||
TemplateParams: templateParams,
|
TemplateParams: templateParams,
|
||||||
}
|
}
|
||||||
@ -285,8 +296,8 @@ func (r *resolver) function(a ast.FunctionDecl) error {
|
|||||||
return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source)
|
return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the overload to the function
|
// Append the overload to the intrinsic
|
||||||
f.Overloads = append(f.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.OpenTypes or sem.Overload.OpenNumbers based on their kind.
|
||||||
@ -307,6 +318,10 @@ func (r *resolver) function(a ast.FunctionDecl) error {
|
|||||||
r.s.MaxOpenNumbers = len(overload.OpenNumbers)
|
r.s.MaxOpenNumbers = len(overload.OpenNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.Kind == ast.Operator && (len(a.Parameters) < 1 || len(a.Parameters) > 2) {
|
||||||
|
return fmt.Errorf("%v operators must have either 1 or 2 parameters", a.Source)
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve the parameters
|
// Resolve the parameters
|
||||||
for i, p := range a.Parameters {
|
for i, p := range a.Parameters {
|
||||||
usage, err := r.fullyQualifiedName(&s, p.Type)
|
usage, err := r.fullyQualifiedName(&s, p.Type)
|
||||||
@ -495,11 +510,11 @@ func (r *resolver) lookupNamed(s *scope, a ast.TemplatedName) (sem.Named, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculateUniqueParameterNames() iterates over all the parameters of all
|
// calculateUniqueParameterNames() iterates over all the parameters of all
|
||||||
// overloads, calculating the list of unique parameter names
|
// builtin overloads, calculating the list of unique parameter names
|
||||||
func (r *resolver) calculateUniqueParameterNames() []string {
|
func (r *resolver) calculateUniqueParameterNames() []string {
|
||||||
set := map[string]struct{}{"": {}}
|
set := map[string]struct{}{"": {}}
|
||||||
names := []string{}
|
names := []string{}
|
||||||
for _, f := range r.s.Functions {
|
for _, f := range r.s.Builtins {
|
||||||
for _, o := range f.Overloads {
|
for _, o := range f.Overloads {
|
||||||
for _, p := range o.Parameters {
|
for _, p := range o.Parameters {
|
||||||
if _, dup := set[p.Name]; !dup {
|
if _, dup := set[p.Name]; !dup {
|
||||||
|
@ -299,6 +299,70 @@ fn f<M: m>(P<M>)`,
|
|||||||
`file.txt:4:14 cannot use template enum 'E' as template number`,
|
`file.txt:4:14 cannot use template enum 'E' as template number`,
|
||||||
}, {
|
}, {
|
||||||
`
|
`
|
||||||
|
type i
|
||||||
|
enum e { a }
|
||||||
|
op << (i) -> e`,
|
||||||
|
`file.txt:3:14 cannot use 'e' as return type. Must be a type or template type`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type T<x>
|
||||||
|
op << (T<u>)`,
|
||||||
|
`file.txt:2:10 cannot resolve 'u'`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
op << ()`,
|
||||||
|
`file.txt:1:4 operators must have either 1 or 2 parameters`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type i
|
||||||
|
op << (i, i, i)`,
|
||||||
|
`file.txt:2:4 operators must have either 1 or 2 parameters`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type x
|
||||||
|
op << <T>(T<x>)`,
|
||||||
|
`file.txt:2:11 'T' template parameters do not accept template arguments`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type A<N: num>
|
||||||
|
type B
|
||||||
|
op << (A<B>)`,
|
||||||
|
`file.txt:3:10 cannot use type 'B' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type A<N>
|
||||||
|
enum E { b }
|
||||||
|
op << (A<b>)`,
|
||||||
|
`file.txt:3:10 cannot use enum entry 'E.b' as template type`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type T
|
||||||
|
type P<N: num>
|
||||||
|
match m: T
|
||||||
|
op << (P<m>)`,
|
||||||
|
`file.txt:4:10 cannot use type matcher 'm' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { b }
|
||||||
|
op << (P<E>)`,
|
||||||
|
`file.txt:3:10 cannot use enum 'E' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { a b }
|
||||||
|
match m: a | b
|
||||||
|
op << (P<m>)`,
|
||||||
|
`file.txt:4:10 cannot use enum matcher 'm' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
|
type P<N: num>
|
||||||
|
enum E { a b }
|
||||||
|
match m: a | b
|
||||||
|
op << <M: m>(P<M>)`,
|
||||||
|
`file.txt:4:16 cannot use template enum 'E' as template number`,
|
||||||
|
}, {
|
||||||
|
`
|
||||||
enum E { a }
|
enum E { a }
|
||||||
type T<X: a>`,
|
type T<X: a>`,
|
||||||
`file.txt:2:8 invalid template parameter type 'a'`,
|
`file.txt:2:8 invalid template parameter type 'a'`,
|
||||||
|
@ -26,7 +26,8 @@ type Sem struct {
|
|||||||
Types []*Type
|
Types []*Type
|
||||||
TypeMatchers []*TypeMatcher
|
TypeMatchers []*TypeMatcher
|
||||||
EnumMatchers []*EnumMatcher
|
EnumMatchers []*EnumMatcher
|
||||||
Functions []*Function
|
Builtins []*Intrinsic
|
||||||
|
Operators []*Intrinsic
|
||||||
// Maximum number of open-types used across all builtins
|
// Maximum number of open-types used across all builtins
|
||||||
MaxOpenTypes int
|
MaxOpenTypes int
|
||||||
// Maximum number of open-numbers used across all builtins
|
// Maximum number of open-numbers used across all builtins
|
||||||
@ -42,7 +43,8 @@ func New() *Sem {
|
|||||||
Types: []*Type{},
|
Types: []*Type{},
|
||||||
TypeMatchers: []*TypeMatcher{},
|
TypeMatchers: []*TypeMatcher{},
|
||||||
EnumMatchers: []*EnumMatcher{},
|
EnumMatchers: []*EnumMatcher{},
|
||||||
Functions: []*Function{},
|
Builtins: []*Intrinsic{},
|
||||||
|
Operators: []*Intrinsic{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,16 +123,16 @@ type TemplateNumberParam struct {
|
|||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function describes the overloads of a builtin function
|
// Intrinsic describes the overloads of a builtin or operator
|
||||||
type Function struct {
|
type Intrinsic struct {
|
||||||
Name string
|
Name string
|
||||||
Overloads []*Overload
|
Overloads []*Overload
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overload describes a single overload of a function
|
// Overload describes a single overload of a builtin or operator
|
||||||
type Overload struct {
|
type Overload struct {
|
||||||
Decl ast.FunctionDecl
|
Decl ast.IntrinsicDecl
|
||||||
Function *Function
|
Intrinsic *Intrinsic
|
||||||
TemplateParams []TemplateParam
|
TemplateParams []TemplateParam
|
||||||
OpenTypes []*TemplateTypeParam
|
OpenTypes []*TemplateTypeParam
|
||||||
OpenNumbers []TemplateParam
|
OpenNumbers []TemplateParam
|
||||||
@ -164,7 +166,13 @@ func (u StageUses) List() []string {
|
|||||||
|
|
||||||
// Format implements the fmt.Formatter interface
|
// Format implements the fmt.Formatter interface
|
||||||
func (o Overload) Format(w fmt.State, verb rune) {
|
func (o Overload) Format(w fmt.State, verb rune) {
|
||||||
fmt.Fprintf(w, "fn %v", o.Function.Name)
|
switch o.Decl.Kind {
|
||||||
|
case ast.Builtin:
|
||||||
|
fmt.Fprintf(w, "fn ")
|
||||||
|
case ast.Operator:
|
||||||
|
fmt.Fprintf(w, "op ")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "%v", o.Intrinsic.Name)
|
||||||
if len(o.TemplateParams) > 0 {
|
if len(o.TemplateParams) > 0 {
|
||||||
fmt.Fprintf(w, "<")
|
fmt.Fprintf(w, "<")
|
||||||
for i, t := range o.TemplateParams {
|
for i, t := range o.TemplateParams {
|
||||||
|
@ -29,12 +29,17 @@ const (
|
|||||||
String Kind = "string"
|
String Kind = "string"
|
||||||
Match Kind = "match"
|
Match Kind = "match"
|
||||||
Function Kind = "fn"
|
Function Kind = "fn"
|
||||||
|
Operator Kind = "op"
|
||||||
Type Kind = "type"
|
Type Kind = "type"
|
||||||
Enum Kind = "enum"
|
Enum Kind = "enum"
|
||||||
Colon Kind = ":"
|
Colon Kind = ":"
|
||||||
Comma Kind = ","
|
Comma Kind = ","
|
||||||
|
Shl Kind = "<<"
|
||||||
|
Shr Kind = ">>"
|
||||||
Lt Kind = "<"
|
Lt Kind = "<"
|
||||||
|
Le Kind = "<="
|
||||||
Gt Kind = ">"
|
Gt Kind = ">"
|
||||||
|
Ge Kind = ">="
|
||||||
Lbrace Kind = "{"
|
Lbrace Kind = "{"
|
||||||
Rbrace Kind = "}"
|
Rbrace Kind = "}"
|
||||||
Ldeco Kind = "[["
|
Ldeco Kind = "[["
|
||||||
@ -43,6 +48,18 @@ const (
|
|||||||
Rparen Kind = ")"
|
Rparen Kind = ")"
|
||||||
Or Kind = "|"
|
Or Kind = "|"
|
||||||
Arrow Kind = "->"
|
Arrow Kind = "->"
|
||||||
|
Star Kind = "*"
|
||||||
|
Divide Kind = "/"
|
||||||
|
Modulo Kind = "%"
|
||||||
|
Xor Kind = "^"
|
||||||
|
Plus Kind = "+"
|
||||||
|
Minus Kind = "-"
|
||||||
|
And Kind = "&"
|
||||||
|
AndAnd Kind = "&&"
|
||||||
|
OrOr Kind = "||"
|
||||||
|
NotEqual Kind = "!="
|
||||||
|
Equal Kind = "=="
|
||||||
|
Assign Kind = "="
|
||||||
)
|
)
|
||||||
|
|
||||||
// Invalid represents an invalid token
|
// Invalid represents an invalid token
|
||||||
|
Loading…
x
Reference in New Issue
Block a user