blob: 5c01e18f219d720544135a70a0a6762ea1be949b [file] [log] [blame]
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package resolver
import (
"sort"
"android.googlesource.com/platform/tools/gpu/api/ast"
"android.googlesource.com/platform/tools/gpu/api/semantic"
)
func api(ctx *context, out *semantic.API) {
in := out.AST
macros := []*macroStub{}
ctx.with(semantic.VoidType, func() {
// Build and register the high level semantic objects
out.Enums = make([]*semantic.Enum, len(in.Enums))
for i, e := range in.Enums {
out.Enums[i] = &semantic.Enum{AST: e, Name: e.Name.Value}
ctx.addType(out.Enums[i])
}
out.Classes = make([]*semantic.Class, len(in.Classes))
for i, c := range in.Classes {
out.Classes[i] = &semantic.Class{AST: c, Name: c.Name.Value, Members: semantic.Members{}}
ctx.addType(out.Classes[i])
}
out.Pseudonyms = make([]*semantic.Pseudonym, len(in.Pseudonyms))
for i, p := range in.Pseudonyms {
out.Pseudonyms[i] = &semantic.Pseudonym{AST: p, Name: p.Name.Value, Members: semantic.Members{}}
ctx.addType(out.Pseudonyms[i])
}
macros = make([]*macroStub, len(in.Macros))
for i, m := range in.Macros {
stub := &macroStub{}
macros[i] = stub
stub.function = &semantic.Function{AST: m, Name: m.Name.Value}
ctx.add(stub.function.Name, stub)
}
out.Externs = make([]*semantic.Function, len(in.Externs))
for i, e := range in.Externs {
out.Externs[i] = &semantic.Function{AST: e, Name: e.Name.Value}
out.Members[out.Externs[i].Name] = out.Externs[i]
}
for _, m := range in.Commands {
if !m.Parameters[0].This {
f := &semantic.Function{AST: m, Name: m.Name.Value}
out.Functions = append(out.Functions, f)
out.Members[f.Name] = f
}
}
out.Globals = make([]*semantic.Global, len(in.Fields))
for i, f := range in.Fields {
out.Globals[i] = &semantic.Global{AST: f, Name: f.Name.Value}
out.Members[out.Globals[i].Name] = out.Globals[i]
}
for name, member := range out.Members {
ctx.add(name, member)
}
// Add all the alias remaps
for _, a := range in.Aliases {
ctx.addType(&alias{AST: a, Name: a.Name.Value})
}
// Now resolve all the references
for _, e := range out.Enums {
enum(ctx, e)
}
for _, g := range out.Globals {
global(ctx, g)
}
for _, p := range out.Pseudonyms {
pseudonym(ctx, p)
}
for _, m := range macros {
functionSignature(ctx, m.function)
m.scope = ctx.scope
}
for _, e := range out.Externs {
functionSignature(ctx, e)
functionBody(ctx, nil, e)
}
for _, c := range out.Classes {
class(ctx, c)
}
for _, f := range out.Functions {
functionSignature(ctx, f)
functionBody(ctx, nil, f)
}
for _, m := range in.Commands {
if m.Parameters[0].This {
method(ctx, m)
}
}
})
sort.Sort(arraysByName(out.Arrays))
sort.Sort(mapsByName(out.Maps))
}
func annotations(ctx *context, in ast.Annotations) semantic.Annotations {
if len(in) == 0 {
return nil
}
out := semantic.Annotations{}
for _, a := range in {
entry := &semantic.Annotation{AST: a, Name: a.Name.Value}
for _, arg := range a.Arguments {
entry.Arguments = append(entry.Arguments, expression(ctx, arg))
}
out = append(out, entry)
}
return out
}
func global(ctx *context, out *semantic.Global) {
in := out.AST
out.Annotations = annotations(ctx, in.Annotations)
out.Type = type_(ctx, in.Type)
if in.Default != nil {
ctx.with(out.Type, func() {
out.Default = expression(ctx, in.Default)
})
dt := out.Default.ExpressionType()
if !assignable(out.Type, dt) {
ctx.errorf(in, "cannot assign %s to %s", typename(dt), typename(out.Type))
}
}
}
// alias is used as a temporary type holder during type resolution,
// it is not present in the final tree returned.
type alias struct {
AST *ast.Alias
Name string
To semantic.Type
}
func (t alias) Typename() string { return t.Name }
func (t alias) Member(name string) interface{} { return nil }
// arraysByName is used to sort the array list by name for generated code stability
type arraysByName []*semantic.Array
func (a arraysByName) Len() int { return len(a) }
func (a arraysByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a arraysByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
// mapsByName is used to sort the map list by name for generated code stability
type mapsByName []*semantic.Map
func (a mapsByName) Len() int { return len(a) }
func (a mapsByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a mapsByName) Less(i, j int) bool { return a[i].Name < a[j].Name }