// 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 (
	"fmt"
	"strconv"

	"android.googlesource.com/platform/tools/gpu/api/ast"
	"android.googlesource.com/platform/tools/gpu/api/semantic"
)

type invalid struct{}

func (invalid) ExpressionType() semantic.Type { return semantic.VoidType }

// expression translates the ast expression to a semantic expression.
func expression(ctx *context, in interface{}) semantic.Expression {
	switch in := in.(type) {
	case *ast.UnaryOp:
		return unaryOp(ctx, in)
	case *ast.BinaryOp:
		return binaryOp(ctx, in)
	case *ast.Call:
		return call(ctx, in)
	case *ast.Switch:
		return select_(ctx, in)
	case *ast.Member:
		return member(ctx, in)
	case *ast.Index:
		return index(ctx, in)
	case *ast.Identifier:
		return identifier(ctx, in)
	case *ast.ClassInitializer:
		return classInitializer(ctx, in)
	case *ast.New:
		return new(ctx, in)
	case *ast.Group:
		return expression(ctx, in.Expression)
	case *ast.Cast:
		return cast(ctx, in)
	case *ast.Length:
		return length(ctx, in)
	case *ast.Unknown:
		return &semantic.Unknown{AST: in}
	case *ast.Number:
		return number(ctx, in)
	case *ast.Bool:
		return semantic.BoolValue(in.Value)
	case *ast.String:
		return semantic.StringValue(in.Value)
	default:
		ctx.icef(in, "Unhandled expression type %T found", in)
		return invalid{}
	}
}

func call(ctx *context, in *ast.Call) semantic.Expression {
	target := expression(ctx, in.Target)
	switch target := target.(type) {
	case *macroStub:
		return macroCall(ctx, in, target)
	case *semantic.Callable:
		return functionCall(ctx, in, target)
	default:
		ctx.errorf(in, "Invalid method call target %T found", target)
		return invalid{}
	}
}

func callArguments(ctx *context, in []interface{}, params []*semantic.Parameter, name string) []semantic.Expression {
	out := []semantic.Expression{}
	if len(params) != len(in) {
		ctx.errorf(in, "wrong number of arguments to %s, expected %v got %v", name, len(params), len(in))
		return out
	}
	for i, a := range in {
		p := params[i]
		ctx.with(p.Type, func() {
			arg := expression(ctx, a)
			at := arg.ExpressionType()
			out = append(out, arg)
			if !assignable(p.Type, at) {
				ctx.errorf(a, "argument %d to %s is wrong type, expected %s got %s", i, name, typename(p.Type), typename(at))
			}
		})
	}
	return out
}

func functionCall(ctx *context, in *ast.Call, target *semantic.Callable) *semantic.Call {
	out := &semantic.Call{AST: in, Target: target, Type: semantic.VoidType}
	params := target.Function.FullParameters
	if target.Object != nil {
		if target.Function.This == nil {
			ctx.errorf(in, "method call on non method %s of %T", target.Function.Name, target.Object)
			return out
		}
		params = params[1:len(params)]
	}
	if target.Function.Return.Type != semantic.VoidType {
		params = params[0 : len(params)-1]
	}
	out.Arguments = callArguments(ctx, in.Arguments, params, target.Function.Name)
	out.Type = out.Target.Function.Return.Type
	return out
}

func macroCall(ctx *context, in *ast.Call, stub *macroStub) semantic.Expression {
	if ctx.scope.block == nil {
		ctx.errorf(in, "macro call outside of block scope")
		return invalid{}
	}
	// generate a globally unique naming prefix to prevent symbol collisions
	prefix := fmt.Sprintf("%s_%v_", stub.function.Name, ctx.uid())
	params := stub.function.CallParameters()
	var result *semantic.DeclareLocal
	args := callArguments(ctx, in.Arguments, params, stub.function.Name)
	// switch scopes back to the one the macro was declared in to prevent symbol leak
	callScope := ctx.scope
	ctx.scope = stub.scope
	defer func() { ctx.scope = callScope }()
	ctx.with(semantic.VoidType, func() {
		// put the block back so we inject directly in to it
		ctx.scope.block = callScope.block
		// replace parameters with a new uniquely named local variable
		for i, p := range params {
			l := addLocal(ctx, nil, p.Name, args[i])
			// set the unique name after symbol table injection
			// this means that the lookups inside the macro match the local correctly
			// but the semantic graph as a globally unique name
			l.Local.Name = prefix + l.Local.Name
			ctx.addStatement(l)
		}
		// evaluate the macro body in place
		r := body(ctx, stub.function.AST.Block.Statements, stub.function)
		// substitute the return statement for a local assignment
		if r != nil {
			result = addLocal(ctx, nil, prefix+"result", r.Value)
			ctx.addStatement(result)
		}
	})
	if result == nil {
		return invalid{}
	}
	return result.Local
}

func select_(ctx *context, in *ast.Switch) *semantic.Select {
	out := &semantic.Select{AST: in}
	out.Type = nil
	out.Value = expression(ctx, in.Value)
	vt := out.Value.ExpressionType()
	for _, c := range in.Cases {
		e := choice(ctx, c, vt)
		out.Choices = append(out.Choices, e)
		if out.Type == nil {
			out.Type = e.Expression.ExpressionType()
		} else if !equal(out.Type, e.Expression.ExpressionType()) {
			// TODO: This could be a common ancestor type instead?
			out.Type = semantic.VoidType
		}
	}
	if out.Type == nil {
		ctx.errorf(in, "could not determine type of switch")
		out.Type = semantic.VoidType
	}
	return out
}

// choice translates Case in to a select Choice.
// vt is the resolved type of the select value being compared against, and can
// be used to infer the choice condition type.
func choice(ctx *context, in *ast.Case, vt semantic.Type) *semantic.Choice {
	out := &semantic.Choice{AST: in}
	ctx.with(vt, func() {
		for _, cond := range in.Conditions {
			exp := expression(ctx, cond)
			out.Conditions = append(out.Conditions, exp)
			ct := exp.ExpressionType()
			if !comparable(vt, ct) {
				ctx.errorf(cond, "select value %s is not comparable with choice condition %s", typename(vt), typename(ct))
			}
		}
	})
	if len(in.Block.Statements) != 1 {
		ctx.errorf(in, "switch case is not a single expression")
		out.Expression = invalid{}
		return out
	}
	out.Expression = expression(ctx, in.Block.Statements[0])
	return out
}

func member(ctx *context, in *ast.Member) semantic.Expression {
	obj := expression(ctx, in.Object)
	ot := obj.ExpressionType()
	entry := ot.Member(in.Name.Value)
	if entry == nil {
		ctx.errorf(in, "%s is not a member of %s", in.Name.Value, typename(ot))
		return invalid{}
	}
	switch entry := entry.(type) {
	case *semantic.Field:
		return &semantic.Member{AST: in, Object: obj, Field: entry}
	case *semantic.Function:
		return &semantic.Callable{Object: obj, Function: entry}
	default:
		ctx.errorf(in, "Invalid member lookup type %T found", entry)
		return invalid{}
	}
}

func index(ctx *context, in *ast.Index) semantic.Expression {
	object := expression(ctx, in.Object)
	at := object.ExpressionType()
	switch at := at.(type) {
	case *semantic.Array:
		out := &semantic.ArrayIndex{AST: in, Array: object}
		ctx.with(semantic.Int32Type, func() {
			out.Index = expression(ctx, in.Index)
		})
		it := out.Index.ExpressionType()
		if !equal(it, semantic.Int32Type) && !equal(it, semantic.Uint32Type) {
			ctx.errorf(in, "type %s not valid indexing array", typename(it))
		}
		out.ValueType = at.ValueType
		return out
	case *semantic.Map:
		out := &semantic.MapIndex{AST: in, Map: object}
		ctx.with(at.KeyType, func() {
			out.Index = expression(ctx, in.Index)
		})
		it := out.Index.ExpressionType()
		if !comparable(it, at.KeyType) {
			ctx.errorf(in, "type %s not valid indexing map", typename(it))
		}
		out.ValueType = at.ValueType
		return out
	default:
		ctx.errorf(in, "index operation on non indexable type %s", typename(at))
		return invalid{}
	}
}

func identifier(ctx *context, in *ast.Identifier) semantic.Expression {
	out := ctx.get(in, in.Value)
	switch out := out.(type) {
	case *semantic.Function:
		return &semantic.Callable{Function: out}
	case semantic.Expression:
		return out
	default:
		ctx.errorf(in, "Symbol %s was non expression %T", in.Value, out)
		return invalid{}
	}
}

func classInitializer(ctx *context, in *ast.ClassInitializer) *semantic.ClassInitializer {
	out := &semantic.ClassInitializer{AST: in}
	t := type_(ctx, in.Class)
	class, ok := t.(*semantic.Class)
	if !ok {
		ctx.errorf(in.Class, "non class entry %s in extension list", typename(t))
		return out
	}
	out.Class = class
	for _, f := range in.Fields {
		out.Fields = append(out.Fields, fieldInitializer(ctx, out.Class, f))
	}
	return out
}

func fieldInitializer(ctx *context, class *semantic.Class, in *ast.FieldInitializer) *semantic.FieldInitializer {
	out := &semantic.FieldInitializer{AST: in}
	m := class.Member(in.Name.Value)
	if m == nil {
		ctx.errorf(in.Name, "class %s has no field %s", class.Name, in.Name.Value)
		return out
	}
	field, ok := m.(*semantic.Field)
	if !ok {
		ctx.errorf(in.Name, "member %s of class %s is not a field [%T]", in.Name.Value, class.Name, m)
		return out
	}
	out.Field = field
	ctx.with(field.Type, func() {
		out.Value = expression(ctx, in.Value)
	})
	ft := out.Field.Type
	vt := out.Value.ExpressionType()
	if !assignable(ft, vt) {
		ctx.errorf(in, "field %s cannot assign %s to %s", out.Field.Name, typename(vt), typename(ft))
	}
	return out
}

func new(ctx *context, in *ast.New) *semantic.New {
	out := &semantic.New{AST: in}
	out.Initializer = classInitializer(ctx, in.ClassInitializer)
	out.Type = getPointerType(ctx, in, out.Initializer.Class)
	return out
}

func cast(ctx *context, in *ast.Cast) semantic.Expression {
	t := type_(ctx, in.Type)
	var obj semantic.Expression
	ctx.with(t, func() {
		obj = expression(ctx, in.Object)
	})
	if equal(t, obj.ExpressionType()) {
		return obj
	}
	out := &semantic.Cast{AST: in, Object: obj, Type: t}
	if !castable(obj.ExpressionType(), out.Type) {
		ctx.errorf(in, "cannot cast from %s to %s", typename(obj.ExpressionType()), typename(out.Type))
	}
	return out
}

func length(ctx *context, in *ast.Length) *semantic.Length {
	out := &semantic.Length{AST: in}
	out.Object = expression(ctx, in.Object)
	at := out.Object.ExpressionType()
	if at == nil {
		ctx.errorf(in, "condition was not valid")
		return out
	}
	ok := false
	switch at.(type) {
	case *semantic.Array:
		ok = true
	case *semantic.Map:
		ok = true
	case *semantic.Builtin:
		if at == semantic.StringType || at == semantic.PointerType {
			ok = true
		}
	}
	if !ok {
		ctx.errorf(in, "len cannot work out length of type %s", typename(at))
		return out
	}
	infer := baseType(ctx.scope.inferType)
	switch infer {
	case semantic.Int32Type, semantic.Uint32Type, semantic.Int64Type, semantic.Uint64Type:
		out.Type = infer
	default:
		out.Type = semantic.Int32Type
	}
	return out
}

func number(ctx *context, in *ast.Number) semantic.Expression {
	infer := baseType(ctx.scope.inferType)
	out := inferNumber(ctx, in, infer)
	if out != nil {
		if infer == ctx.scope.inferType {
			return out
		}
		return &semantic.Cast{Type: ctx.scope.inferType, Object: out}
	}
	if v, err := strconv.ParseInt(in.Value, 0, 32); err == nil {
		return semantic.Int32Value(v)
	}
	if v, err := strconv.ParseFloat(in.Value, 64); err == nil {
		return semantic.Float64Value(v)
	}
	ctx.errorf(in, "could not parse %s as a number (%s)", in.Value, typename(infer))
	return invalid{}
}
