diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc index 7656e55429..58cc0b0dd0 100644 --- a/src/tint/resolver/intrinsic_table.cc +++ b/src/tint/resolver/intrinsic_table.cc @@ -762,9 +762,9 @@ struct OverloadInfo { bool is_deprecated; }; -/// BuiltinInfo describes a builtin function -struct BuiltinInfo { - /// Number of overloads of the builtin function +/// IntrinsicInfo describes a builtin function +struct IntrinsicInfo { + /// Number of overloads of the intrinsic const uint8_t num_overloads; /// Pointer to the start of the overloads for the function OverloadInfo const* const overloads; @@ -772,9 +772,8 @@ struct BuiltinInfo { #include "intrinsic_table.inl" -/// BuiltinPrototype describes a fully matched builtin function, which is -/// used as a lookup for building unique sem::Builtin instances. -struct BuiltinPrototype { +/// IntrinsicPrototype describes a fully matched intrinsic. +struct IntrinsicPrototype { /// Parameter describes a single parameter struct Parameter { /// Parameter type @@ -783,11 +782,11 @@ struct BuiltinPrototype { ParameterUsage const usage = ParameterUsage::kNone; }; - /// Hasher provides a hash function for the BuiltinPrototype + /// Hasher provides a hash function for the IntrinsicPrototype struct Hasher { - /// @param i the BuiltinPrototype to create a hash for + /// @param i the IntrinsicPrototype to create a hash for /// @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()); for (auto& p : i.parameters) { utils::HashCombine(&hash, p.type, p.usage); @@ -803,8 +802,8 @@ struct BuiltinPrototype { bool is_deprecated = false; }; -/// Equality operator for BuiltinPrototype -bool operator==(const BuiltinPrototype& a, const BuiltinPrototype& b) { +/// Equality operator for IntrinsicPrototype +bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) { if (a.type != b.type || a.supported_stages != b.supported_stages || a.return_type != b.return_type || a.is_deprecated != b.is_deprecated || a.parameters.size() != b.parameters.size()) { @@ -845,7 +844,7 @@ class Impl : public IntrinsicTable { ProgramBuilder& builder; Matchers matchers; - std::unordered_map builtins; + std::unordered_map builtins; }; /// @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); - std::vector parameters; + std::vector parameters; auto num_params = std::min(num_parameters, num_arguments); 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* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef()); if (type) { - parameters.emplace_back(BuiltinPrototype::Parameter{type, parameter.usage}); + parameters.emplace_back(IntrinsicPrototype::Parameter{type, parameter.usage}); match_score += kScorePerMatchedParam; } else { overload_matched = false; @@ -1014,7 +1013,7 @@ const sem::Builtin* Impl::Match(sem::BuiltinType builtin_type, return_type = builder.create(); } - BuiltinPrototype builtin; + IntrinsicPrototype builtin; builtin.type = builtin_type; builtin.return_type = return_type; builtin.parameters = std::move(parameters); diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl index fa48359728..acced8f4ef 100644 --- a/src/tint/resolver/intrinsic_table.inl +++ b/src/tint/resolver/intrinsic_table.inl @@ -13,11 +13,11 @@ // limitations under the License. //////////////////////////////////////////////////////////////////////////////// -// File generated by tools/builtin-gen +// File generated by tools/intrinsic-gen // using the template: -// src/tint/builtin_table.inl.tmpl -// and the builtin defintion file: -// src/tint/builtins.def +// src/tint/resolver/intrinsic_table.inl.tmpl +// and the intrinsic defintion file: +// src/tint/intrinsics.def // // Do not modify this file directly //////////////////////////////////////////////////////////////////////////////// @@ -25,7 +25,7 @@ // clang-format off /// TypeMatcher for 'type bool' -/// @see src/tint/builtins.def:68:6 +/// @see src/tint/intrinsics.def:68:6 class Bool : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -52,7 +52,7 @@ std::string Bool::String(MatchState&) const { } /// TypeMatcher for 'type f32' -/// @see src/tint/builtins.def:69:6 +/// @see src/tint/intrinsics.def:69:6 class F32 : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -79,7 +79,7 @@ std::string F32::String(MatchState&) const { } /// TypeMatcher for 'type i32' -/// @see src/tint/builtins.def:70:6 +/// @see src/tint/intrinsics.def:70:6 class I32 : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -106,7 +106,7 @@ std::string I32::String(MatchState&) const { } /// TypeMatcher for 'type u32' -/// @see src/tint/builtins.def:71:6 +/// @see src/tint/intrinsics.def:71:6 class U32 : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -133,7 +133,7 @@ std::string U32::String(MatchState&) const { } /// TypeMatcher for 'type vec2' -/// @see src/tint/builtins.def:72:6 +/// @see src/tint/intrinsics.def:72:6 class Vec2 : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -166,7 +166,7 @@ std::string Vec2::String(MatchState& state) const { } /// TypeMatcher for 'type vec3' -/// @see src/tint/builtins.def:73:6 +/// @see src/tint/intrinsics.def:73:6 class Vec3 : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -199,7 +199,7 @@ std::string Vec3::String(MatchState& state) const { } /// TypeMatcher for 'type vec4' -/// @see src/tint/builtins.def:74:6 +/// @see src/tint/intrinsics.def:74:6 class Vec4 : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -232,7 +232,7 @@ std::string Vec4::String(MatchState& state) const { } /// TypeMatcher for 'type vec' -/// @see src/tint/builtins.def:75:37 +/// @see src/tint/intrinsics.def:75:37 class Vec : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -273,7 +273,7 @@ std::string Vec::String(MatchState& state) const { } /// TypeMatcher for 'type mat' -/// @see src/tint/builtins.def:76:37 +/// @see src/tint/intrinsics.def:76:37 class Mat : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -320,7 +320,7 @@ std::string Mat::String(MatchState& state) const { } /// TypeMatcher for 'type ptr' -/// @see src/tint/builtins.def:77:6 +/// @see src/tint/intrinsics.def:77:6 class Ptr : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -365,7 +365,7 @@ std::string Ptr::String(MatchState& state) const { } /// TypeMatcher for 'type atomic' -/// @see src/tint/builtins.def:78:6 +/// @see src/tint/intrinsics.def:78:6 class Atomic : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -398,7 +398,7 @@ std::string Atomic::String(MatchState& state) const { } /// TypeMatcher for 'type array' -/// @see src/tint/builtins.def:79:6 +/// @see src/tint/intrinsics.def:79:6 class Array : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -431,7 +431,7 @@ std::string Array::String(MatchState& state) const { } /// TypeMatcher for 'type sampler' -/// @see src/tint/builtins.def:80:6 +/// @see src/tint/intrinsics.def:80:6 class Sampler : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -458,7 +458,7 @@ std::string Sampler::String(MatchState&) const { } /// TypeMatcher for 'type sampler_comparison' -/// @see src/tint/builtins.def:81:6 +/// @see src/tint/intrinsics.def:81:6 class SamplerComparison : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -485,7 +485,7 @@ std::string SamplerComparison::String(MatchState&) const { } /// TypeMatcher for 'type texture_1d' -/// @see src/tint/builtins.def:82:6 +/// @see src/tint/intrinsics.def:82:6 class Texture1D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:83:6 +/// @see src/tint/intrinsics.def:83:6 class Texture2D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:84:6 +/// @see src/tint/intrinsics.def:84:6 class Texture2DArray : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:85:6 +/// @see src/tint/intrinsics.def:85:6 class Texture3D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:86:6 +/// @see src/tint/intrinsics.def:86:6 class TextureCube : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:87:6 +/// @see src/tint/intrinsics.def:87:6 class TextureCubeArray : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:88:6 +/// @see src/tint/intrinsics.def:88:6 class TextureMultisampled2D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:89:6 +/// @see src/tint/intrinsics.def:89:6 class TextureDepth2D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:90:6 +/// @see src/tint/intrinsics.def:90:6 class TextureDepth2DArray : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:91:6 +/// @see src/tint/intrinsics.def:91:6 class TextureDepthCube : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:92:6 +/// @see src/tint/intrinsics.def:92:6 class TextureDepthCubeArray : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:93:6 +/// @see src/tint/intrinsics.def:93:6 class TextureDepthMultisampled2D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:94:6 +/// @see src/tint/intrinsics.def:94:6 class TextureStorage1D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:95:6 +/// @see src/tint/intrinsics.def:95:6 class TextureStorage2D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:96:6 +/// @see src/tint/intrinsics.def:96:6 class TextureStorage2DArray : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:97:6 +/// @see src/tint/intrinsics.def:97:6 class TextureStorage3D : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:98:6 +/// @see src/tint/intrinsics.def:98:6 class TextureExternal : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -1034,7 +1034,7 @@ std::string TextureExternal::String(MatchState&) const { } /// TypeMatcher for 'type __modf_result' -/// @see src/tint/builtins.def:100:6 +/// @see src/tint/intrinsics.def:100:6 class ModfResult : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:101:42 +/// @see src/tint/intrinsics.def:101:42 class ModfResultVec : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:102:6 +/// @see src/tint/intrinsics.def:102:6 class FrexpResult : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:103:43 +/// @see src/tint/intrinsics.def:103:43 class FrexpResultVec : public TypeMatcher { public: /// Checks whether the given type matches the matcher rules. @@ -1158,7 +1158,7 @@ std::string FrexpResultVec::String(MatchState& state) const { } /// TypeMatcher for 'match fiu32' -/// @see src/tint/builtins.def:111:7 +/// @see src/tint/intrinsics.def:111:7 class Fiu32 : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:112:7 +/// @see src/tint/intrinsics.def:112:7 class Iu32 : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:113:7 +/// @see src/tint/intrinsics.def:113:7 class Scalar : public TypeMatcher { public: /// 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' -/// @see src/tint/builtins.def:124:7 +/// @see src/tint/intrinsics.def:124:7 class F32TexelFormat : public NumberMatcher { public: /// 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' -/// @see src/tint/builtins.def:126:7 +/// @see src/tint/intrinsics.def:126:7 class I32TexelFormat : public NumberMatcher { public: /// 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' -/// @see src/tint/builtins.def:128:7 +/// @see src/tint/intrinsics.def:128:7 class U32TexelFormat : public NumberMatcher { public: /// 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' -/// @see src/tint/builtins.def:131:7 +/// @see src/tint/intrinsics.def:131:7 class WriteOnly : public NumberMatcher { public: /// 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' -/// @see src/tint/builtins.def:133:7 +/// @see src/tint/intrinsics.def:133:7 class FunctionPrivateWorkgroup : public NumberMatcher { public: /// 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' -/// @see src/tint/builtins.def:134:7 +/// @see src/tint/intrinsics.def:134:7 class WorkgroupOrStorage : public NumberMatcher { public: /// Checks whether the given number matches the enum matcher rules. @@ -8814,7 +8814,7 @@ constexpr OverloadInfo kOverloads[] = { }, }; -constexpr BuiltinInfo kBuiltins[] = { +constexpr IntrinsicInfo kBuiltins[] = { { /* [0] */ /* fn abs(T) -> T */ diff --git a/src/tint/resolver/intrinsic_table.inl.tmpl b/src/tint/resolver/intrinsic_table.inl.tmpl index 931ae247ae..b39ad5dc86 100644 --- a/src/tint/resolver/intrinsic_table.inl.tmpl +++ b/src/tint/resolver/intrinsic_table.inl.tmpl @@ -23,7 +23,7 @@ See: {{ end -}} {{- end -}} -{{- with BuiltinTable -}} +{{- with IntrinsicTable -}} {{- template "Matchers" . }} constexpr MatcherIndex kMatcherIndices[] = { @@ -106,15 +106,15 @@ constexpr OverloadInfo kOverloads[] = { {{- end }} }; -constexpr BuiltinInfo kBuiltins[] = { -{{- range $i, $f := .Functions }} +constexpr IntrinsicInfo kBuiltins[] = { +{{- range $i, $b := .Builtins }} { /* [{{$i}}] */ -{{- range $f.OverloadDescriptions }} +{{- range $b.OverloadDescriptions }} /* {{.}} */ {{- end }} - /* num overloads */ {{$f.NumOverloads}}, - /* overloads */ &kOverloads[{{$f.OverloadsOffset}}], + /* num overloads */ {{$b.NumOverloads}}, + /* overloads */ &kOverloads[{{$b.OverloadsOffset}}], }, {{- end }} }; diff --git a/src/tint/sem/builtin_type.cc.tmpl b/src/tint/sem/builtin_type.cc.tmpl index 63c20830c6..4e830dac95 100644 --- a/src/tint/sem/builtin_type.cc.tmpl +++ b/src/tint/sem/builtin_type.cc.tmpl @@ -15,7 +15,7 @@ See: namespace tint::sem { BuiltinType ParseBuiltinType(const std::string& name) { -{{- range .Sem.Functions }} +{{- range .Sem.Builtins }} if (name == "{{.Name}}") { return BuiltinType::k{{Title .Name}}; } @@ -27,7 +27,7 @@ const char* str(BuiltinType i) { switch (i) { case BuiltinType::kNone: return ""; -{{- range .Sem.Functions }} +{{- range .Sem.Builtins }} case BuiltinType::k{{Title .Name}}: return "{{.Name}}"; {{- end }} diff --git a/src/tint/sem/builtin_type.h.tmpl b/src/tint/sem/builtin_type.h.tmpl index d4e1cc77d3..258ac87f72 100644 --- a/src/tint/sem/builtin_type.h.tmpl +++ b/src/tint/sem/builtin_type.h.tmpl @@ -19,7 +19,7 @@ namespace tint::sem { /// Enumerator of all builtin functions enum class BuiltinType { kNone = -1, -{{- range .Sem.Functions }} +{{- range .Sem.Builtins }} k{{Title .Name}}, {{- end }} }; diff --git a/test/tint/builtins/builtins.wgsl.tmpl b/test/tint/builtins/builtins.wgsl.tmpl index 0edd48ebd8..ecc76a5493 100644 --- a/test/tint/builtins/builtins.wgsl.tmpl +++ b/test/tint/builtins/builtins.wgsl.tmpl @@ -9,15 +9,15 @@ See: -------------------------------------------------------------------------------- */ -}} -{{- /* For each permutation of each overload of each function... */ -}} -{{- range .Sem.Functions -}} +{{- /* For each permutation of each overload of each builtin... */ -}} +{{- range .Sem.Builtins -}} {{- /* TODO(crbug.com/tint/1483): Remove the bodge below after smoothStep is removed from builtins.def */}} {{- if not (eq .Name "smoothStep") }} {{- range .Overloads -}} {{- range Permute . -}} {{- /* Generate a ./gen//.wgsl file using 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" . -}} {{- WriteFile $file $content -}} {{- end }} @@ -30,8 +30,8 @@ See: {{- define "Permutation" -}} {{- /* Emits the body of the intrinsic permuation .wgsl file */ -}} {{- /* ------------------------------------------------------------------ */ -}} -{{- $function := .Function.Name -}} -{{- $permutation := printf "%v_%v" $function .Hash -}} +{{- $builtin := .Intrinsic.Name -}} +{{- $permutation := printf "%v_%v" $builtin .Hash -}} {{- $args := Map -}} {{- /* Generate RW storage buffer parameters */ -}} @@ -125,7 +125,7 @@ fn {{$permutation}}() { {{- if .ReturnType -}} var res{{if IsDeclarable .ReturnType}}: {{template "Type" .ReturnType}}{{end}} = {{/* preserve space after = */ -}} {{- end -}} - {{$function}}( + {{$builtin}}( {{- range $i, $p := .Parameters -}} {{- if $i -}}, {{end}}{{$args.Get $i -}} {{- end -}} diff --git a/tools/src/cmd/intrinsic-gen/ast/ast.go b/tools/src/cmd/intrinsic-gen/ast/ast.go index 92dcaa7800..17454a0dd8 100644 --- a/tools/src/cmd/intrinsic-gen/ast/ast.go +++ b/tools/src/cmd/intrinsic-gen/ast/ast.go @@ -28,7 +28,8 @@ type AST struct { Enums []EnumDecl Types []TypeDecl Matchers []MatcherDecl - Functions []FunctionDecl + Builtins []IntrinsicDecl + Operators []IntrinsicDecl } func (a AST) String() string { @@ -45,8 +46,12 @@ func (a AST) String() string { fmt.Fprintf(&sb, "%v", m) fmt.Fprintln(&sb) } - for _, f := range a.Functions { - fmt.Fprintf(&sb, "%v", f) + for _, b := range a.Builtins { + fmt.Fprintf(&sb, "%v", b) + fmt.Fprintln(&sb) + } + for _, o := range a.Operators { + fmt.Fprintf(&sb, "%v", o) fmt.Fprintln(&sb) } return sb.String() @@ -98,9 +103,18 @@ func (m MatcherDecl) Format(w fmt.State, verb rune) { m.Options.Format(w, verb) } -// FunctionDecl describes a function declaration -type FunctionDecl struct { +// IntrinsicKind is either a Builtin or Operator +type IntrinsicKind string + +const ( + Builtin IntrinsicKind = "builtin" + Operator IntrinsicKind = "operator" +) + +// IntrinsicDecl describes a builtin or operator declaration +type IntrinsicDecl struct { Source tok.Source + Kind IntrinsicKind Name string Decorations Decorations TemplateParams TemplateParams @@ -109,13 +123,19 @@ type FunctionDecl struct { } // Format implements the fmt.Formatter interface -func (f FunctionDecl) Format(w fmt.State, verb rune) { - fmt.Fprintf(w, "fn %v", f.Name) - f.TemplateParams.Format(w, verb) - f.Parameters.Format(w, verb) - if f.ReturnType != nil { +func (i IntrinsicDecl) Format(w fmt.State, verb rune) { + switch i.Kind { + case Builtin: + fmt.Fprintf(w, "fn ") + 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, " -> ") - f.ReturnType.Format(w, verb) + i.ReturnType.Format(w, verb) } } diff --git a/tools/src/cmd/intrinsic-gen/gen/builtin_table.go b/tools/src/cmd/intrinsic-gen/gen/builtin_table.go index b3bfa16743..94c8a5cd90 100644 --- a/tools/src/cmd/intrinsic-gen/gen/builtin_table.go +++ b/tools/src/cmd/intrinsic-gen/gen/builtin_table.go @@ -22,8 +22,8 @@ import ( "dawn.googlesource.com/dawn/tools/src/lut" ) -// BuiltinTable holds data specific to the intrinsic_table.inl.tmpl template -type BuiltinTable struct { +// IntrinsicTable holds data specific to the intrinsic_table.inl.tmpl template +type IntrinsicTable struct { // The semantic info Sem *sem.Sem @@ -42,7 +42,8 @@ type BuiltinTable struct { OpenNumbers []OpenNumber // kOpenNumbers table content Parameters []Parameter // kParameters 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 @@ -68,9 +69,9 @@ type Parameter struct { // The parameter usage (parameter name) 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 - // into BuiltinTable::TMatchers and / or BuiltinTable::NMatchers. + // into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers. // These indices are consumed by the matchers themselves. // The first index is always a TypeMatcher. MatcherIndicesOffset *int @@ -84,15 +85,15 @@ type Overload struct { NumOpenTypes int // Total number of open numbers for the overload NumOpenNumbers int - // Index to the first open type in BuiltinTable.OpenTypes + // Index to the first open type in IntrinsicTable.OpenTypes OpenTypesOffset *int - // Index to the first open number in BuiltinTable.OpenNumbers + // Index to the first open number in IntrinsicTable.OpenNumbers OpenNumbersOffset *int - // Index to the first parameter in BuiltinTable.Parameters + // Index to the first parameter in IntrinsicTable.Parameters 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 - // into BuiltinTable::TMatchers and / or BuiltinTable::NMatchers. + // into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers. // These indices are consumed by the matchers themselves. // The first index is always a TypeMatcher. ReturnMatcherIndicesOffset *int @@ -102,17 +103,18 @@ type Overload struct { IsDeprecated bool } -// Function is used to create the C++ IntrinsicInfo structure -type Function struct { +// Intrinsic is used to create the C++ IntrinsicInfo structure +type Intrinsic struct { + Name string OverloadDescriptions []string NumOverloads int OverloadsOffset *int } -// Helper for building the BuiltinTable -type BuiltinTableBuilder struct { +// Helper for building the IntrinsicTable +type IntrinsicTableBuilder struct { // The output of the builder - BuiltinTable + IntrinsicTable // Lookup tables. // These are packed (compressed) once all the entries have been added. @@ -127,7 +129,7 @@ type BuiltinTableBuilder struct { // Helper for building a single overload type overloadBuilder struct { - *BuiltinTableBuilder + *IntrinsicTableBuilder // Maps TemplateParam to index in openTypes openTypeIndex map[sem.TemplateParam]int // Maps TemplateParam to index in openNumbers @@ -138,9 +140,9 @@ type overloadBuilder struct { openNumbers []OpenNumber // All parameters declared by the overload 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 - // into BuiltinTable::TMatchers and / or BuiltinTable::NMatchers. + // into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers. // These indices are consumed by the matchers themselves. // The first index is always a TypeMatcher. returnTypeMatcherIndicesOffset *int @@ -148,7 +150,7 @@ type overloadBuilder struct { // layoutMatchers assigns each of the TMatchers and NMatchers a unique index // 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 b.TMatchers = make([]sem.Named, s.MaxOpenTypes) for _, m := range s.Types { @@ -169,11 +171,11 @@ func (b *BuiltinTableBuilder) layoutMatchers(s *sem.Sem) { } // 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{ - BuiltinTableBuilder: b, - openTypeIndex: map[sem.TemplateParam]int{}, - openNumberIndex: map[sem.TemplateParam]int{}, + IntrinsicTableBuilder: b, + openTypeIndex: map[sem.TemplateParam]int{}, + openNumberIndex: map[sem.TemplateParam]int{}, } if err := ob.buildOpenTypes(o); err != nil { @@ -279,7 +281,7 @@ func (b *overloadBuilder) buildReturnType(o *sem.Overload) error { } // 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) { switch n := n.(type) { case *sem.Type, *sem.TypeMatcher: @@ -342,10 +344,10 @@ func (b *overloadBuilder) collectMatcherIndices(fqn sem.FullyQualifiedName) ([]i return out, nil } -// buildBuiltinTable builds the BuiltinTable from the semantic info -func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) { - b := BuiltinTableBuilder{ - BuiltinTable: BuiltinTable{ +// buildIntrinsicTable builds the IntrinsicTable from the semantic info +func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) { + b := IntrinsicTableBuilder{ + IntrinsicTable: IntrinsicTable{ Sem: s, TMatcherIndex: map[sem.Named]int{}, NMatcherIndex: map[sem.Named]int{}, @@ -359,22 +361,34 @@ func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) { b.layoutMatchers(s) - for _, f := range s.Functions { - overloads := make([]Overload, len(f.Overloads)) - overloadDescriptions := make([]string, len(f.Overloads)) - for i, o := range f.Overloads { - overloadDescriptions[i] = fmt.Sprint(o.Decl) - var err error - if overloads[i], err = b.buildOverload(o); err != nil { - return nil, err + buildIntrinsics := func(in []*sem.Intrinsic) ([]Intrinsic, error) { + out := make([]Intrinsic, len(in)) + for i, f := range in { + overloads := make([]Overload, len(f.Overloads)) + overloadDescriptions := make([]string, len(f.Overloads)) + for i, o := range f.Overloads { + overloadDescriptions[i] = fmt.Sprint(o.Decl) + var err error + if overloads[i], err = b.buildOverload(o); err != nil { + return nil, err + } + } + out[i] = Intrinsic{ + Name: f.Name, + OverloadDescriptions: overloadDescriptions, + NumOverloads: len(overloads), + OverloadsOffset: b.lut.overloads.Add(overloads), } } + return out, nil + } - b.Functions = append(b.Functions, Function{ - OverloadDescriptions: overloadDescriptions, - NumOverloads: len(overloads), - OverloadsOffset: b.lut.overloads.Add(overloads), - }) + 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() @@ -383,5 +397,5 @@ func buildBuiltinTable(s *sem.Sem) (*BuiltinTable, error) { b.lut.parameters.Compact() b.lut.overloads.Compact() - return &b.BuiltinTable, nil + return &b.IntrinsicTable, nil } diff --git a/tools/src/cmd/intrinsic-gen/gen/generate.go b/tools/src/cmd/intrinsic-gen/gen/generate.go index 246fb7b853..5d83b19235 100644 --- a/tools/src/cmd/intrinsic-gen/gen/generate.go +++ b/tools/src/cmd/intrinsic-gen/gen/generate.go @@ -29,8 +29,8 @@ type generator struct { s *sem.Sem t *template.Template cached struct { - builtinTable *BuiltinTable // lazily built by builtinTable() - permuter *Permuter // lazily built by permute() + intrinsicTable *IntrinsicTable // lazily built by intrinsicTable() + permuter *Permuter // lazily built by permute() } } @@ -73,7 +73,7 @@ func (g *generator) generate(tmpl string, w io.Writer, writeFile WriteFile) erro "IsDeclarable": isDeclarable, "IsFirstIn": isFirstIn, "IsLastIn": isLastIn, - "BuiltinTable": g.builtinTable, + "IntrinsicTable": g.intrinsicTable, "Permute": g.permute, "Eval": g.eval, "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 } -// builtinTable lazily calls and returns the result of buildBuiltinTable(), +// intrinsicTable lazily calls and returns the result of buildIntrinsicTable(), // caching the result for repeated calls. -func (g *generator) builtinTable() (*BuiltinTable, error) { - if g.cached.builtinTable == nil { +func (g *generator) intrinsicTable() (*IntrinsicTable, error) { + if g.cached.intrinsicTable == nil { var err error - g.cached.builtinTable, err = buildBuiltinTable(g.s) + g.cached.intrinsicTable, err = buildIntrinsicTable(g.s) if err != nil { return nil, err } } - return g.cached.builtinTable, nil + return g.cached.intrinsicTable, nil } // permute lazily calls buildPermuter(), caching the result for repeated diff --git a/tools/src/cmd/intrinsic-gen/gen/permutate.go b/tools/src/cmd/intrinsic-gen/gen/permutate.go index 934e966161..41e6472fa4 100644 --- a/tools/src/cmd/intrinsic-gen/gen/permutate.go +++ b/tools/src/cmd/intrinsic-gen/gen/permutate.go @@ -74,7 +74,7 @@ func (p *Permuter) Permute(overload *sem.Overload) ([]Permutation, error) { permutate := func() error { o := sem.Overload{ Decl: overload.Decl, - Function: overload.Function, + Intrinsic: overload.Intrinsic, CanBeUsedInStage: overload.CanBeUsedInStage, } for i, p := range overload.Parameters { diff --git a/tools/src/cmd/intrinsic-gen/lexer/lexer.go b/tools/src/cmd/intrinsic-gen/lexer/lexer.go index 749ab0d374..35cd73e181 100644 --- a/tools/src/cmd/intrinsic-gen/lexer/lexer.go +++ b/tools/src/cmd/intrinsic-gen/lexer/lexer.go @@ -52,10 +52,6 @@ func (l *lexer) lex() error { l.next() case '\n': l.next() - case '<': - l.tok(1, tok.Lt) - case '>': - l.tok(1, tok.Gt) case '(': l.tok(1, tok.Lparen) case ')': @@ -68,8 +64,14 @@ func (l *lexer) lex() error { l.tok(1, tok.Colon) case ',': l.tok(1, tok.Comma) - case '|': - l.tok(1, tok.Or) + case '*': + l.tok(1, tok.Star) + case '+': + l.tok(1, tok.Plus) + case '%': + l.tok(1, tok.Modulo) + case '^': + l.tok(1, tok.Xor) case '"': start := l.loc l.next() // Skip opening quote @@ -81,13 +83,16 @@ func (l *lexer) lex() error { l.next() // Skip closing quote default: switch { - case l.peek(1) == '/': + case l.peek(0) == '/' && l.peek(1) == '/': l.skip(l.count(toFirst('\n'))) l.next() // Consume newline + case l.match("/", tok.Divide): case l.match("[[", tok.Ldeco): case l.match("]]", tok.Rdeco): case l.match("->", tok.Arrow): + case l.match("-", tok.Minus): case l.match("fn", tok.Function): + case l.match("op", tok.Operator): case l.match("enum", tok.Enum): case l.match("type", tok.Type): case l.match("match", tok.Match): @@ -95,6 +100,19 @@ func (l *lexer) lex() error { l.tok(l.count(alphaNumericOrUnderscore), tok.Identifier) case unicode.IsNumber(l.peek(0)): 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: return fmt.Errorf("%v: unexpected '%v'", l.loc, string(l.runes[0])) } diff --git a/tools/src/cmd/intrinsic-gen/lexer/lexer_test.go b/tools/src/cmd/intrinsic-gen/lexer/lexer_test.go index 51130e5d1f..bfc8df8d7b 100644 --- a/tools/src/cmd/intrinsic-gen/lexer/lexer_test.go +++ b/tools/src/cmd/intrinsic-gen/lexer/lexer_test.go @@ -52,6 +52,9 @@ func TestLexTokens(t *testing.T) { {"fn", tok.Token{Kind: tok.Function, Runes: []rune("fn"), Source: tok.Source{ 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{ 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{ 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{ 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{ 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{ S: loc(1, 1, 0), E: loc(1, 3, 2), }}}, @@ -134,10 +179,14 @@ func TestErrors(t *testing.T) { for _, test := range []test{ {" \"abc", "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") - if gotErr := err.Error(); test.expect != gotErr { + gotErr := "" + if err != nil { + gotErr = err.Error() + } + if test.expect != gotErr { t.Errorf(`Lex() returned error "%+v", expected error "%+v"`, gotErr, test.expect) } if got != nil { diff --git a/tools/src/cmd/intrinsic-gen/parser/parser.go b/tools/src/cmd/intrinsic-gen/parser/parser.go index cd775cca4b..48c8a943f7 100644 --- a/tools/src/cmd/intrinsic-gen/parser/parser.go +++ b/tools/src/cmd/intrinsic-gen/parser/parser.go @@ -66,7 +66,10 @@ func (p *parser) parse() (*ast.AST, error) { out.Types = append(out.Types, p.typeDecl(decorations)) decorations = nil 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 default: p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind) @@ -153,11 +156,12 @@ func (p *parser) decorations() ast.Decorations { 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") name := p.expect(tok.Identifier, "function name") - f := ast.FunctionDecl{ + f := ast.IntrinsicDecl{ Source: name.Source, + Kind: ast.Builtin, Decorations: decos, Name: string(name.Runes), } @@ -172,6 +176,25 @@ func (p *parser) functionDecl(decos ast.Decorations) ast.FunctionDecl { 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 { l := ast.Parameters{} 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) } -// 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 { if p.err != nil || len(p.tokens) == 0 { return nil @@ -296,6 +305,18 @@ func (p *parser) match(kind tok.Kind) *tok.Token { 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 { t := p.peek(i) if t == nil { diff --git a/tools/src/cmd/intrinsic-gen/parser/parser_test.go b/tools/src/cmd/intrinsic-gen/parser/parser_test.go index ae78113e70..9ea76c3117 100644 --- a/tools/src/cmd/intrinsic-gen/parser/parser_test.go +++ b/tools/src/cmd/intrinsic-gen/parser/parser_test.go @@ -19,170 +19,369 @@ import ( "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/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) { type test struct { - src string - expect ast.AST + location string + src string + expect ast.AST } for _, test := range []test{ - {"enum E {}", ast.AST{ - Enums: []ast.EnumDecl{{Name: "E"}}, - }}, - {"enum E { A [[deco]] B C }", ast.AST{ - Enums: []ast.EnumDecl{{ - Name: "E", - Entries: []ast.EnumEntry{ - {Name: "A"}, - { - Decorations: ast.Decorations{{Name: "deco"}}, - Name: "B", - }, - {Name: "C"}, - }, - }}, - }}, - {"type T", ast.AST{ - Types: []ast.TypeDecl{{Name: "T"}}, - }}, - {"type T", ast.AST{ - Types: []ast.TypeDecl{{ - Name: "T", - TemplateParams: ast.TemplateParams{ - {Name: "A"}, - {Name: "B"}, - {Name: "C"}, - }, - }}, - }}, - {"[[deco]] type T", ast.AST{ - Types: []ast.TypeDecl{{ - Decorations: ast.Decorations{ - {Name: "deco"}, - }, - Name: "T", - }}, - }}, - {`[[deco("a", "b")]] type T`, ast.AST{ - Types: []ast.TypeDecl{{ - Decorations: ast.Decorations{ - {Name: "deco", Values: []string{"a", "b"}}, - }, - Name: "T", - }}, - }}, - {"match M : A", ast.AST{ - Matchers: []ast.MatcherDecl{{ - Name: "M", - Options: ast.MatcherOptions{ - ast.TemplatedName{Name: "A"}, - }, - }}, - }}, - {"match M : A | B", ast.AST{ - Matchers: []ast.MatcherDecl{{ - Name: "M", - Options: ast.MatcherOptions{ - ast.TemplatedName{Name: "A"}, - ast.TemplatedName{Name: "B"}, - }, - }}, - }}, - {"fn F()", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - }}, - }}, - {"[[deco]] fn F()", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - Decorations: ast.Decorations{ - {Name: "deco"}, - }, - }}, - }}, - {"fn F(a)", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - Parameters: ast.Parameters{ - {Type: ast.TemplatedName{Name: "a"}}, - }, - }}, - }}, - {"fn F(a: T)", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - Parameters: ast.Parameters{ - {Name: "a", Type: ast.TemplatedName{Name: "T"}}, - }, - }}, - }}, - {"fn F(a, b)", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - Parameters: ast.Parameters{ - {Type: ast.TemplatedName{Name: "a"}}, - {Type: ast.TemplatedName{Name: "b"}}, - }, - }}, - }}, - {"fn F>()", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - TemplateParams: ast.TemplateParams{ - { - Name: "A", Type: ast.TemplatedName{ + { + utils.ThisLine(), + "enum E {}", + ast.AST{ + Enums: []ast.EnumDecl{{Name: "E"}}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "enum E { A [[deco]] B C }", + ast.AST{ + Enums: []ast.EnumDecl{{ + Name: "E", + Entries: []ast.EnumEntry{ + {Name: "A"}, + { + Decorations: ast.Decorations{{ + Name: "deco", + Values: []string{}, + }}, Name: "B", - TemplateArgs: ast.TemplatedNames{ - {Name: "C"}, + }, + {Name: "C"}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "type T", + ast.AST{ + Types: []ast.TypeDecl{{Name: "T"}}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "type T", + ast.AST{ + Types: []ast.TypeDecl{{ + Name: "T", + TemplateParams: ast.TemplateParams{ + {Name: "A"}, + {Name: "B"}, + {Name: "C"}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "[[deco]] type T", + ast.AST{ + Types: []ast.TypeDecl{{ + Decorations: ast.Decorations{ + {Name: "deco", Values: []string{}}, + }, + Name: "T", + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + `[[deco("a", "b")]] type T`, ast.AST{ + Types: []ast.TypeDecl{{ + Decorations: ast.Decorations{ + {Name: "deco", Values: []string{"a", "b"}}, + }, + Name: "T", + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "match M : A", + ast.AST{ + Matchers: []ast.MatcherDecl{{ + Name: "M", + Options: ast.MatcherOptions{ + ast.TemplatedName{Name: "A"}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "match M : A | B", + ast.AST{ + Matchers: []ast.MatcherDecl{{ + Name: "M", + Options: ast.MatcherOptions{ + ast.TemplatedName{Name: "A"}, + ast.TemplatedName{Name: "B"}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F()", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + Parameters: ast.Parameters{}, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "[[deco]] fn F()", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + Decorations: ast.Decorations{ + {Name: "deco", Values: []string{}}, + }, + Parameters: ast.Parameters{}, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F(a)", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + Parameters: ast.Parameters{ + {Type: ast.TemplatedName{Name: "a"}}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F(a: T)", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + Parameters: ast.Parameters{ + {Name: "a", Type: ast.TemplatedName{Name: "T"}}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F(a, b)", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + Parameters: ast.Parameters{ + {Type: ast.TemplatedName{Name: "a"}}, + {Type: ast.TemplatedName{Name: "b"}}, + }, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F >()", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + TemplateParams: ast.TemplateParams{ + { + Name: "A", Type: ast.TemplatedName{ + Name: "B", + TemplateArgs: ast.TemplatedNames{ + {Name: "C"}, + }, }, }, }, - }, - }}, - }}, - {"fn F(a: X, b: Y)", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - TemplateParams: ast.TemplateParams{ - {Name: "T"}, - }, - Parameters: ast.Parameters{ - {Name: "a", Type: ast.TemplatedName{Name: "X"}}, - {Name: "b", Type: ast.TemplatedName{ - Name: "Y", + Parameters: ast.Parameters{}, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F(a: X, b: Y)", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + 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(), + "fn F() -> X", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + ReturnType: &ast.TemplatedName{Name: "X"}, + Parameters: ast.Parameters{}, + }}, + }, + }, { /////////////////////////////////////////////////////////////////// + utils.ThisLine(), + "fn F() -> X", + ast.AST{ + Builtins: []ast.IntrinsicDecl{{ + Kind: ast.Builtin, + Name: "F", + ReturnType: &ast.TemplatedName{ + Name: "X", 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 >()", + 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(a: X, b: Y)", + 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", + ast.AST{ + Operators: []ast.IntrinsicDecl{{ + Kind: ast.Operator, + Name: "F", + ReturnType: &ast.TemplatedName{ + Name: "X", + TemplateArgs: []ast.TemplatedName{{Name: "T"}}, + }, + Parameters: ast.Parameters{}, + }}, }}, - }}, - {"fn F() -> X", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - ReturnType: &ast.TemplatedName{Name: "X"}, - }}, - }}, - {"fn F() -> X", ast.AST{ - Functions: []ast.FunctionDecl{{ - Name: "F", - ReturnType: &ast.TemplatedName{ - Name: "X", - TemplateArgs: []ast.TemplatedName{{Name: "T"}}, - }, - }}, - }}, } { got, err := parser.Parse(test.src, "file.txt") 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 } - gotStr, expectStr := got.String(), test.expect.String() - if gotStr != expectStr { - t.Errorf("While parsing:\n%s\nGot:\n%s\nExpected:\n%s", test.src, gotStr, expectStr) + if diff := cmp.Diff(got, &test.expect, ignoreSource); diff != "" { + t.Errorf("\n%v\nWhile parsing:\n%s\n\n%s", + test.location, test.src, diff) } } } @@ -194,10 +393,22 @@ func TestErrors(t *testing.T) { } 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'"}, - {"[[abc", "expected ']]' for decoration list, but reached end of file"}, + { + "£", + "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'", + }, + { + "[[abc", + "expected ']]' for decoration list, but reached end of file", + }, } { got, err := parser.Parse(test.src, "test.txt") if gotErr := err.Error(); test.expect != gotErr { diff --git a/tools/src/cmd/intrinsic-gen/resolver/resolve.go b/tools/src/cmd/intrinsic-gen/resolver/resolve.go index f7f662adf2..3a09f38d1a 100644 --- a/tools/src/cmd/intrinsic-gen/resolver/resolve.go +++ b/tools/src/cmd/intrinsic-gen/resolver/resolve.go @@ -28,7 +28,8 @@ type resolver struct { s *sem.Sem globals scope - functions map[string]*sem.Function + builtins map[string]*sem.Intrinsic + operators map[string]*sem.Intrinsic enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher } @@ -38,7 +39,8 @@ func Resolve(a *ast.AST) (*sem.Sem, error) { a: a, s: sem.New(), globals: newScope(nil), - functions: map[string]*sem.Function{}, + builtins: map[string]*sem.Intrinsic{}, + operators: map[string]*sem.Intrinsic{}, enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{}, } // Declare and resolve all the enumerators @@ -59,9 +61,15 @@ func Resolve(a *ast.AST) (*sem.Sem, error) { return nil, err } } - // Declare and resolve the functions - for _, f := range a.Functions { - if err := r.function(f); err != nil { + // Declare and resolve the builtins + for _, f := range a.Builtins { + 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 } } @@ -220,18 +228,21 @@ func (r *resolver) matcher(a ast.MatcherDecl) error { return fmt.Errorf("'%v' cannot be used for matcher", a.Name) } -// function() resolves a function overload declaration. -// The the first overload for the function creates and appends the sem.Function -// to Sem.Functions. Subsequent overloads append their resolved overload to the -// sem.Function.Overloads list. -func (r *resolver) function(a ast.FunctionDecl) error { - // If this is the first overload of the function, create and register the - // semantic function. - f := r.functions[a.Name] - if f == nil { - f = &sem.Function{Name: a.Name} - r.functions[a.Name] = f - r.s.Functions = append(r.s.Functions, f) +// intrinsic() resolves a intrinsic overload declaration. +// The the first overload for the intrinsic creates and appends the sem.Intrinsic +// to Sem.Intrinsics. Subsequent overloads append their resolved overload to the +// sem.intrinsic.Overloads list. +func (r *resolver) intrinsic( + a ast.IntrinsicDecl, + intrinsicsByName map[string]*sem.Intrinsic, + semIntrinsics *[]*sem.Intrinsic) error { + // If this is the first overload of the intrinsic, create and register the + // semantic intrinsic. + intrinsic := intrinsicsByName[a.Name] + 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 @@ -246,7 +257,7 @@ func (r *resolver) function(a ast.FunctionDecl) error { // Construct the semantic overload overload := &sem.Overload{ Decl: a, - Function: f, + Intrinsic: intrinsic, Parameters: make([]sem.Parameter, len(a.Parameters)), TemplateParams: templateParams, } @@ -285,8 +296,8 @@ func (r *resolver) function(a ast.FunctionDecl) error { return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source) } - // Append the overload to the function - f.Overloads = append(f.Overloads, overload) + // Append the overload to the intrinsic + intrinsic.Overloads = append(intrinsic.Overloads, overload) // Sort the template parameters by resolved type. Append these to // 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) } + 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 for i, p := range a.Parameters { 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 -// overloads, calculating the list of unique parameter names +// builtin overloads, calculating the list of unique parameter names func (r *resolver) calculateUniqueParameterNames() []string { set := map[string]struct{}{"": {}} names := []string{} - for _, f := range r.s.Functions { + for _, f := range r.s.Builtins { for _, o := range f.Overloads { for _, p := range o.Parameters { if _, dup := set[p.Name]; !dup { diff --git a/tools/src/cmd/intrinsic-gen/resolver/resolver_test.go b/tools/src/cmd/intrinsic-gen/resolver/resolver_test.go index 1768dbf9f3..9f3aac07bb 100644 --- a/tools/src/cmd/intrinsic-gen/resolver/resolver_test.go +++ b/tools/src/cmd/intrinsic-gen/resolver/resolver_test.go @@ -139,7 +139,7 @@ fn f()`, ` type f32 type T -fn f(T>)`, +fn f(T< T >)`, success, }, { `enum E {A A}`, @@ -299,6 +299,70 @@ fn f(P)`, `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 +op << (T)`, + `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)`, + `file.txt:2:11 'T' template parameters do not accept template arguments`, + }, { + ` +type A +type B +op << (A)`, + `file.txt:3:10 cannot use type 'B' as template number`, + }, { + ` +type A +enum E { b } +op << (A)`, + `file.txt:3:10 cannot use enum entry 'E.b' as template type`, + }, { + ` +type T +type P +match m: T +op << (P)`, + `file.txt:4:10 cannot use type matcher 'm' as template number`, + }, { + ` +type P +enum E { b } +op << (P)`, + `file.txt:3:10 cannot use enum 'E' as template number`, + }, { + ` +type P +enum E { a b } +match m: a | b +op << (P)`, + `file.txt:4:10 cannot use enum matcher 'm' as template number`, + }, { + ` +type P +enum E { a b } +match m: a | b +op << (P)`, + `file.txt:4:16 cannot use template enum 'E' as template number`, + }, { + ` enum E { a } type T`, `file.txt:2:8 invalid template parameter type 'a'`, diff --git a/tools/src/cmd/intrinsic-gen/sem/sem.go b/tools/src/cmd/intrinsic-gen/sem/sem.go index 3d50bc28eb..9a0f973ccb 100644 --- a/tools/src/cmd/intrinsic-gen/sem/sem.go +++ b/tools/src/cmd/intrinsic-gen/sem/sem.go @@ -26,7 +26,8 @@ type Sem struct { Types []*Type TypeMatchers []*TypeMatcher EnumMatchers []*EnumMatcher - Functions []*Function + Builtins []*Intrinsic + Operators []*Intrinsic // Maximum number of open-types used across all builtins MaxOpenTypes int // Maximum number of open-numbers used across all builtins @@ -42,7 +43,8 @@ func New() *Sem { Types: []*Type{}, TypeMatchers: []*TypeMatcher{}, EnumMatchers: []*EnumMatcher{}, - Functions: []*Function{}, + Builtins: []*Intrinsic{}, + Operators: []*Intrinsic{}, } } @@ -121,16 +123,16 @@ type TemplateNumberParam struct { Name string } -// Function describes the overloads of a builtin function -type Function struct { +// Intrinsic describes the overloads of a builtin or operator +type Intrinsic struct { Name string Overloads []*Overload } -// Overload describes a single overload of a function +// Overload describes a single overload of a builtin or operator type Overload struct { - Decl ast.FunctionDecl - Function *Function + Decl ast.IntrinsicDecl + Intrinsic *Intrinsic TemplateParams []TemplateParam OpenTypes []*TemplateTypeParam OpenNumbers []TemplateParam @@ -164,7 +166,13 @@ func (u StageUses) List() []string { // Format implements the fmt.Formatter interface 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 { fmt.Fprintf(w, "<") for i, t := range o.TemplateParams { diff --git a/tools/src/cmd/intrinsic-gen/tok/tok.go b/tools/src/cmd/intrinsic-gen/tok/tok.go index c15a2359b9..d9e25ad655 100644 --- a/tools/src/cmd/intrinsic-gen/tok/tok.go +++ b/tools/src/cmd/intrinsic-gen/tok/tok.go @@ -29,12 +29,17 @@ const ( String Kind = "string" Match Kind = "match" Function Kind = "fn" + Operator Kind = "op" Type Kind = "type" Enum Kind = "enum" Colon Kind = ":" Comma Kind = "," + Shl Kind = "<<" + Shr Kind = ">>" Lt Kind = "<" + Le Kind = "<=" Gt Kind = ">" + Ge Kind = ">=" Lbrace Kind = "{" Rbrace Kind = "}" Ldeco Kind = "[[" @@ -43,6 +48,18 @@ const ( Rparen Kind = ")" Or 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