(root)/
Python-3.12.0/
Objects/
boolobject.c
       1  /* Boolean type, a subtype of int */
       2  
       3  #include "Python.h"
       4  #include "pycore_object.h"      // _Py_FatalRefcountError()
       5  #include "pycore_long.h"        // FALSE_TAG TRUE_TAG
       6  #include "pycore_runtime.h"       // _Py_ID()
       7  
       8  #include <stddef.h>
       9  
      10  /* We define bool_repr to return "False" or "True" */
      11  
      12  static PyObject *
      13  bool_repr(PyObject *self)
      14  {
      15      PyObject *res = self == Py_True ? &_Py_ID(True) : &_Py_ID(False);
      16      return Py_NewRef(res);
      17  }
      18  
      19  /* Function to return a bool from a C long */
      20  
      21  PyObject *PyBool_FromLong(long ok)
      22  {
      23      return ok ? Py_True : Py_False;
      24  }
      25  
      26  /* We define bool_new to always return either Py_True or Py_False */
      27  
      28  static PyObject *
      29  bool_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
      30  {
      31      PyObject *x = Py_False;
      32      long ok;
      33  
      34      if (!_PyArg_NoKeywords("bool", kwds))
      35          return NULL;
      36      if (!PyArg_UnpackTuple(args, "bool", 0, 1, &x))
      37          return NULL;
      38      ok = PyObject_IsTrue(x);
      39      if (ok < 0)
      40          return NULL;
      41      return PyBool_FromLong(ok);
      42  }
      43  
      44  static PyObject *
      45  bool_vectorcall(PyObject *type, PyObject * const*args,
      46                  size_t nargsf, PyObject *kwnames)
      47  {
      48      long ok = 0;
      49      if (!_PyArg_NoKwnames("bool", kwnames)) {
      50          return NULL;
      51      }
      52  
      53      Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
      54      if (!_PyArg_CheckPositional("bool", nargs, 0, 1)) {
      55          return NULL;
      56      }
      57  
      58      assert(PyType_Check(type));
      59      if (nargs) {
      60          ok = PyObject_IsTrue(args[0]);
      61          if (ok < 0) {
      62              return NULL;
      63          }
      64      }
      65      return PyBool_FromLong(ok);
      66  }
      67  
      68  /* Arithmetic operations redefined to return bool if both args are bool. */
      69  
      70  static PyObject *
      71  bool_invert(PyObject *v)
      72  {
      73      if (PyErr_WarnEx(PyExc_DeprecationWarning,
      74                       "Bitwise inversion '~' on bool is deprecated. This "
      75                       "returns the bitwise inversion of the underlying int "
      76                       "object and is usually not what you expect from negating "
      77                       "a bool. Use the 'not' operator for boolean negation or "
      78                       "~int(x) if you really want the bitwise inversion of the "
      79                       "underlying int.",
      80                       1) < 0) {
      81          return NULL;
      82      }
      83      return PyLong_Type.tp_as_number->nb_invert(v);
      84  }
      85  
      86  static PyObject *
      87  bool_and(PyObject *a, PyObject *b)
      88  {
      89      if (!PyBool_Check(a) || !PyBool_Check(b))
      90          return PyLong_Type.tp_as_number->nb_and(a, b);
      91      return PyBool_FromLong((a == Py_True) & (b == Py_True));
      92  }
      93  
      94  static PyObject *
      95  bool_or(PyObject *a, PyObject *b)
      96  {
      97      if (!PyBool_Check(a) || !PyBool_Check(b))
      98          return PyLong_Type.tp_as_number->nb_or(a, b);
      99      return PyBool_FromLong((a == Py_True) | (b == Py_True));
     100  }
     101  
     102  static PyObject *
     103  bool_xor(PyObject *a, PyObject *b)
     104  {
     105      if (!PyBool_Check(a) || !PyBool_Check(b))
     106          return PyLong_Type.tp_as_number->nb_xor(a, b);
     107      return PyBool_FromLong((a == Py_True) ^ (b == Py_True));
     108  }
     109  
     110  /* Doc string */
     111  
     112  PyDoc_STRVAR(bool_doc,
     113  "bool(x) -> bool\n\
     114  \n\
     115  Returns True when the argument x is true, False otherwise.\n\
     116  The builtins True and False are the only two instances of the class bool.\n\
     117  The class bool is a subclass of the class int, and cannot be subclassed.");
     118  
     119  /* Arithmetic methods -- only so we can override &, |, ^. */
     120  
     121  static PyNumberMethods bool_as_number = {
     122      0,                          /* nb_add */
     123      0,                          /* nb_subtract */
     124      0,                          /* nb_multiply */
     125      0,                          /* nb_remainder */
     126      0,                          /* nb_divmod */
     127      0,                          /* nb_power */
     128      0,                          /* nb_negative */
     129      0,                          /* nb_positive */
     130      0,                          /* nb_absolute */
     131      0,                          /* nb_bool */
     132      (unaryfunc)bool_invert,     /* nb_invert */
     133      0,                          /* nb_lshift */
     134      0,                          /* nb_rshift */
     135      bool_and,                   /* nb_and */
     136      bool_xor,                   /* nb_xor */
     137      bool_or,                    /* nb_or */
     138      0,                          /* nb_int */
     139      0,                          /* nb_reserved */
     140      0,                          /* nb_float */
     141      0,                          /* nb_inplace_add */
     142      0,                          /* nb_inplace_subtract */
     143      0,                          /* nb_inplace_multiply */
     144      0,                          /* nb_inplace_remainder */
     145      0,                          /* nb_inplace_power */
     146      0,                          /* nb_inplace_lshift */
     147      0,                          /* nb_inplace_rshift */
     148      0,                          /* nb_inplace_and */
     149      0,                          /* nb_inplace_xor */
     150      0,                          /* nb_inplace_or */
     151      0,                          /* nb_floor_divide */
     152      0,                          /* nb_true_divide */
     153      0,                          /* nb_inplace_floor_divide */
     154      0,                          /* nb_inplace_true_divide */
     155      0,                          /* nb_index */
     156  };
     157  
     158  static void
     159  bool_dealloc(PyObject *boolean)
     160  {
     161      /* This should never get called, but we also don't want to SEGV if
     162       * we accidentally decref Booleans out of existence. Instead,
     163       * since bools are immortal, re-set the reference count.
     164       */
     165      _Py_SetImmortal(boolean);
     166  }
     167  
     168  /* The type object for bool.  Note that this cannot be subclassed! */
     169  
     170  PyTypeObject PyBool_Type = {
     171      PyVarObject_HEAD_INIT(&PyType_Type, 0)
     172      "bool",
     173      offsetof(struct _longobject, long_value.ob_digit),  /* tp_basicsize */
     174      sizeof(digit),                              /* tp_itemsize */
     175      bool_dealloc,                               /* tp_dealloc */
     176      0,                                          /* tp_vectorcall_offset */
     177      0,                                          /* tp_getattr */
     178      0,                                          /* tp_setattr */
     179      0,                                          /* tp_as_async */
     180      bool_repr,                                  /* tp_repr */
     181      &bool_as_number,                            /* tp_as_number */
     182      0,                                          /* tp_as_sequence */
     183      0,                                          /* tp_as_mapping */
     184      0,                                          /* tp_hash */
     185      0,                                          /* tp_call */
     186      0,                                          /* tp_str */
     187      0,                                          /* tp_getattro */
     188      0,                                          /* tp_setattro */
     189      0,                                          /* tp_as_buffer */
     190      Py_TPFLAGS_DEFAULT,                         /* tp_flags */
     191      bool_doc,                                   /* tp_doc */
     192      0,                                          /* tp_traverse */
     193      0,                                          /* tp_clear */
     194      0,                                          /* tp_richcompare */
     195      0,                                          /* tp_weaklistoffset */
     196      0,                                          /* tp_iter */
     197      0,                                          /* tp_iternext */
     198      0,                                          /* tp_methods */
     199      0,                                          /* tp_members */
     200      0,                                          /* tp_getset */
     201      &PyLong_Type,                               /* tp_base */
     202      0,                                          /* tp_dict */
     203      0,                                          /* tp_descr_get */
     204      0,                                          /* tp_descr_set */
     205      0,                                          /* tp_dictoffset */
     206      0,                                          /* tp_init */
     207      0,                                          /* tp_alloc */
     208      bool_new,                                   /* tp_new */
     209      .tp_vectorcall = bool_vectorcall,
     210  };
     211  
     212  /* The objects representing bool values False and True */
     213  
     214  struct _longobject _Py_FalseStruct = {
     215      PyObject_HEAD_INIT(&PyBool_Type)
     216      { .lv_tag = _PyLong_FALSE_TAG,
     217          { 0 }
     218      }
     219  };
     220  
     221  struct _longobject _Py_TrueStruct = {
     222      PyObject_HEAD_INIT(&PyBool_Type)
     223      { .lv_tag = _PyLong_TRUE_TAG,
     224          { 1 }
     225      }
     226  };