
# Autogenerated by mlir-tblgen; don't manually edit.

from ._ods_common import _cext as _ods_cext
from ._ods_common import (
    equally_sized_accessor as _ods_equally_sized_accessor,
    get_default_loc_context as _ods_get_default_loc_context,
    get_op_results_or_values as _get_op_results_or_values,
    segmented_accessor as _ods_segmented_accessor,
)
_ods_ir = _ods_cext.ir
_ods_cext.globals.register_traceback_file_exclusion(__file__)

import builtins
from typing import Any as _Any, Sequence as _Sequence, Union as _Union, Optional as _Optional
import sys as _sys
if _sys.version_info >= (3, 12):
  from collections.abc import Buffer as _Buffer  # pytype: disable=not-supported-yet
else:
  try:
    from typing_extensions import Buffer as _Buffer
  except ImportError:
    _Buffer = _Any


from ._transform_ops_gen import _Dialect

@_ods_cext.register_operation(_Dialect)
class ConstrainParamsOp(_ods_ir.OpView):
  r"""
  Allows expressing constraints on params using the SMT dialect.
  
  Each Transform-dialect param provided as an operand has a corresponding
  argument of SMT-type in the region. The SMT-Dialect ops in the region use
  these params-as-SMT-vars as operands, thereby expressing relevant
  constraints on their allowed values.
  
  Computations w.r.t. passed-in params can also be expressed through the
  region's SMT-ops. Namely, the constraints express relationships to other
  SMT-variables which can then be yielded from the region (with `smt.yield`).
  
  The semantics of this op is that all the ops in the region together express
  a constraint on the params-interpreted-as-smt-vars. The op fails in case the
  expressed constraint is not satisfiable per SMTLIB semantics. Otherwise the
  op succeeds and any one satisfying assignment is used to map the
  SMT-variables yielded in the region to `transform.param`s.
  
  ---
  
  TODO: currently the operational semantics per the Transform interpreter is
  to always fail. The intention is build out support for hooking in your own
  operational semantics so you can invoke your favourite solver to determine
  satisfiability of the corresponding constraint problem.
  """

  OPERATION_NAME = "transform.smt.constrain_params"

  _ODS_REGIONS = (1, True)

  def __init__(self, results_: _Sequence[_ods_ir.Type], params: _Sequence[_ods_ir.Value], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.extend(_get_op_results_or_values(params))
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.extend(results_)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def params(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 1 + 1
    return self.operation.operands[0:0 + _ods_variadic_group_length]

  @builtins.property
  def results_(self) -> _ods_ir.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 1 + 1
    return self.operation.results[0:0 + _ods_variadic_group_length]

  @builtins.property
  def body(self) -> _ods_ir.Region:
    return self.regions[0]

@_ods_cext.register_op_adaptor(ConstrainParamsOp)
class ConstrainParamsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.smt.constrain_params"

  @builtins.property
  def params(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 1 + 1
    return self.operands[0:0 + _ods_variadic_group_length]

def smt_constrain_params(results_: _Sequence[_ods_ir.Type], params: _Sequence[_ods_ir.Value], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, ConstrainParamsOp]:
  op = ConstrainParamsOp(results_=results_, params=params, loc=loc, ip=ip); results = op.results
  return results if len(results) > 1 else (results[0] if len(results) == 1 else op)
