1=================
2Development Guide
3=================
4
5This document gives an overview of the code in `boolean.py`, explaining the
6layout and design decisions and some difficult algorithms. All used definitions
7and laws are stated in :doc:`concepts`.
8
9.. contents::
10    :depth: 2
11    :backlinks: top
12
13Testing
14-------
15
16Test `boolean.py` with your current Python environment:
17
18.. code-block:: shell
19
20   python setup.py test
21
22Test with all of the supported Python environments using `tox`:
23
24.. code-block:: shell
25
26   pip install -r test-requirements.txt
27   tox
28
29If `tox` throws `InterpreterNotFound`, limit it to python interpreters that are actually installed on your machine:
30
31.. code-block:: shell
32
33   tox -e py27,py36
34
35Classes Hierarchy
36-----------------
37..
38    boolean.boolean.BooleanAlgebra
39    boolean.boolean.Expression
40        boolean.boolean.BaseElement
41            boolean.boolean._TRUE
42            boolean.boolean._FALSE
43        boolean.boolean.Symbol
44        boolean.boolean.Function
45            boolean.boolean.NOT
46            boolean.boolean.DualBase
47                boolean.boolean.AND
48                boolean.boolean.OR
49
50
51
52Expression
53^^^^^^^^^^
54..
55    .. autoclass:: boolean.boolean.Expression
56
57Symbol
58^^^^^^
59..
60    .. autoclass:: boolean.boolean.Symbol
61
62Function
63^^^^^^^^
64..
65    .. autoclass:: boolean.boolean.Function
66
67NOT
68^^^
69..
70    .. autoclass:: boolean.boolean.NOT
71
72AND
73^^^
74..
75    .. autoclass:: boolean.boolean.AND
76
77OR
78^^
79..
80    .. autoclass:: boolean.boolean.OR
81
82
83.. _class-creation:
84
85Class creation
86--------------
87
88Except for BooleanAlgebra and Symbol, no other classes are is designed to be instantiated directly.
89Instead you should create a BooleanAlgebra instance, then use  BooleanAlgebra.symbol,
90BooleanAlgebra.NOT, BooleanAlgebra.AND, BooleanAlgebra.OR BooleanAlgebra.TRUE and BooleanAlgebra.FALSE
91to compose your expressions in the context of this algebra.
92
93
94.. _class-initialization:
95
96Class initialization
97--------------------
98
99In this section for all classes is stated which arguments they will accept
100and how these arguments are processed before they are used.
101
102Symbol
103^^^^^^
104
105& :obj:`obj` (Named Symbol)
106
107
108Ordering
109--------
110
111As far as possible every expression should always be printed in exactly the
112same way. Therefore a strict ordering between different boolean classes and
113between instances of same classes is needed. This is defined primarily by the
114sort_order attribute.
115
116
117Class ordering
118^^^^^^^^^^^^^^
119
120:class:`BaseElement` < :class:`Symbol` < :class:`AND` <  :class:`OR`
121
122:class:`NOT` is an exception in this scheme. It will be sorted based on the sort order of its
123argument.
124
125Class ordering is implemented by an attribute :attr:`sort_order` in all
126relevant classes. It holds an integer that will be used for comparison
127if it is available in both compared objects.
128For Symbols, the attached `obj` object is used instead.
129
130+----------------------+-----------+
131|    :class:`Class`    | sort_order|
132+======================+===========+
133| :class:`BaseElement` |    0      |
134+----------------------+-----------+
135| :class:`Symbol`      |    5      |
136+----------------------+-----------+
137| :class:`AND`         |    10     |
138+----------------------+-----------+
139| :class:`OR`          |    25     |
140+----------------------+-----------+
141
142Instance ordering
143^^^^^^^^^^^^^^^^^
144
145:class:`BaseElement`
146    :obj:`FALSE` < :obj:`TRUE`
147
148:class:`Symbol`
149
150    :obj:`Symbol.obj` o  :obj:`Symbol.obj`
151
152:class:`NOT`
153    if :obj:`NOT.args[0]` == :obj:`other` ---> :obj:`other` < :obj:`NOT`
154
155    :obj:`NOT` o :obj:`other` ---> :obj:`NOT.args[0]` o :obj:`other`
156
157:class:`AND`
158    :obj:`AND` o :obj:`AND` ---> :obj:`AND.args[0]` o :obj:`AND.args[0]`
159
160    if undecided: repeat for all args
161
162    if undecided: len(:obj:`AND.args`) o len(:obj:`AND.args`)
163
164    if undecided: return :obj:`AND` < :obj:`AND`
165
166:class:`OR`
167    :obj:`OR` o :obj:`OR` ---> :obj:`OR.args[0]` o :obj:`OR.args[0]`
168
169    if undecided: repeat for all args
170
171    if undecided: len(:obj:`OR.args`) o len(:obj:`OR.args`)
172
173    if undecided: return :obj:`OR` < :obj:`OR`
174
175
176Parsing
177-------
178
179Parsing is done in two steps:
180A tokenizer iterates over string characters assigning a TOKEN_TYPE to each token.
181The parser receives this stream of token types and strings and creates
182adequate boolean objects from a parse tree.
183
184