<ulclass="toc"><li><ahref="2-bl.html#SP1">§1. Introduction</a></li><li><ahref="2-bl.html#SP4">§4. Creation</a></li><li><ahref="2-bl.html#SP5">§5. Addition</a></li><li><ahref="2-bl.html#SP6">§6. Removal</a></li><li><ahref="2-bl.html#SP7">§7. Scanning lists for their contents</a></li><li><ahref="2-bl.html#SP8">§8. Compilation of rule definitions for rulebook</a></li></ul><hrclass="tocbar">
<pclass="commentary firstcommentary"><aid="SP1"class="paragraph-anchor"></a><b>§1. Introduction. </b>Bookings are intended to be bound together in linked lists, each of which
represents the interior pages of a single rulebook.
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">struct</span><spanclass="plain-syntax"></span><spanclass="reserved-syntax">booking</span><spanclass="plain-syntax"> *</span><spanclass="identifier-syntax">list_head</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> the dummy entry at the front</span>
<ulclass="endnotetexts"><li>The structure booking_list is private to this section.</li></ul>
<pclass="commentary firstcommentary"><aid="SP2"class="paragraph-anchor"></a><b>§2. </b>There are only three operations on lists: creation, addition of a booking,
and removal of a booking. The following invariants are preserved:
</p>
<ulclass="items"><li>(a) The list head is a dummy, i.e., meaningless, booking which has never been
the subject of any addition operation and has never moved.
</li><li>(b) The only <spanclass="extract"><spanclass="extract-syntax">FIRST_PLACEMENT</span></span> entries in the list immediately follow the list
head. Those which were added explicitly as first-placed are in reverse order
of addition to the list.
</li><li>(c) The only <spanclass="extract"><spanclass="extract-syntax">LAST_PLACEMENT</span></span> entries in the list are at the end. Those which
were added explicitly as last-placed are in order of addition to the list.
</li><li>(d) If R and S are middle-placed rules which were placed in the list within
the same range (say, both anywhere, or both "after T" or "before U") and R
precedes S, then either R is more specific than S, or they are equally specific
and R was added to the list before S.
</li><li>(e) The list never contains duplicates, that is, never contains two bookings
whose rules are equal, in the sense of <ahref="2-rls.html#SP13"class="internal">Rules::eq</a>.
</li></ul>
<pclass="commentary firstcommentary"><aid="SP3"class="paragraph-anchor"></a><b>§3. </b>These macros are useful for iterating through the contents in sequence;
note that <spanclass="extract"><spanclass="extract-syntax">br</span></span> is never equal to the dummy head, and that <spanclass="extract"><spanclass="extract-syntax">pr</span></span> is never <spanclass="extract"><spanclass="extract-syntax">NULL</span></span>—
though it is initially equal to the dummy, which of course is the point of
<pclass="commentary firstcommentary"><aid="SP5"class="paragraph-anchor"></a><b>§5. Addition. </b>The following is called when a booking <spanclass="extract"><spanclass="extract-syntax">br</span></span> for the rule R needs to be placed
into list <spanclass="extract"><spanclass="extract-syntax">L</span></span>, which is the contents of a rulebook we will call B. This happens,
for example, in response to an an assertion like "R is listed after S in B";
in that cast the <spanclass="extract"><spanclass="extract-syntax">side</span></span> would be <spanclass="extract"><spanclass="extract-syntax">AFTER_SIDE</span></span>, and the <spanclass="extract"><spanclass="extract-syntax">ref_rule</span></span> would be S.
</p>
<pclass="commentary">It is also possible to specify a <spanclass="extract"><spanclass="extract-syntax">placing</span></span>. For example, for a rule described
as "First every turn rule: ...", this would be added to the every turn rulebook
with placing <spanclass="extract"><spanclass="extract-syntax">FIRST_PLACEMENT</span></span>. There are three possible placings: see <ahref="2-rb.html#SP1"class="internal">booking</a>
for what they are.
</p>
<pclass="commentary">And since there are four possible sides, the following function effectively has
12 different modes to get right.
</p>
<pclass="commentary">Each "addition" leaves the list either the same size or longer by 1.
</p>
<preclass="definitions code-font"><spanclass="definition-keyword">define</span><spanclass="constant-syntax">BEFORE_SIDE</span><spanclass="plain-syntax"> -1 </span><spanclass="comment-syntax"> before the reference rule</span>
<spanclass="definition-keyword">define</span><spanclass="constant-syntax">IN_SIDE</span><spanclass="plain-syntax"></span><spanclass="constant-syntax">0</span><spanclass="plain-syntax"></span><spanclass="comment-syntax"> if no mention is made of where to put the new booking</span>
<spanclass="definition-keyword">define</span><spanclass="constant-syntax">AFTER_SIDE</span><spanclass="plain-syntax"></span><spanclass="constant-syntax">1</span><spanclass="plain-syntax"></span><spanclass="comment-syntax"> after the reference rule</span>
<spanclass="definition-keyword">define</span><spanclass="constant-syntax">INSTEAD_SIDE</span><spanclass="plain-syntax"></span><spanclass="constant-syntax">2</span><spanclass="plain-syntax"></span><spanclass="comment-syntax"> in place of the reference rule</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_1"class="named-paragraph-link"><spanclass="named-paragraph">Make some sanity checks on the addition instructions</span><spanclass="named-paragraph-number">5.1</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_2"class="named-paragraph-link"><spanclass="named-paragraph">Handle the case where the new rule is already in the list</span><spanclass="named-paragraph-number">5.2</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_3"class="named-paragraph-link"><spanclass="named-paragraph">Handle all placements made with the INSTEAD side</span><spanclass="named-paragraph-number">5.3</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_4"class="named-paragraph-link"><spanclass="named-paragraph">Handle all placements made with the FIRST placement</span><spanclass="named-paragraph-number">5.4</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_5"class="named-paragraph-link"><spanclass="named-paragraph">Handle all placements made with the LAST placement</span><spanclass="named-paragraph-number">5.5</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_6"class="named-paragraph-link"><spanclass="named-paragraph">Handle what's left: MIDDLE placements on the IN, BEFORE or AFTER sides</span><spanclass="named-paragraph-number">5.6</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax">}</span>
</pre>
<pclass="commentary firstcommentary"><aid="SP5_1"class="paragraph-anchor"></a><b>§5.1. </b><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Make some sanity checks on the addition instructions</span><spanclass="named-paragraph-number">5.1</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">internal_error</span><spanclass="plain-syntax">(</span><spanclass="string-syntax">"tried to add before or after or instead of non-rule"</span><spanclass="plain-syntax">);</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">internal_error</span><spanclass="plain-syntax">(</span><spanclass="string-syntax">"tried to add in middle but with ref rule"</span><spanclass="plain-syntax">);</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">internal_error</span><spanclass="plain-syntax">(</span><spanclass="string-syntax">"tried to add before or after but with non-middle placement"</span><spanclass="plain-syntax">);</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">internal_error</span><spanclass="plain-syntax">(</span><spanclass="string-syntax">"tried to add rule to null list"</span><spanclass="plain-syntax">);</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">default:</span><spanclass="plain-syntax"></span><spanclass="identifier-syntax">internal_error</span><spanclass="plain-syntax">(</span><spanclass="string-syntax">"invalid placing of rule"</span><spanclass="plain-syntax">);</span>
<spanclass="plain-syntax"> }</span>
</pre>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5">§5</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_2"class="paragraph-anchor"></a><b>§5.2. </b>If R is already in B, the assertion may still have an effect.
</p>
<pclass="commentary">If our instructions specify no particular position for R to take, we return
because nothing need be done: the rule's there already, so be happy. Otherwise,
we remove R's existing booking in order that it can be rebooked in a new position.
</p>
<pclass="commentary">This is a change in semantics from the original Inform 7 design for rulebooks,
under which a rule could be booked multiple times in the same rulebook — which
was then called "duplication". Following debate on the Usenet newsgroup
<spanclass="extract"><spanclass="extract-syntax">rec.arts.int-fiction</span></span> in February and March 2009, it was decided to abolish
duplication in favour of the clean principle that a rule can only be in a
single rulebook once. This makes it easier to place rules with tricky preambles,
though there were arguments on both sides.
</p>
<pclass="commentary"><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Handle the case where the new rule is already in the list</span><spanclass="named-paragraph-number">5.2</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">LOGIF</span><spanclass="plain-syntax">(</span><spanclass="identifier-syntax">RULE_ATTACHMENTS</span><spanclass="plain-syntax">, </span><spanclass="string-syntax">"Removing previous entry from rulebook\n"</span><spanclass="plain-syntax">);</span>
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">break</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> rule can only appear once, so no need to keep checking</span>
<spanclass="plain-syntax"> }</span>
</pre>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5">§5</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_3"class="paragraph-anchor"></a><b>§5.3. </b><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Handle all placements made with the INSTEAD side</span><spanclass="named-paragraph-number">5.3</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">new_br</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">placement</span><spanclass="plain-syntax"> = </span><spanclass="identifier-syntax">pos</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">placement</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> replace with same placement</span>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5">§5</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_4"class="paragraph-anchor"></a><b>§5.4. </b>If we insert a rule as first-placed rule when there already is a first-placed
rule, the new one displaces it to go first, but both continue to be labelled as
having <spanclass="extract"><spanclass="extract-syntax">FIRST_PLACEMENT</span></span>, so that subsequent rule insertions of middle-placed rules
will still go after both of them.
</p>
<pclass="commentary"><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Handle all placements made with the FIRST placement</span><spanclass="named-paragraph-number">5.4</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">if</span><spanclass="plain-syntax"> (</span><spanclass="identifier-syntax">placing</span><spanclass="plain-syntax"> == </span><spanclass="constant-syntax">FIRST_PLACEMENT</span><spanclass="plain-syntax">) { </span><spanclass="comment-syntax"> first in valid interval (must be whole list)</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">new_br</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">next_booking</span><spanclass="plain-syntax"> = </span><spanclass="identifier-syntax">previously_first</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> pushes any existing first rule forward</span>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5">§5</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_5"class="paragraph-anchor"></a><b>§5.5. </b>Symmetrically, a second last-placed rule is inserted after any existing one, but
both are labelled as having <spanclass="extract"><spanclass="extract-syntax">LAST_PLACEMENT</span></span>.
</p>
<pclass="commentary"><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Handle all placements made with the LAST placement</span><spanclass="named-paragraph-number">5.5</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">if</span><spanclass="plain-syntax"> (</span><spanclass="identifier-syntax">placing</span><spanclass="plain-syntax"> == </span><spanclass="constant-syntax">LAST_PLACEMENT</span><spanclass="plain-syntax">) { </span><spanclass="comment-syntax"> last in valid interval (must be whole list)</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">prev</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">next_booking</span><spanclass="plain-syntax"> = </span><spanclass="identifier-syntax">new_br</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> pushes any existing last rule backward</span>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5">§5</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_6"class="paragraph-anchor"></a><b>§5.6. </b><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Handle what's left: MIDDLE placements on the IN, BEFORE or AFTER sides</span><spanclass="named-paragraph-number">5.6</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">booking</span><spanclass="plain-syntax"> *</span><spanclass="identifier-syntax">start_rule</span><spanclass="plain-syntax"> = </span><spanclass="identifier-syntax">L</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">list_head</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> valid interval begins after this rule</span>
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">booking</span><spanclass="plain-syntax"> *</span><spanclass="identifier-syntax">end_rule</span><spanclass="plain-syntax"> = </span><spanclass="identifier-syntax">NULL</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> valid interval ends before this rule, or runs to end if </span><spanclass="extract"><spanclass="extract-syntax">NULL</span></span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_6_1"class="named-paragraph-link"><spanclass="named-paragraph">Adjust the valid interval to take care of BEFORE and AFTER side requirements</span><spanclass="named-paragraph-number">5.6.1</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_6_2"class="named-paragraph-link"><spanclass="named-paragraph">Check that the valid interval is indeed as advertised</span><spanclass="named-paragraph-number">5.6.2</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="reserved-syntax">booking</span><spanclass="plain-syntax"> *</span><spanclass="identifier-syntax">insert_after</span><spanclass="plain-syntax"> = </span><spanclass="identifier-syntax">start_rule</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> insertion point is after this</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_6_3"class="named-paragraph-link"><spanclass="named-paragraph">Find insertion point, keeping the valid interval in specificity order</span><spanclass="named-paragraph-number">5.6.3</span></a></span><spanclass="plain-syntax">;</span>
<spanclass="plain-syntax"></span><spanclass="named-paragraph-container code-font"><ahref="2-bl.html#SP5_6_4"class="named-paragraph-link"><spanclass="named-paragraph">Set the placement for the new rule booking</span><spanclass="named-paragraph-number">5.6.4</span></a></span><spanclass="plain-syntax">;</span>
</pre>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5">§5</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_6_1"class="paragraph-anchor"></a><b>§5.6.1. </b><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Adjust the valid interval to take care of BEFORE and AFTER side requirements</span><spanclass="named-paragraph-number">5.6.1</span></span><spanclass="comment-syntax"> =</span>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5_6">§5.6</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_6_2"class="paragraph-anchor"></a><b>§5.6.2. </b><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Check that the valid interval is indeed as advertised</span><spanclass="named-paragraph-number">5.6.2</span></span><spanclass="comment-syntax"> =</span>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5_6">§5.6</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_6_3"class="paragraph-anchor"></a><b>§5.6.3. </b><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Find insertion point, keeping the valid interval in specificity order</span><spanclass="named-paragraph-number">5.6.3</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax">&& (</span><spanclass="identifier-syntax">insert_after</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">next_booking</span><spanclass="plain-syntax">-></span><spanclass="element-syntax">placement</span><spanclass="plain-syntax"> != </span><spanclass="constant-syntax">LAST_PLACEMENT</span><spanclass="plain-syntax">) </span><spanclass="comment-syntax"> or reaches a last rule</span>
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">log</span><spanclass="plain-syntax">) >= </span><spanclass="constant-syntax">0</span><spanclass="plain-syntax">)) </span><spanclass="comment-syntax"> or a rule less specific than the new one</span>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5_6">§5.6</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP5_6_4"class="paragraph-anchor"></a><b>§5.6.4. </b>Since this part of the algorithm is used only when we've requested MIDDLE
placement, it might seem that <spanclass="extract"><spanclass="extract-syntax">new_br->placement</span></span> should always be set to
that. This does indeed mostly happen, but not always. To preserve rulebook
invariants (b) and (c), we need to force anything added after a LAST rule
to be LAST as well, and similarly for FIRSTs. (This will only happen in
cases where the source text called for placements AFTER a LAST rule, or
BEFORE a FIRST one.)
</p>
<pclass="commentary"><spanclass="named-paragraph-container code-font"><spanclass="named-paragraph-defn">Set the placement for the new rule booking</span><spanclass="named-paragraph-number">5.6.4</span></span><spanclass="comment-syntax"> =</span>
<spanclass="plain-syntax"></span><spanclass="constant-syntax">LAST_PLACEMENT</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> happens if valid interval is after a last rule</span>
<spanclass="plain-syntax"></span><spanclass="constant-syntax">FIRST_PLACEMENT</span><spanclass="plain-syntax">; </span><spanclass="comment-syntax"> happens if valid interval is before a first rule</span>
</pre>
<ulclass="endnotetexts"><li>This code is used in <ahref="2-bl.html#SP5_6">§5.6</a>.</li></ul>
<pclass="commentary firstcommentary"><aid="SP6"class="paragraph-anchor"></a><b>§6. Removal. </b>This is much simpler, since it doesn't disturb the ordering:
<pclass="commentary firstcommentary"><aid="SP8"class="paragraph-anchor"></a><b>§8. Compilation of rule definitions for rulebook. </b>There's no real need to do so, but we compile rule definitions in rulebook
order to make the compiled code more legible, and for the same reason we add
<spanclass="plain-syntax"></span><spanclass="identifier-syntax">WRITE_TO</span><spanclass="plain-syntax">(</span><spanclass="identifier-syntax">C</span><spanclass="plain-syntax">, </span><spanclass="string-syntax">"--- now the "</span><spanclass="plain-syntax">);</span>