// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package noder

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/syntax"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/compile/internal/types2"
	"cmd/internal/src"
)

func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) {
	obj, ok := g.info.Defs[name]
	if !ok {
		base.FatalfAt(g.pos(name), "unknown name %v", name)
	}
	return g.obj(obj), obj
}

func (g *irgen) use(name *syntax.Name) *ir.Name {
	obj, ok := g.info.Uses[name]
	if !ok {
		base.FatalfAt(g.pos(name), "unknown name %v", name)
	}
	return ir.CaptureName(g.pos(obj), ir.CurFunc, g.obj(obj))
}

// obj returns the Name that represents the given object. If no such
// Name exists yet, it will be implicitly created.
//
// For objects declared at function scope, ir.CurFunc must already be
// set to the respective function when the Name is created.
func (g *irgen) obj(obj types2.Object) *ir.Name {
	// For imported objects, we use iimport directly instead of mapping
	// the types2 representation.
	if obj.Pkg() != g.self {
		sym := g.sym(obj)
		if sym.Def != nil {
			return sym.Def.(*ir.Name)
		}
		n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
		if n, ok := n.(*ir.Name); ok {
			return n
		}
		base.FatalfAt(g.pos(obj), "failed to resolve %v", obj)
	}

	if name, ok := g.objs[obj]; ok {
		return name // previously mapped
	}

	var name *ir.Name
	pos := g.pos(obj)

	class := typecheck.DeclContext
	if obj.Parent() == g.self.Scope() {
		class = ir.PEXTERN // forward reference to package-block declaration
	}

	// "You are in a maze of twisting little passages, all different."
	switch obj := obj.(type) {
	case *types2.Const:
		name = g.objCommon(pos, ir.OLITERAL, g.sym(obj), class, g.typ(obj.Type()))

	case *types2.Func:
		sig := obj.Type().(*types2.Signature)
		var sym *types.Sym
		var typ *types.Type
		if recv := sig.Recv(); recv == nil {
			if obj.Name() == "init" {
				sym = renameinit()
			} else {
				sym = g.sym(obj)
			}
			typ = g.typ(sig)
		} else {
			sym = g.selector(obj)
			if !sym.IsBlank() {
				sym = ir.MethodSym(g.typ(recv.Type()), sym)
			}
			typ = g.signature(g.param(recv), sig)
		}
		name = g.objCommon(pos, ir.ONAME, sym, ir.PFUNC, typ)

	case *types2.TypeName:
		if obj.IsAlias() {
			name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type()))
		} else {
			name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj))
			g.objFinish(name, class, types.NewNamed(name))
		}

	case *types2.Var:
		var sym *types.Sym
		if class == ir.PPARAMOUT {
			// Backend needs names for result parameters,
			// even if they're anonymous or blank.
			switch obj.Name() {
			case "":
				sym = typecheck.LookupNum("~r", len(ir.CurFunc.Dcl)) // 'r' for "result"
			case "_":
				sym = typecheck.LookupNum("~b", len(ir.CurFunc.Dcl)) // 'b' for "blank"
			}
		}
		if sym == nil {
			sym = g.sym(obj)
		}
		name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type()))

	default:
		g.unhandled("object", obj)
	}

	g.objs[obj] = name
	return name
}

func (g *irgen) objCommon(pos src.XPos, op ir.Op, sym *types.Sym, class ir.Class, typ *types.Type) *ir.Name {
	name := ir.NewDeclNameAt(pos, op, sym)
	g.objFinish(name, class, typ)
	return name
}

func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) {
	sym := name.Sym()

	name.SetType(typ)
	name.Class = class
	if name.Class == ir.PFUNC {
		sym.SetFunc(true)
	}

	// We already know name's type, but typecheck is really eager to try
	// recomputing it later. This appears to prevent that at least.
	name.Ntype = ir.TypeNode(typ)
	name.SetTypecheck(1)
	name.SetWalkdef(1)

	if ir.IsBlank(name) {
		return
	}

	switch class {
	case ir.PEXTERN:
		g.target.Externs = append(g.target.Externs, name)
		fallthrough
	case ir.PFUNC:
		sym.Def = name
		if name.Class == ir.PFUNC && name.Type().Recv() != nil {
			break // methods are exported with their receiver type
		}
		if types.IsExported(sym.Name) {
			if name.Class == ir.PFUNC && name.Type().NumTParams() > 0 {
				base.FatalfAt(name.Pos(), "Cannot export a generic function (yet): %v", name)
			}
			typecheck.Export(name)
		}
		if base.Flag.AsmHdr != "" && !name.Sym().Asm() {
			name.Sym().SetAsm(true)
			g.target.Asms = append(g.target.Asms, name)
		}

	default:
		// Function-scoped declaration.
		name.Curfn = ir.CurFunc
		if name.Op() == ir.ONAME {
			ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, name)
		}
	}
}
