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 
9 static PyObject *
bool_repr(PyObject * self)10 bool_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 
PyBool_FromLong(long ok)18 PyObject *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 
32 static PyObject *
bool_new(PyTypeObject * type,PyObject * args,PyObject * kwds)33 bool_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 
48 static PyObject *
bool_vectorcall(PyObject * type,PyObject * const * args,size_t nargsf,PyObject * kwnames)49 bool_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 
74 static PyObject *
bool_and(PyObject * a,PyObject * b)75 bool_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 
82 static PyObject *
bool_or(PyObject * a,PyObject * b)83 bool_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 
90 static PyObject *
bool_xor(PyObject * a,PyObject * b)91 bool_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 
100 PyDoc_STRVAR(bool_doc,
101 "bool(x) -> bool\n\
102 \n\
103 Returns True when the argument x is true, False otherwise.\n\
104 The builtins True and False are the only two instances of the class bool.\n\
105 The class bool is a subclass of the class int, and cannot be subclassed.");
106 
107 /* Arithmetic methods -- only so we can override &, |, ^. */
108 
109 static 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 
146 static void _Py_NO_RETURN
bool_dealloc(PyObject * Py_UNUSED (ignore))147 bool_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 
154 PyTypeObject 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 
198 struct _longobject _Py_FalseStruct = {
199     PyVarObject_HEAD_INIT(&PyBool_Type, 0)
200     { 0 }
201 };
202 
203 struct _longobject _Py_TrueStruct = {
204     PyVarObject_HEAD_INIT(&PyBool_Type, 1)
205     { 1 }
206 };
207