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