#
# Generate code for op that has Expr, ExprList, and private fields.
#
optgen exprs test.opt
define FuncCall {
    Name Expr
    Args ExprList
    Def  FuncOpDef
}
----
----
// Code generated by optgen; [omitted]

package memo

import (
	"github.com/cockroachdb/cockroach/pkg/sql/coltypes"
	"github.com/cockroachdb/cockroach/pkg/sql/opt"
	"github.com/cockroachdb/cockroach/pkg/sql/opt/props"
	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
	"github.com/cockroachdb/cockroach/pkg/sql/sem/types"
)

var opLayoutTable = [...]opLayout{
	opt.UnknownOp:  0xFF, // will cause a crash if used
	opt.FuncCallOp: makeOpLayout(1 /*base*/, 2 /*list*/, 4 /*priv*/),
}

type FuncCallExpr Expr

func MakeFuncCallExpr(name GroupID, args ListID, def PrivateID) FuncCallExpr {
	return FuncCallExpr{op: opt.FuncCallOp, state: exprState{uint32(name), args.Offset, args.Length, uint32(def)}}
}

func (e *FuncCallExpr) Name() GroupID {
	return GroupID(e.state[0])
}

func (e *FuncCallExpr) Args() ListID {
	return ListID{Offset: e.state[1], Length: e.state[2]}
}

func (e *FuncCallExpr) Def() PrivateID {
	return PrivateID(e.state[3])
}

func (e *FuncCallExpr) Fingerprint() Fingerprint {
	return Fingerprint(*e)
}

func (e *Expr) AsFuncCall() *FuncCallExpr {
	if e.op != opt.FuncCallOp {
		return nil
	}
	return (*FuncCallExpr)(e)
}

// InternFuncOpDef adds the given value to the memo and returns an ID that
// can be used for later lookup. If the same value was added previously,
// this method is a no-op and returns the ID of the previous value.
func (m *Memo) InternFuncOpDef(val *FuncOpDef) PrivateID {
	return m.privateStorage.internFuncOpDef(val)
}

type makeExprFunc func(operands DynamicOperands) Expr

var makeExprLookup [opt.NumOperators]makeExprFunc

func init() {
	// UnknownOp
	makeExprLookup[opt.UnknownOp] = func(operands DynamicOperands) Expr {
		panic("op type not initialized")
	}

	// FuncCallOp
	makeExprLookup[opt.FuncCallOp] = func(operands DynamicOperands) Expr {
		return Expr(MakeFuncCallExpr(GroupID(operands[0]), operands[1].ListID(), PrivateID(operands[2])))
	}

}

func MakeExpr(op opt.Operator, operands DynamicOperands) Expr {
	return makeExprLookup[op](operands)
}
----
----

#
# Generate code for enforcer op.
#
optgen exprs test.opt
[Enforcer]
define Sort {
    Input Expr
}
----
----
// Code generated by optgen; [omitted]

package memo

import (
	"github.com/cockroachdb/cockroach/pkg/sql/coltypes"
	"github.com/cockroachdb/cockroach/pkg/sql/opt"
	"github.com/cockroachdb/cockroach/pkg/sql/opt/props"
	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
	"github.com/cockroachdb/cockroach/pkg/sql/sem/types"
)

var opLayoutTable = [...]opLayout{
	opt.UnknownOp: 0xFF, // will cause a crash if used
	opt.SortOp:    makeOpLayout(1 /*base*/, 0 /*list*/, 0 /*priv*/),
}

var isEnforcerLookup = [...]bool{
	opt.UnknownOp: false,

	opt.SortOp: true,
}

func (ev ExprView) IsEnforcer() bool {
	return isEnforcerLookup[ev.op]
}

func (e *Expr) IsEnforcer() bool {
	return isEnforcerLookup[e.op]
}

type makeExprFunc func(operands DynamicOperands) Expr

var makeExprLookup [opt.NumOperators]makeExprFunc

func init() {
	// UnknownOp
	makeExprLookup[opt.UnknownOp] = func(operands DynamicOperands) Expr {
		panic("op type not initialized")
	}

}

func MakeExpr(op opt.Operator, operands DynamicOperands) Expr {
	return makeExprLookup[op](operands)
}
----
----
