1// Copyright 2021 The Tint Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package sem 16 17import ( 18 "fmt" 19 20 "dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/ast" 21) 22 23// Sem is the root of the semantic tree 24type Sem struct { 25 Enums []*Enum 26 Types []*Type 27 TypeMatchers []*TypeMatcher 28 EnumMatchers []*EnumMatcher 29 Functions []*Function 30 // Maximum number of open-types used across all intrinsics 31 MaxOpenTypes int 32 // Maximum number of open-numbers used across all intrinsics 33 MaxOpenNumbers int 34 // The alphabetically sorted list of unique parameter names 35 UniqueParameterNames []string 36} 37 38// New returns a new Sem 39func New() *Sem { 40 return &Sem{ 41 Enums: []*Enum{}, 42 Types: []*Type{}, 43 TypeMatchers: []*TypeMatcher{}, 44 EnumMatchers: []*EnumMatcher{}, 45 Functions: []*Function{}, 46 } 47} 48 49// Enum describes an enumerator 50type Enum struct { 51 Decl ast.EnumDecl 52 Name string 53 Entries []*EnumEntry 54} 55 56// FindEntry returns the enum entry with the given name 57func (e *Enum) FindEntry(name string) *EnumEntry { 58 for _, entry := range e.Entries { 59 if entry.Name == name { 60 return entry 61 } 62 } 63 return nil 64} 65 66// EnumEntry is an entry in an enumerator 67type EnumEntry struct { 68 Enum *Enum 69 Name string 70 IsInternal bool // True if this entry is not part of the WGSL grammar 71} 72 73// Format implements the fmt.Formatter interface 74func (e EnumEntry) Format(w fmt.State, verb rune) { 75 if e.IsInternal { 76 fmt.Fprint(w, "[[internal]] ") 77 } 78 fmt.Fprint(w, e.Name) 79} 80 81// Type declares a type 82type Type struct { 83 TemplateParams []TemplateParam 84 Decl ast.TypeDecl 85 Name string 86 DisplayName string 87} 88 89// TypeMatcher declares a type matcher 90type TypeMatcher struct { 91 TemplateParams []TemplateParam 92 Decl ast.MatcherDecl 93 Name string 94 Types []*Type 95} 96 97// EnumMatcher declares a enum matcher 98type EnumMatcher struct { 99 TemplateParams []TemplateParam 100 Decl ast.MatcherDecl 101 Name string 102 Enum *Enum 103 Options []*EnumEntry 104} 105 106// TemplateEnumParam is a template enum parameter 107type TemplateEnumParam struct { 108 Name string 109 Enum *Enum 110 Matcher *EnumMatcher // Optional 111} 112 113// TemplateTypeParam is a template type parameter 114type TemplateTypeParam struct { 115 Name string 116 Type ResolvableType 117} 118 119// TemplateNumberParam is a template type parameter 120type TemplateNumberParam struct { 121 Name string 122} 123 124// Function describes the overloads of an intrinsic function 125type Function struct { 126 Name string 127 Overloads []*Overload 128} 129 130// Overload describes a single overload of a function 131type Overload struct { 132 Decl ast.FunctionDecl 133 Function *Function 134 TemplateParams []TemplateParam 135 OpenTypes []*TemplateTypeParam 136 OpenNumbers []TemplateParam 137 ReturnType *FullyQualifiedName 138 Parameters []Parameter 139 CanBeUsedInStage StageUses 140 IsDeprecated bool // True if this overload is deprecated 141} 142 143// StageUses describes the stages an overload can be used in 144type StageUses struct { 145 Vertex bool 146 Fragment bool 147 Compute bool 148} 149 150// List returns the stage uses as a string list 151func (u StageUses) List() []string { 152 out := []string{} 153 if u.Vertex { 154 out = append(out, "vertex") 155 } 156 if u.Fragment { 157 out = append(out, "fragment") 158 } 159 if u.Compute { 160 out = append(out, "compute") 161 } 162 return out 163} 164 165// Format implements the fmt.Formatter interface 166func (o Overload) Format(w fmt.State, verb rune) { 167 fmt.Fprintf(w, "fn %v", o.Function.Name) 168 if len(o.TemplateParams) > 0 { 169 fmt.Fprintf(w, "<") 170 for i, t := range o.TemplateParams { 171 if i > 0 { 172 fmt.Fprint(w, ", ") 173 } 174 fmt.Fprintf(w, "%v", t) 175 } 176 fmt.Fprintf(w, ">") 177 } 178 fmt.Fprint(w, "(") 179 for i, p := range o.Parameters { 180 if i > 0 { 181 fmt.Fprint(w, ", ") 182 } 183 fmt.Fprintf(w, "%v", p) 184 } 185 fmt.Fprint(w, ")") 186 if o.ReturnType != nil { 187 fmt.Fprintf(w, " -> %v", o.ReturnType) 188 } 189} 190 191// Parameter describes a single parameter of a function overload 192type Parameter struct { 193 Name string 194 Type FullyQualifiedName 195} 196 197// Format implements the fmt.Formatter interface 198func (p Parameter) Format(w fmt.State, verb rune) { 199 if p.Name != "" { 200 fmt.Fprintf(w, "%v: ", p.Name) 201 } 202 fmt.Fprintf(w, "%v", p.Type) 203} 204 205// FullyQualifiedName is the usage of a Type, TypeMatcher or TemplateTypeParam 206type FullyQualifiedName struct { 207 Target Named 208 TemplateArguments []interface{} 209} 210 211// Format implements the fmt.Formatter interface 212func (f FullyQualifiedName) Format(w fmt.State, verb rune) { 213 fmt.Fprint(w, f.Target.GetName()) 214 if len(f.TemplateArguments) > 0 { 215 fmt.Fprintf(w, "<") 216 for i, t := range f.TemplateArguments { 217 if i > 0 { 218 fmt.Fprint(w, ", ") 219 } 220 fmt.Fprintf(w, "%v", t) 221 } 222 fmt.Fprintf(w, ">") 223 } 224} 225 226// TemplateParam is a TemplateEnumParam, TemplateTypeParam or TemplateNumberParam 227type TemplateParam interface { 228 Named 229 isTemplateParam() 230} 231 232func (*TemplateEnumParam) isTemplateParam() {} 233func (*TemplateTypeParam) isTemplateParam() {} 234func (*TemplateNumberParam) isTemplateParam() {} 235 236// ResolvableType is a Type, TypeMatcher or TemplateTypeParam 237type ResolvableType interface { 238 Named 239 isResolvableType() 240} 241 242func (*Type) isResolvableType() {} 243func (*TypeMatcher) isResolvableType() {} 244func (*TemplateTypeParam) isResolvableType() {} 245 246// Named is something that can be looked up by name 247type Named interface { 248 isNamed() 249 GetName() string 250} 251 252func (*Enum) isNamed() {} 253func (*EnumEntry) isNamed() {} 254func (*Type) isNamed() {} 255func (*TypeMatcher) isNamed() {} 256func (*EnumMatcher) isNamed() {} 257func (*TemplateTypeParam) isNamed() {} 258func (*TemplateEnumParam) isNamed() {} 259func (*TemplateNumberParam) isNamed() {} 260 261// GetName returns the name of the Enum 262func (e *Enum) GetName() string { return e.Name } 263 264// GetName returns the name of the EnumEntry 265func (e *EnumEntry) GetName() string { return e.Name } 266 267// GetName returns the name of the Type 268func (t *Type) GetName() string { return t.Name } 269 270// GetName returns the name of the TypeMatcher 271func (t *TypeMatcher) GetName() string { return t.Name } 272 273// GetName returns the name of the EnumMatcher 274func (e *EnumMatcher) GetName() string { return e.Name } 275 276// GetName returns the name of the TemplateTypeParam 277func (t *TemplateTypeParam) GetName() string { return t.Name } 278 279// GetName returns the name of the TemplateEnumParam 280func (t *TemplateEnumParam) GetName() string { return t.Name } 281 282// GetName returns the name of the TemplateNumberParam 283func (t *TemplateNumberParam) GetName() string { return t.Name } 284