blob: abda52ff42b8efcce0405c53b83c075b82dfb2b3 [file] [log] [blame]
// Copyright (C) 2016 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 (
"strconv"
"android.googlesource.com/platform/tools/gpu/api/ast"
"android.googlesource.com/platform/tools/gpu/api/semantic"
)
func inferNumber(rv *resolver, in *ast.Number, infer semantic.Type) semantic.Expression {
var out semantic.Expression
switch infer {
case semantic.Int8Type:
if v, err := strconv.ParseInt(in.Value, 0, 8); err == nil {
out = semantic.Int8Value(v)
}
case semantic.Uint8Type:
if v, err := strconv.ParseUint(in.Value, 0, 8); err == nil {
out = semantic.Uint8Value(v)
}
case semantic.Int16Type:
if v, err := strconv.ParseInt(in.Value, 0, 16); err == nil {
out = semantic.Int16Value(v)
}
case semantic.Uint16Type:
if v, err := strconv.ParseUint(in.Value, 0, 16); err == nil {
out = semantic.Uint16Value(v)
}
case semantic.Int32Type:
if v, err := strconv.ParseInt(in.Value, 0, 32); err == nil {
out = semantic.Int32Value(v)
}
case semantic.Uint32Type:
if v, err := strconv.ParseUint(in.Value, 0, 32); err == nil {
out = semantic.Uint32Value(v)
}
case semantic.Int64Type:
if v, err := strconv.ParseInt(in.Value, 0, 64); err == nil {
out = semantic.Int64Value(v)
}
case semantic.Uint64Type:
if v, err := strconv.ParseUint(in.Value, 0, 64); err == nil {
out = semantic.Uint64Value(v)
}
case semantic.Float32Type:
if v, err := strconv.ParseFloat(in.Value, 32); err == nil {
out = semantic.Float32Value(v)
}
case semantic.Float64Type:
if v, err := strconv.ParseFloat(in.Value, 64); err == nil {
out = semantic.Float64Value(v)
}
default:
return nil
}
rv.mappings.add(in, out)
return out
}
func inferUnknown(rv *resolver, lhs semantic.Node, rhs semantic.Node) {
// We cannot infer unknown if assigning to _.
// This is ok if the unknown is still inferred later.
if _, isIgnore := lhs.(*semantic.Ignore); isIgnore {
return
}
u := findUnknown(rv, rhs)
if u != nil && u.Inferred == nil {
u.Inferred = lhsToObserved(rv, lhs)
}
}
func findUnknown(rv *resolver, rhs semantic.Node) *semantic.Unknown {
switch rhs := rhs.(type) {
case *semantic.Unknown:
return rhs
case *semantic.Cast:
return findUnknown(rv, rhs.Object)
case *semantic.Local:
return findUnknown(rv, rhs.Value)
default:
return nil
}
}
// lhsToObserved takes an expression that is a valid lhs of an assignment, and
// creates a new expression that would read the observed output.
// This is used when attempting to infer the value an Unknown had from the
// observed outputs.
func lhsToObserved(rv *resolver, lhs semantic.Node) semantic.Expression {
switch lhs := lhs.(type) {
case *semantic.SliceIndex:
o := lhsToObserved(rv, lhs.Slice)
if o == nil {
return nil
}
return &semantic.SliceIndex{Slice: o, Index: lhs.Index, Type: lhs.Type}
case *semantic.PointerRange:
o := lhsToObserved(rv, lhs.Pointer)
if o == nil {
return nil
}
return &semantic.PointerRange{Pointer: o, Range: lhs.Range, Type: lhs.Type}
case *semantic.MapIndex:
o := lhsToObserved(rv, lhs.Map)
if o == nil {
return nil
}
return &semantic.MapIndex{Map: o, Index: lhs.Index, Type: lhs.Type}
case *semantic.Parameter:
if f := rv.scope.function; f != nil && f.Subroutine && lhs == f.Return {
rv.errorf(lhs, "unknowns cannot be used to infer return values in subroutines")
}
return &semantic.Observed{Parameter: lhs}
case *semantic.Local:
return lhsToObserved(rv, lhs.Value)
case *semantic.Member:
obj := lhsToObserved(rv, lhs.Object)
return &semantic.Member{Object: obj, Field: lhs.Field}
default:
rv.errorf(lhs, "Cannot infer unknown from %T", lhs)
return nil
}
}