parameters: (FuncOp,
                     *inputs: Type,
                     results: Optional[Sequence[Type]] = None,
                     name: Optional[str] = None)
return_statement: return decorator
docstring: Decorator to define an MLIR FuncOp specified as a python function.
  
      Requires that an `mlir.ir.InsertionPoint` and `mlir.ir.Location` are
      active for the current thread (i.e. established in a `with` block).
  
      When applied as a decorator to a Python function, an entry block will
      be constructed for the FuncOp with types as specified in `*inputs`. The
      block arguments will be passed positionally to the Python function. In
      addition, if the Python function accepts keyword arguments generally or
      has a corresponding keyword argument, the following will be passed:
        * `func_op`: The `func` op being defined.
  
      By default, the function name will be the Python function `__name__`. This
      can be overriden by passing the `name` argument to the decorator.
  
      If `results` is not specified, then the decorator will implicitly
      insert a `ReturnOp` with the `Value`'s returned from the decorated
      function. It will also set the `FuncOp` type with the actual return
      value types. If `results` is specified, then the decorated function
      must return `None` and no implicit `ReturnOp` is added (nor are the result
      types updated). The implicit behavior is intended for simple, single-block
      cases, and users should specify result types explicitly for any complicated
      cases.
  
      The decorated function can further be called from Python and will insert
      a `CallOp` at the then-current insertion point, returning either None (
      if no return values), a unary Value (for one result), or a list of Values).
      This mechanism cannot be used to emit recursive calls (by construction).
docstring_summary: Decorator to define an MLIR FuncOp specified as a python function.
docstring_tokens: Decorator to define an MLIR FuncOp specified as a python function .
function: def from_py_func(FuncOp,
                     *inputs: Type,
                     results: Optional[Sequence[Type]] = None,
                     name: Optional[str] = None):
      """Decorator to define an MLIR FuncOp specified as a python function.
  
      Requires that an `mlir.ir.InsertionPoint` and `mlir.ir.Location` are
      active for the current thread (i.e. established in a `with` block).
  
      When applied as a decorator to a Python function, an entry block will
      be constructed for the FuncOp with types as specified in `*inputs`. The
      block arguments will be passed positionally to the Python function. In
      addition, if the Python function accepts keyword arguments generally or
      has a corresponding keyword argument, the following will be passed:
        * `func_op`: The `func` op being defined.
  
      By default, the function name will be the Python function `__name__`. This
      can be overriden by passing the `name` argument to the decorator.
  
      If `results` is not specified, then the decorator will implicitly
      insert a `ReturnOp` with the `Value`'s returned from the decorated
      function. It will also set the `FuncOp` type with the actual return
      value types. If `results` is specified, then the decorated function
      must return `None` and no implicit `ReturnOp` is added (nor are the result
      types updated). The implicit behavior is intended for simple, single-block
      cases, and users should specify result types explicitly for any complicated
      cases.
  
      The decorated function can further be called from Python and will insert
      a `CallOp` at the then-current insertion point, returning either None (
      if no return values), a unary Value (for one result), or a list of Values).
      This mechanism cannot be used to emit recursive calls (by construction).
      """
  
      def decorator(f):
        from . import std
        # Introspect the callable for optional features.
        sig = inspect.signature(f)
        has_arg_func_op = False
        for param in sig.parameters.values():
          if param.kind == param.VAR_KEYWORD:
            has_arg_func_op = True
          if param.name == "func_op" and (param.kind
                                          == param.POSITIONAL_OR_KEYWORD or
                                          param.kind == param.KEYWORD_ONLY):
            has_arg_func_op = True
  
        # Emit the FuncOp.
        implicit_return = results is None
        symbol_name = name or f.__name__
        function_type = FunctionType.get(
            inputs=inputs, results=[] if implicit_return else results)
        func_op = FuncOp(name=symbol_name, type=function_type)
        with InsertionPoint(func_op.add_entry_block()):
          func_args = func_op.entry_block.arguments
          func_kwargs = {}
          if has_arg_func_op:
            func_kwargs["func_op"] = func_op
          return_values = f(*func_args, **func_kwargs)
          if not implicit_return:
            return_types = list(results)
            assert return_values is None, (
                "Capturing a python function with explicit `results=` "
                "requires that the wrapped function returns None.")
          else:
            # Coerce return values, add ReturnOp and rewrite func type.
            if return_values is None:
              return_values = []
            elif isinstance(return_values, tuple):
              return_values = list(return_values)
            elif isinstance(return_values, Value):
              # Returning a single value is fine, coerce it into a list.
              return_values = [return_values]
            elif isinstance(return_values, OpView):
              # Returning a single operation is fine, coerce its results a list.
              return_values = return_values.operation.results
            elif isinstance(return_values, Operation):
              # Returning a single operation is fine, coerce its results a list.
              return_values = return_values.results
            else:
              return_values = list(return_values)
            std.ReturnOp(return_values)
            # Recompute the function type.
            return_types = [v.type for v in return_values]
            function_type = FunctionType.get(inputs=inputs, results=return_types)
            func_op.attributes["type"] = TypeAttr.get(function_type)
  
        def emit_call_op(*call_args):
          call_op = std.CallOp(return_types, FlatSymbolRefAttr.get(symbol_name),
                               call_args)
          if return_types is None:
            return None
          elif len(return_types) == 1:
            return call_op.result
          else:
            return call_op.results
  
        wrapped = emit_call_op
        wrapped.__name__ = f.__name__
        wrapped.func_op = func_op
        return wrapped
  
      return decorator
function_tokens: def from_py_func ( FuncOp , * inputs : Type , results : Optional [ Sequence [ Type ] ] = None , name : Optional [ str ] = None ) : def decorator ( f ) : from . import std # Introspect the callable for optional features. sig = inspect . signature ( f ) has_arg_func_op = False for param in sig . parameters . values ( ) : if param . kind == param . VAR_KEYWORD : has_arg_func_op = True if param . name == "func_op" and ( param . kind == param . POSITIONAL_OR_KEYWORD or param . kind == param . KEYWORD_ONLY ) : has_arg_func_op = True # Emit the FuncOp. implicit_return = results is None symbol_name = name or f . __name__ function_type = FunctionType . get ( inputs = inputs , results = [ ] if implicit_return else results ) func_op = FuncOp ( name = symbol_name , type = function_type ) with InsertionPoint ( func_op . add_entry_block ( ) ) : func_args = func_op . entry_block . arguments func_kwargs = { } if has_arg_func_op : func_kwargs [ "func_op" ] = func_op return_values = f ( * func_args , * * func_kwargs ) if not implicit_return : return_types = list ( results ) assert return_values is None , ( "Capturing a python function with explicit `results=` " "requires that the wrapped function returns None." ) else : # Coerce return values, add ReturnOp and rewrite func type. if return_values is None : return_values = [ ] elif isinstance ( return_values , tuple ) : return_values = list ( return_values ) elif isinstance ( return_values , Value ) : # Returning a single value is fine, coerce it into a list. return_values = [ return_values ] elif isinstance ( return_values , OpView ) : # Returning a single operation is fine, coerce its results a list. return_values = return_values . operation . results elif isinstance ( return_values , Operation ) : # Returning a single operation is fine, coerce its results a list. return_values = return_values . results else : return_values = list ( return_values ) std . ReturnOp ( return_values ) # Recompute the function type. return_types = [ v . type for v in return_values ] function_type = FunctionType . get ( inputs = inputs , results = return_types ) func_op . attributes [ "type" ] = TypeAttr . get ( function_type ) def emit_call_op ( * call_args ) : call_op = std . CallOp ( return_types , FlatSymbolRefAttr . get ( symbol_name ) , call_args ) if return_types is None : return None elif len ( return_types ) == 1 : return call_op . result else : return call_op . results wrapped = emit_call_op wrapped . __name__ = f . __name__ wrapped . func_op = func_op return wrapped return decorator