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