// Copyright 2021 The Tint Authors.
//
// 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 gen

import (
	"fmt"

	"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/sem"
	"dawn.googlesource.com/dawn/tools/src/list"
	"dawn.googlesource.com/dawn/tools/src/lut"
)

// IntrinsicTable holds data specific to the intrinsic_table.inl.tmpl template
type IntrinsicTable struct {
	// The semantic info
	Sem *sem.Sem

	// TMatchers are all the sem.TemplateType, sem.Type and sem.TypeMatchers.
	// These are all implemented by classes deriving from tint::TypeMatcher
	TMatchers     []sem.Named
	TMatcherIndex map[sem.Named]int // [object -> index] in TMatcher

	// NMatchers are all the sem.TemplateNumber and sem.EnumMatchers.
	// These are all implemented by classes deriving from tint::NumberMatcher
	NMatchers     []sem.Named
	NMatcherIndex map[sem.Named]int // [object -> index] in NMatchers

	MatcherIndices            []int            // kMatcherIndices table content
	TemplateTypes             []TemplateType   // kTemplateTypes table content
	TemplateNumbers           []TemplateNumber // kTemplateNumbers table content
	Parameters                []Parameter      // kParameters table content
	Overloads                 []Overload       // kOverloads table content
	Builtins                  []Intrinsic      // kBuiltins table content
	UnaryOperators            []Intrinsic      // kUnaryOperators table content
	BinaryOperators           []Intrinsic      // kBinaryOperators table content
	ConstructorsAndConverters []Intrinsic      // kConstructorsAndConverters table content
}

// TemplateType is used to create the C++ TemplateTypeInfo structure
type TemplateType struct {
	// Name of the template type (e.g. 'T')
	Name string
	// Optional type matcher constraint.
	// Either an index in Matchers::type, or -1
	MatcherIndex int
}

// TemplateNumber is used to create the C++ TemplateNumberInfo structure
type TemplateNumber struct {
	// Name of the template number (e.g. 'N')
	Name string
	// Optional type matcher constraint.
	// Either an index in Matchers::type, or -1
	MatcherIndex int
}

// Parameter is used to create the C++ ParameterInfo structure
type Parameter struct {
	// The parameter usage (parameter name)
	Usage string

	// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
	// required to match the parameter type. The matcher indices index
	// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
	// These indices are consumed by the matchers themselves.
	// The first index is always a TypeMatcher.
	MatcherIndicesOffset *int
}

// Overload is used to create the C++ OverloadInfo structure
type Overload struct {
	// Total number of parameters for the overload
	NumParameters int
	// Total number of template types for the overload
	NumTemplateTypes int
	// Total number of template numbers for the overload
	NumTemplateNumbers int
	// Index to the first template type in IntrinsicTable.TemplateTypes
	TemplateTypesOffset *int
	// Index to the first template number in IntrinsicTable.TemplateNumbers
	TemplateNumbersOffset *int
	// Index to the first parameter in IntrinsicTable.Parameters
	ParametersOffset *int
	// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
	// required to match the return type. The matcher indices index
	// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
	// These indices are consumed by the matchers themselves.
	// The first index is always a TypeMatcher.
	ReturnMatcherIndicesOffset *int
	// StageUses describes the stages an overload can be used in
	CanBeUsedInStage sem.StageUses
	// True if the overload is marked as deprecated
	IsDeprecated bool
	// The kind of overload
	Kind string
}

// Intrinsic is used to create the C++ IntrinsicInfo structure
type Intrinsic struct {
	Name                 string
	OverloadDescriptions []string
	NumOverloads         int
	OverloadsOffset      *int
}

// Helper for building the IntrinsicTable
type IntrinsicTableBuilder struct {
	// The output of the builder
	IntrinsicTable

	// Lookup tables.
	// These are packed (compressed) once all the entries have been added.
	lut struct {
		matcherIndices  lut.LUT
		templateTypes   lut.LUT
		templateNumbers lut.LUT
		parameters      lut.LUT
		overloads       lut.LUT
	}
}

// Helper for building a single overload
type overloadBuilder struct {
	*IntrinsicTableBuilder
	// Maps TemplateParam to index in templateTypes
	templateTypeIndex map[sem.TemplateParam]int
	// Maps TemplateParam to index in templateNumbers
	templateNumberIndex map[sem.TemplateParam]int
	// Template types used by the overload
	templateTypes []TemplateType
	// Template numbers used by the overload
	templateNumbers []TemplateNumber
	// All parameters declared by the overload
	parameters []Parameter
	// Index into IntrinsicTable.MatcherIndices, beginning the list of matchers
	// required to match the return type. The matcher indices index
	// into IntrinsicTable::TMatchers and / or IntrinsicTable::NMatchers.
	// These indices are consumed by the matchers themselves.
	// The first index is always a TypeMatcher.
	returnTypeMatcherIndicesOffset *int
}

// layoutMatchers assigns each of the TMatchers and NMatchers a unique index
// in the C++ Matchers::type and Matchers::number arrays, respectively.
func (b *IntrinsicTableBuilder) layoutMatchers(s *sem.Sem) {
	// First MaxTemplateTypes of TMatchers are template types
	b.TMatchers = make([]sem.Named, s.MaxTemplateTypes)
	for _, m := range s.Types {
		b.TMatcherIndex[m] = len(b.TMatchers)
		b.TMatchers = append(b.TMatchers, m)
	}
	for _, m := range s.TypeMatchers {
		b.TMatcherIndex[m] = len(b.TMatchers)
		b.TMatchers = append(b.TMatchers, m)
	}

	// First MaxTemplateNumbers of NMatchers are template numbers
	b.NMatchers = make([]sem.Named, s.MaxTemplateNumbers)
	for _, m := range s.EnumMatchers {
		b.NMatcherIndex[m] = len(b.NMatchers)
		b.NMatchers = append(b.NMatchers, m)
	}
}

// buildOverload constructs an Overload for a sem.Overload
func (b *IntrinsicTableBuilder) buildOverload(o *sem.Overload) (Overload, error) {
	ob := overloadBuilder{
		IntrinsicTableBuilder: b,
		templateTypeIndex:     map[sem.TemplateParam]int{},
		templateNumberIndex:   map[sem.TemplateParam]int{},
	}

	if err := ob.buildTemplateTypes(o); err != nil {
		return Overload{}, err
	}
	if err := ob.buildTemplateNumbers(o); err != nil {
		return Overload{}, err
	}
	if err := ob.buildParameters(o); err != nil {
		return Overload{}, err
	}
	if err := ob.buildReturnType(o); err != nil {
		return Overload{}, err
	}

	return Overload{
		NumParameters:              len(ob.parameters),
		NumTemplateTypes:           len(ob.templateTypes),
		NumTemplateNumbers:         len(ob.templateNumbers),
		TemplateTypesOffset:        b.lut.templateTypes.Add(ob.templateTypes),
		TemplateNumbersOffset:      b.lut.templateNumbers.Add(ob.templateNumbers),
		ParametersOffset:           b.lut.parameters.Add(ob.parameters),
		ReturnMatcherIndicesOffset: ob.returnTypeMatcherIndicesOffset,
		CanBeUsedInStage:           o.CanBeUsedInStage,
		IsDeprecated:               o.IsDeprecated,
		Kind:                       string(o.Decl.Kind),
	}, nil
}

// buildTemplateTypes constructs the TemplateTypes used by the overload, populating
// b.templateTypes
func (b *overloadBuilder) buildTemplateTypes(o *sem.Overload) error {
	b.templateTypes = make([]TemplateType, len(o.TemplateTypes))
	for i, t := range o.TemplateTypes {
		b.templateTypeIndex[t] = i
		matcherIndex := -1
		if t.Type != nil {
			var err error
			matcherIndex, err = b.matcherIndex(t.Type)
			if err != nil {
				return err
			}
		}
		b.templateTypes[i] = TemplateType{
			Name:         t.Name,
			MatcherIndex: matcherIndex,
		}
	}
	return nil
}

// buildTemplateNumbers constructs the TemplateNumbers used by the overload, populating
// b.templateNumbers
func (b *overloadBuilder) buildTemplateNumbers(o *sem.Overload) error {
	b.templateNumbers = make([]TemplateNumber, len(o.TemplateNumbers))
	for i, t := range o.TemplateNumbers {
		b.templateNumberIndex[t] = i
		matcherIndex := -1
		if e, ok := t.(*sem.TemplateEnumParam); ok && e.Matcher != nil {
			var err error
			matcherIndex, err = b.matcherIndex(e.Matcher)
			if err != nil {
				return err
			}
		}
		b.templateNumbers[i] = TemplateNumber{
			Name:         t.GetName(),
			MatcherIndex: matcherIndex,
		}
	}
	return nil
}

// buildParameters constructs the Parameters used by the overload, populating
// b.parameters
func (b *overloadBuilder) buildParameters(o *sem.Overload) error {
	b.parameters = make([]Parameter, len(o.Parameters))
	for i, p := range o.Parameters {
		indices, err := b.collectMatcherIndices(p.Type)
		if err != nil {
			return err
		}

		b.parameters[i] = Parameter{
			Usage:                p.Name,
			MatcherIndicesOffset: b.lut.matcherIndices.Add(indices),
		}
	}
	return nil
}

// buildParameters calculates the matcher indices required to match the
// overload's return type (if the overload has a return value), possibly
// populating b.returnTypeMatcherIndicesOffset
func (b *overloadBuilder) buildReturnType(o *sem.Overload) error {
	if o.ReturnType != nil {
		indices, err := b.collectMatcherIndices(*o.ReturnType)
		if err != nil {
			return err
		}
		b.returnTypeMatcherIndicesOffset = b.lut.matcherIndices.Add(indices)
	}
	return nil
}

// matcherIndex returns the index of TMatcher or NMatcher in
// IntrinsicTable.TMatcher or IntrinsicTable.NMatcher, respectively.
func (b *overloadBuilder) matcherIndex(n sem.Named) (int, error) {
	switch n := n.(type) {
	case *sem.Type, *sem.TypeMatcher:
		if i, ok := b.TMatcherIndex[n]; ok {
			return i, nil
		}
		return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
	case *sem.TemplateTypeParam:
		if i, ok := b.templateTypeIndex[n]; ok {
			return i, nil
		}
		return 0, fmt.Errorf("templateTypeIndex missing entry for %v %T", n.Name, n)
	case *sem.EnumMatcher:
		if i, ok := b.NMatcherIndex[n]; ok {
			return i, nil
		}
		return 0, fmt.Errorf("matcherIndex missing entry for %v %T", n.GetName(), n)
	case *sem.TemplateEnumParam:
		if i, ok := b.templateNumberIndex[n]; ok {
			return i, nil
		}
		return 0, fmt.Errorf("templateNumberIndex missing entry for %v %T", n, n)
	case *sem.TemplateNumberParam:
		if i, ok := b.templateNumberIndex[n]; ok {
			return i, nil
		}
		return 0, fmt.Errorf("templateNumberIndex missing entry for %v %T", n, n)
	default:
		return 0, fmt.Errorf("overload.matcherIndex() does not handle %v %T", n, n)
	}
}

// collectMatcherIndices returns the full list of matcher indices required to
// match the fully-qualified-name. For names that have do not have templated
// arguments, collectMatcherIndices() will return a single TMatcher index.
// For names that do have templated arguments, collectMatcherIndices() returns
// a list of type matcher indices, starting with the target of the fully
// qualified name, then followed by each of the template arguments from left to
// right. Note that template arguments may themselves have template arguments,
// and so collectMatcherIndices() may call itself.
// The order of returned matcher indices is always the order of the fully
// qualified name as read from left to right.
// For example, calling collectMatcherIndices() for the fully qualified name:
//    A<B<C, D>, E<F, G<H>, I>
// Would return the matcher indices:
//    A, B, C, D, E, F, G, H, I
func (b *overloadBuilder) collectMatcherIndices(fqn sem.FullyQualifiedName) ([]int, error) {
	idx, err := b.matcherIndex(fqn.Target)
	if err != nil {
		return nil, err
	}
	out := []int{idx}
	for _, arg := range fqn.TemplateArguments {
		indices, err := b.collectMatcherIndices(arg.(sem.FullyQualifiedName))
		if err != nil {
			return nil, err
		}
		out = append(out, indices...)
	}
	return out, nil
}

// buildIntrinsicTable builds the IntrinsicTable from the semantic info
func buildIntrinsicTable(s *sem.Sem) (*IntrinsicTable, error) {
	b := IntrinsicTableBuilder{
		IntrinsicTable: IntrinsicTable{
			Sem:           s,
			TMatcherIndex: map[sem.Named]int{},
			NMatcherIndex: map[sem.Named]int{},
		},
	}
	b.lut.matcherIndices = lut.New(list.Wrap(&b.MatcherIndices))
	b.lut.templateTypes = lut.New(list.Wrap(&b.TemplateTypes))
	b.lut.templateNumbers = lut.New(list.Wrap(&b.TemplateNumbers))
	b.lut.parameters = lut.New(list.Wrap(&b.Parameters))
	b.lut.overloads = lut.New(list.Wrap(&b.Overloads))

	b.layoutMatchers(s)

	for _, intrinsics := range []struct {
		in  []*sem.Intrinsic
		out *[]Intrinsic
	}{
		{s.Builtins, &b.Builtins},
		{s.UnaryOperators, &b.UnaryOperators},
		{s.BinaryOperators, &b.BinaryOperators},
		{s.ConstructorsAndConverters, &b.ConstructorsAndConverters},
	} {
		out := make([]Intrinsic, len(intrinsics.in))
		for i, f := range intrinsics.in {
			overloads := make([]Overload, len(f.Overloads))
			overloadDescriptions := make([]string, len(f.Overloads))
			for i, o := range f.Overloads {
				overloadDescriptions[i] = fmt.Sprint(o.Decl)
				var err error
				if overloads[i], err = b.buildOverload(o); err != nil {
					return nil, err
				}
			}
			out[i] = Intrinsic{
				Name:                 f.Name,
				OverloadDescriptions: overloadDescriptions,
				NumOverloads:         len(overloads),
				OverloadsOffset:      b.lut.overloads.Add(overloads),
			}
		}
		*intrinsics.out = out
	}

	b.lut.matcherIndices.Compact()
	b.lut.templateTypes.Compact()
	b.lut.templateNumbers.Compact()
	b.lut.parameters.Compact()
	b.lut.overloads.Compact()

	return &b.IntrinsicTable, nil
}
