blob: bf7c082f802b8329d2332e3de88e2a75f88df177 [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 (
"bytes"
"android.googlesource.com/platform/tools/gpu/api/ast"
"android.googlesource.com/platform/tools/gpu/api/semantic"
)
type macroStub struct {
scope *scope
function *semantic.Function
}
func (m *macroStub) ExpressionType() semantic.Type { return m.function.Signature }
func functionSignature(ctx *context, out *semantic.Function) {
in := out.AST
args := make([]semantic.Type, 0, len(in.Parameters)-1)
out.Outputs = make([]*semantic.Parameter, 0, len(in.Parameters))
out.FullParameters = make([]*semantic.Parameter, 0, len(in.Parameters))
for i, inp := range in.Parameters {
outp := parameter(ctx, out, inp)
if inp.This {
if i == 0 {
out.This = outp
} else {
ctx.errorf(inp, "this only allowed on arg 0")
}
}
if i < len(in.Parameters)-1 {
if isVoid(outp.Type) {
ctx.errorf(in, "void typed parameter %s on function %s", outp.Name, out.Name)
}
if !inp.This {
args = append(args, outp.Type)
}
if inp.Output {
out.Outputs = append(out.Outputs, outp)
}
out.FullParameters = append(out.FullParameters, outp)
} else {
out.Return = outp
if !isVoid(outp.ExpressionType()) {
out.Return.Name = "result"
out.Outputs = append(out.Outputs, outp)
out.FullParameters = append(out.FullParameters, outp)
}
}
}
out.Signature = getSignature(ctx, in, out.Return.Type, args)
ctx.mappings[in] = out
}
func parameter(ctx *context, owner *semantic.Function, in *ast.Parameter) *semantic.Parameter {
out := &semantic.Parameter{
AST: in,
Input: in.Input,
Output: in.Output,
Function: owner,
}
if in.Name != nil {
out.Name = in.Name.Value
}
out.Docs = findDocumentation(in.CST)
out.Annotations = annotations(ctx, in.Annotations)
out.Type = type_(ctx, in.Type)
ctx.mappings[in] = out
return out
}
func functionBody(ctx *context, owner semantic.Type, out *semantic.Function) {
in := out.AST
out.Owner = owner
if in.Block != nil {
ctx.with(semantic.VoidType, func() {
for _, p := range out.FullParameters {
ctx.add(p.Name, p)
}
if out.This != nil {
ctx.add(string(ast.KeywordThis), out.This)
}
out.Annotations = annotations(ctx, in.Annotations)
out.Block = block(ctx, in.Block, out)
addFence(ctx, out.Block)
})
}
if len(out.Docs) == 0 {
out.Docs = findDocumentation(out.AST.CST)
}
ctx.mappings[in] = out
}
func method(ctx *context, out *semantic.Function) {
functionSignature(ctx, out)
t := out.This.Type
switch t := t.(type) {
case *semantic.Pointer:
if class, ok := t.To.(*semantic.Class); !ok {
ctx.errorf(out.AST, "expected this as a reference to a class, got %s[%T]", typename(t.To), t.To)
} else {
class.Methods = append(class.Methods, out)
class.Members[out.Name] = out
functionBody(ctx, class, out)
}
case *semantic.Pseudonym:
t.Methods = append(t.Methods, out)
t.Members[out.Name] = out
functionBody(ctx, t, out)
case *semantic.Class:
t.Methods = append(t.Methods, out)
t.Members[out.Name] = out
functionBody(ctx, t, out)
default:
ctx.errorf(out.AST, "invalid type for this , got %s[%T]", typename(t), t)
}
ctx.mappings[out.AST] = out
}
func getSignature(ctx *context, at ast.Node, r semantic.Type, args []semantic.Type) *semantic.Signature {
buffer := bytes.Buffer{}
buffer.WriteString("fun_")
buffer.WriteString(r.Typename())
buffer.WriteString("_")
for _, a := range args {
buffer.WriteString("_")
buffer.WriteString(a.Typename())
}
name := buffer.String()
for _, s := range ctx.api.Signatures {
if s.Name == name {
if !equal(r, s.Return) {
ctx.icef(at, "Signature %s found with non matching return type, got %s expected %s", name, typename(s.Return), typename(r))
}
if len(args) != len(s.Arguments) {
ctx.icef(at, "Signature %s found with %d arguments, expected %s", name, len(s.Arguments), len(args))
}
for i, a := range args {
if !equal(a, s.Arguments[i]) {
ctx.icef(at, "Signature %s found with non matching arg at %d, got %s expected %s", name, i, typename(s.Arguments[i]), typename(a))
}
}
return s
}
}
out := &semantic.Signature{
Name: name,
Return: r,
Arguments: args,
}
ctx.api.Signatures = append(ctx.api.Signatures, out)
return out
}