xref: /third_party/python/Objects/boolobject.c (revision 7db96d56)
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