diff --git a/docs/assertions-module/1-am.html b/docs/assertions-module/1-am.html
index 8a7e72f31..23a3c4d57 100644
--- a/docs/assertions-module/1-am.html
+++ b/docs/assertions-module/1-am.html
@@ -82,18 +82,18 @@ which use this module:
enumRELATION_DEFINITIONS_DA
diff --git a/docs/assertions-module/2-ar.html b/docs/assertions-module/2-ar.html
index d148bc38f..5cdfa6fad 100644
--- a/docs/assertions-module/2-ar.html
+++ b/docs/assertions-module/2-ar.html
@@ -234,7 +234,7 @@ conclusion we would have reached.
}
diff --git a/docs/assertions-module/2-bv.html b/docs/assertions-module/2-bv.html
index abb65b312..7ec3494ab 100644
--- a/docs/assertions-module/2-bv.html
+++ b/docs/assertions-module/2-bv.html
@@ -297,7 +297,7 @@ other languages may as well drop the hyphens.
diff --git a/docs/assertions-module/2-cs.html b/docs/assertions-module/2-cs.html
index c37948b08..809df713f 100644
--- a/docs/assertions-module/2-cs.html
+++ b/docs/assertions-module/2-cs.html
@@ -438,7 +438,7 @@ property of something.
}
diff --git a/docs/assertions-module/2-is.html b/docs/assertions-module/2-is.html
index 80a5483f4..b792193a1 100644
--- a/docs/assertions-module/2-is.html
+++ b/docs/assertions-module/2-is.html
@@ -100,7 +100,7 @@ therefore safely be used to sweep up any voidImperativeSubtrees::accept(parse_node *p) {ImperativeSubtrees::accept_inner(p, TRUE);}
-voidImperativeSubtrees::accept_body(parse_node *p) {
+voidImperativeSubtrees::accept_body(parse_node *p) {ImperativeSubtrees::accept_inner(p, FALSE);}
@@ -123,7 +123,7 @@ therefore safely be used to sweep up any worry about the preamble in the node pif (accept_header)Node::set_impdef(header,
-ImperativeDefinitions::make_imperative_definition(header));
+ImperativeDefinitions::make_imperative_definition(header)); }}
@@ -1034,7 +1034,7 @@ where we look for such mistakes.
-voidImperativeSubtrees::police_code_block(parse_node *block, control_structure_phrase *context) {
+voidImperativeSubtrees::police_code_block(parse_node *block, control_structure_phrase *context) {for (parse_node *p = block->down, *prev_p = NULL; p; prev_p = p, p = p->next) {current_sentence = p;
@@ -1217,7 +1217,7 @@ to issue good problem messages for failures to use "otherwise if" correctly.
diff --git a/docs/assertions-module/2-ptmn.html b/docs/assertions-module/2-ptmn.html
index 063a6e37c..517b181e5 100644
--- a/docs/assertions-module/2-ptmn.html
+++ b/docs/assertions-module/2-ptmn.html
@@ -123,7 +123,7 @@ but saves a deal of passing parameters around.
if (pass == 2) Extend the pass to sentences needed when implicit kinds are set2.2;}
-
The structure pass_state is accessed in 2/ar, 3/tr, 3/uor, 3/dbtr, 4/ass, 4/ass2, 5/tc and here.
+
The structure pass_state is accessed in 2/ar, 3/tr, 3/uor, 3/dbtr, 4/ass, 4/ass2, 6/tc and here.
§2.1. Extend the pass to invented sentences from kinds2.1 =
@@ -214,9 +214,9 @@ organisation, and are not directly functional in themselves.
caseSENTENCE_NT:Pass through a SENTENCE node3.1.2; break;caseTRACE_NT:Pass through a TRACE node3.1.5; break;
-caseTABLE_NT:if (global_pass_state.pass == 0) Tables::create_table(p);
+caseTABLE_NT:if (global_pass_state.pass == 0) Tables::create_table(p);break;
-caseEQUATION_NT:if (global_pass_state.pass == 0) Equations::new_at(p, FALSE);
+caseEQUATION_NT:if (global_pass_state.pass == 0) Equations::new_at(p, FALSE);break;caseINFORM6CODE_NT:if (global_pass_state.pass == 2) Config::Inclusions::inform_6_inclusion(p);
@@ -328,7 +328,7 @@ two cases") and all others (such as "regular meaning are more subtle").
@@ -387,7 +387,7 @@ followed by double-quoted text is a note for the telemetry file.
}
diff --git a/docs/assertions-module/3-dbtr.html b/docs/assertions-module/3-dbtr.html
index a46eb5bc0..c693cd7eb 100644
--- a/docs/assertions-module/3-dbtr.html
+++ b/docs/assertions-module/3-dbtr.html
@@ -240,7 +240,7 @@ whatever was named in column 1: see below.
K = Kinds::weaken(K, K_object);if (!(Kinds::Behaviour::is_object(K))) RTKinds::set_defined_by_table(K, t);t->kind_defined_in_this_table = K;
-Tables::Columns::set_kind(t->columns[0].column_identity, t, K);
+Tables::Columns::set_kind(t->columns[0].column_identity, t, K);Create values for this kind as enumerated by names in the first column4.1.3;
§4.1.1.1. Issue PM_TableDefiningObject problem4.1.1.1 =
@@ -490,7 +490,7 @@ table: do they get permission as well? We're going to say that they do.
Ensure that a property with the same name as the column name exists4.2.1;if (global_pass_state.pass == 1)Assert::true_about(
-Propositions::Abstract::to_provide_property(P),
+Propositions::Abstract::to_provide_property(P),KindSubjects::from_kind(t->kind_defined_in_this_table),prevailing_mood);if (t->contains_property_values_at_run_time)
@@ -513,7 +513,7 @@ table-stocking the column will have a kind for its entries.
<unfortunate-table-column-property>(PW);P = ValueProperties::obtain(PW);if (ValueProperties::kind(P) == NULL) {
-kind *CK = Tables::Columns::get_kind(tc);
+kind *CK = Tables::Columns::get_kind(tc);if ((Kinds::get_construct(CK) == CON_rule) || (Kinds::get_construct(CK) == CON_rulebook)) {kind *K1 = NULL, *K2 = NULL;
@@ -521,7 +521,7 @@ table-stocking the column will have a kind for its entries.
if ((Kinds::eq(K1, K_value)) && (Kinds::eq(K1, K_value))) {CK = Kinds::binary_con(Kinds::get_construct(CK), K_action_name, K_nil);
-Tables::Columns::set_kind(tc, t, CK);
+Tables::Columns::set_kind(tc, t, CK); } }if (CK) ValueProperties::set_kind(P, CK);
@@ -617,7 +617,7 @@ also ordinary sentences about the property value, and the former won't.
diff --git a/docs/assertions-module/3-dlr.html b/docs/assertions-module/3-dlr.html
index 635c03131..7a3cac4ae 100644
--- a/docs/assertions-module/3-dlr.html
+++ b/docs/assertions-module/3-dlr.html
@@ -184,7 +184,7 @@ modifiers and a pointer to a Preform nonterminal if one has been named.
}
diff --git a/docs/assertions-module/3-nar.html b/docs/assertions-module/3-nar.html
index f1ff29590..bbc092dd0 100644
--- a/docs/assertions-module/3-nar.html
+++ b/docs/assertions-module/3-nar.html
@@ -125,7 +125,7 @@ matches:
}
diff --git a/docs/assertions-module/3-nar2.html b/docs/assertions-module/3-nar2.html
index 68369eff3..95ca75bde 100644
--- a/docs/assertions-module/3-nar2.html
+++ b/docs/assertions-module/3-nar2.html
@@ -121,7 +121,7 @@ function togglePopup(material_id) {
}
diff --git a/docs/assertions-module/3-nlpr.html b/docs/assertions-module/3-nlpr.html
index fb813b31e..ef10cb797 100644
--- a/docs/assertions-module/3-nlpr.html
+++ b/docs/assertions-module/3-nlpr.html
@@ -469,7 +469,7 @@ by a bracketed list of up to three options in any order.
}
diff --git a/docs/assertions-module/3-npr.html b/docs/assertions-module/3-npr.html
index 08bbea881..5c250a872 100644
--- a/docs/assertions-module/3-npr.html
+++ b/docs/assertions-module/3-npr.html
@@ -527,7 +527,7 @@ differently as a result.
} elseprn = ConditionsOfSubjects::parse(owner_infs, CNW, the_list, &already_created_instances);Assert::true_about(
-Propositions::Abstract::to_provide_property(prn),
+Propositions::Abstract::to_provide_property(prn),owner_infs, prevailing_mood);
diff --git a/docs/assertions-module/3-nrr.html b/docs/assertions-module/3-nrr.html
index 31e156f81..c0c6a2a86 100644
--- a/docs/assertions-module/3-nrr.html
+++ b/docs/assertions-module/3-nrr.html
@@ -134,7 +134,7 @@ of subsequent sentences, which also happens in the pre-pass.
"this is too long a name for a single relation to have","and would become unwieldy.");elseNode::set_new_relation_here(V->next,
-Relations::Explicit::make_pair_sketchily(
+Relations::Explicit::make_pair_sketchily(WordAssemblages::from_wording(RW)));returnTRUE; }
@@ -170,7 +170,7 @@ and "each other" respectively.
intunique; TRUE for one, FALSE for various, NOT_APPLICABLE if not yet known} relation_request_term;
-
The structure relation_request is accessed in 6/kpr, 6/tap, 6/tcp and here.
The structure relation_request_term is accessed in 6/aa, 6/am, 6/amd and here.
+
The structure relation_request is accessed in 7/kpr, 7/tap, 7/tcp and here.
The structure relation_request_term is accessed in 7/aa, 7/am, 7/amd and here.
§2.2. Syntax on the left (term 0) and right (term 1) slightly differs. The integer
result is a bitmap of these:
diff --git a/docs/assertions-module/3-nvr.html b/docs/assertions-module/3-nvr.html
index e5c1ed8ff..c7f043e0c 100644
--- a/docs/assertions-module/3-nvr.html
+++ b/docs/assertions-module/3-nvr.html
@@ -674,7 +674,7 @@ in the case of ambiguity, with lower numbers preferred. See
diff --git a/docs/assertions-module/3-pr.html b/docs/assertions-module/3-pr.html
index 626eedc0e..1801125bd 100644
--- a/docs/assertions-module/3-pr.html
+++ b/docs/assertions-module/3-pr.html
@@ -149,7 +149,7 @@ text anyway, so the following problem messages are not too gratuitous.
diff --git a/docs/assertions-module/3-rpr.html b/docs/assertions-module/3-rpr.html
index 70fa54de9..b284aed1e 100644
--- a/docs/assertions-module/3-rpr.html
+++ b/docs/assertions-module/3-rpr.html
@@ -559,7 +559,7 @@ a given rule appears in, and (within limits) where. A simple example:
diff --git a/docs/assertions-module/3-uor.html b/docs/assertions-module/3-uor.html
index b67e4545e..ff47b151d 100644
--- a/docs/assertions-module/3-uor.html
+++ b/docs/assertions-module/3-uor.html
@@ -211,7 +211,7 @@ since the compiler next down the chain may no longer be I6.
diff --git a/docs/assertions-module/4-ass2.html b/docs/assertions-module/4-ass2.html
index 1af0738a3..97f0197cb 100644
--- a/docs/assertions-module/4-ass2.html
+++ b/docs/assertions-module/4-ass2.html
@@ -128,7 +128,7 @@ generalisations which apply to it.
CLASS_DEFINITION} generalisation;
-
The structure generalisation is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/imp, 5/tbl, 5/eqt, 6/tcp, 6/cu and here.
+
The structure generalisation is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/imp, 5/adf, 6/tbl, 6/eqt, 7/tcp, 7/cu and here.
§3. For reasons to do with timing, each object needs to keep track of which
generalisations have and have not yet applied to it. In practice, this is
a list of pairs \((K, g)\) where \(K\) is a kind and \(g\) is the most recent one
@@ -142,7 +142,7 @@ applied from \(K\)'s list.
structapplication *next;} application;
-
The structure application is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/imp, 5/tbl, 5/eqt, 6/tcp, 6/cu and here.
+
The structure application is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/imp, 5/adf, 6/tbl, 6/eqt, 7/tcp, 7/cu and here.
§4. These structures are combined in the following packet of data attached to
each inference subject:
@@ -511,7 +511,7 @@ machinery is in infinite regress, e.g., because each \(K\) must contain an
diff --git a/docs/assertions-module/4-imp.html b/docs/assertions-module/4-imp.html
index 7efb61cd6..d90191aa6 100644
--- a/docs/assertions-module/4-imp.html
+++ b/docs/assertions-module/4-imp.html
@@ -101,7 +101,7 @@ description only, whereas B could be any subtree of an assertion.
intpossession_certainty; ditto} possession_marker;
-
The structure possession_marker is accessed in 6/tap and here.
+
The structure possession_marker is accessed in 7/tap and here.
§3. Implications are gathered during the main parse tree traverses, but all we do
is to store them and sit on them.
@@ -187,7 +187,7 @@ is to store them and sit on them.
diff --git a/docs/assertions-module/4-npa.html b/docs/assertions-module/4-npa.html
index ea0fc3eb7..97884aa72 100644
--- a/docs/assertions-module/4-npa.html
+++ b/docs/assertions-module/4-npa.html
@@ -133,7 +133,7 @@ automatically creates it.
if ((K) && (KindSubjects::has_properties(K) == FALSE))Disallow this kind as a new owner of a value property1.1.1;property *prn = ValueProperties::obtain(Node::get_text(p));
-Assert::true_about(Propositions::Abstract::to_provide_property(prn),
+Assert::true_about(Propositions::Abstract::to_provide_property(prn),owner_infs, prevailing_mood);returnprn;
@@ -294,7 +294,7 @@ several property names, e.g., in
diff --git a/docs/assertions-module/4-rk.html b/docs/assertions-module/4-rk.html
index cc6ba5ad3..ac04474b9 100644
--- a/docs/assertions-module/4-rk.html
+++ b/docs/assertions-module/4-rk.html
@@ -140,7 +140,7 @@ objects or values, but there are two exceptional cases to take care of.
"like 'Here is nothing.': just don't put anything there."); } else {Assert::true_about(
-Propositions::Abstract::to_put_here(),
+Propositions::Abstract::to_put_here(),Node::get_subject(value), prevailing_mood); }return;
@@ -244,7 +244,7 @@ that subtrees \(T_X\) and \(T_Y\), where \(T_X\) is a single value or object and
Impose a tedious restriction on relations between objects and values3.2;Assert::true(
-Propositions::Abstract::to_set_relation(bp, Node::get_subject(px), Node::get_evaluation(px), Node::get_subject(py), Node::get_evaluation(py)),
+Propositions::Abstract::to_set_relation(bp, Node::get_subject(px), Node::get_evaluation(px), Node::get_subject(py), Node::get_evaluation(py)),prevailing_mood);}
@@ -275,7 +275,7 @@ that subtrees \(T_X\) and \(T_Y\), where \(T_X\) is a single value or object and
-if ((Relations::Explicit::relates_values_not_objects(bp)) &&
+if ((Relations::Explicit::relates_values_not_objects(bp)) && (((Node::get_subject(px)) && (KindSubjects::to_kind(Node::get_subject(px)))) || ((Node::get_subject(py)) && (KindSubjects::to_kind(Node::get_subject(py)))))) {StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_KindRelatedToValue),
@@ -306,7 +306,7 @@ that subtrees \(T_X\) and \(T_Y\), where \(T_X\) is a single value or object and
diff --git a/docs/assertions-module/4-rpt.html b/docs/assertions-module/4-rpt.html
index 8696c9cc7..a45ccd3a3 100644
--- a/docs/assertions-module/4-rpt.html
+++ b/docs/assertions-module/4-rpt.html
@@ -96,7 +96,7 @@ in a creation_proposition Make a common or proper noun as appropriate1.1;}
-voidRefiner::give_spec_to_noun(parse_node *p, parse_node *eval) {
+voidRefiner::give_spec_to_noun(parse_node *p, parse_node *eval) {inference_subject *infs = Specifications::to_subject(eval);Make a common or proper noun as appropriate1.1;}
@@ -133,7 +133,7 @@ it probably never needs to be copied, but we do so for safety's sake.)
-voidRefiner::copy_noun_details(parse_node *p_to, parse_node *p_from) {
+voidRefiner::copy_noun_details(parse_node *p_to, parse_node *p_from) {Node::set_type(p_to, Node::get_type(p_from));Node::set_evaluation(p_to, Node::get_evaluation(p_from));Node::set_creation_proposition(p_to, Node::get_creation_proposition(p_from));
@@ -205,9 +205,9 @@ though only if it has a positive sense and has a nominal meaning.
intRefiner::nominalise_adjective(parse_node *p) {if ((p) && (Node::get_type(p) == ADJECTIVE_NT)) {unary_predicate *pred = Node::get_predicate(p);
-if (AdjectivalPredicates::parity(pred) == TRUE) {
-instance *q = AdjectiveAmbiguity::has_enumerative_meaning(
-AdjectivalPredicates::to_adjective(pred));
+if (AdjectivalPredicates::parity(pred) == TRUE) {
+instance *q = AdjectiveAmbiguity::has_enumerative_meaning(
+AdjectivalPredicates::to_adjective(pred));if (q) Refiner::give_spec_to_noun(p, Rvalues::from_instance(q)); } }
@@ -363,7 +363,7 @@ refine them.
-pcalc_prop *prop = Propositions::Abstract::to_create_something(create_as, W);
+pcalc_prop *prop = Propositions::Abstract::to_create_something(create_as, W);pcalc_prop *such_that = Node::get_creation_proposition(governor);if (such_that) prop = Propositions::concatenate(prop, such_that);Assert::true(prop, prevailing_mood);
@@ -1024,7 +1024,7 @@ if nothing has already been said:
-intAssertions::Creator::vet_name(wordingW) {
+intAssertions::Creator::vet_name(wordingW) {if (<creation-problem-diagnosis>(W)) returnFALSE;returnTRUE;}
@@ -1182,7 +1182,7 @@ to a different vehicle object.
Check that the new name is non-empty and distinct from all existing ones7.4.1.2;NW = Wordings::truncate(NW, 32); truncate to the maximum lengthparse_node *pz = Node::new(PROPER_NOUN_NT);
-pcalc_prop *prop = Propositions::Abstract::to_create_something(instance_kind, NW);
+pcalc_prop *prop = Propositions::Abstract::to_create_something(instance_kind, NW);Assert::true(prop, prevailing_mood);new_instance = Instances::as_subject(Instances::latest());if (named_after) {
@@ -1360,14 +1360,14 @@ proposition claiming its existence, then assert it to be true.
inform_language *L;LOOP_OVER(L, inform_language) {pcalc_prop *prop =
-Propositions::Abstract::to_create_something(K, L->instance_name);
+Propositions::Abstract::to_create_something(K, L->instance_name);Assert::true(prop, CERTAIN_CE);L->nl_instance = Instances::latest(); }}
we need to make the pronoun "it" a local variable of kind "container" in the
+stack frame used to compile the "..." part. If it uses a calling, like so:
+
+
+
+
Definition: A container (called the sack) is capacious if: ...
+
+
+
then we also want the name "sack" to refer to this. Here's where we take care
+of it:
+
Each IMPERATIVE node in the syntax tree makes a definition of a phrase or rule.
+
+
§1. When this function starts, the tree contains a number of top-level IMPERATIVE_NT
+nodes with INVOCATION_LIST_NT nodes hanging from them, but we haven't looked at
+any of the text in the IMPERATIVE_NT head nodes and therefore we have no idea what
+they define. Some will be rules, some will define To... phrases, and so on.
+
§9. The rulebooks are now complete and final. It is time to
+compile the Inter code which will provide the run-time definitions of all
+these phrases. This will be a long task, and we can only do most of it now,
+because more phrases will appear later.
+
§9.4. This doesn't compile all adjective definitions, only the ones which supply
+a whole multi-step phrase to define them — a relatively little-used feature
+of Inform.
+
§9.5. As we'll see, it's legal in Inform to define "To..." phrases with vague
+kinds: "To expose (X - a value)", for example. This can't be compiled as
+vaguely as the definition implies, since there would be no way to know how
+to store X. Instead, for each different kind of X which is actually needed,
+a fresh version of the phrase is compiled — one where X is a number, one
+where it's a text, and so on. This is handled by making a "request" for the
+phrase, indicating that a compiled version of it will be needed.
+
+
+
Since "To..." phrases are only compiled on request, we must remember to
+request the boring ones with straightforward kinds ("To award (N - a number)
+points", say). This is where we do it:
+
+
+
Mark To... phrases which have definite kinds for future compilation9.5 =
+
§9.6. Throw problems for phrases with return kinds too vaguely defined9.6 =
+
+
+
+phrase *ph;
+LOOP_OVER(ph, phrase) {
+kind *KR = Phrases::TypeData::get_return_kind(&(ph->type_data));
+if ((Kinds::Behaviour::semidefinite(KR) == FALSE) &&
+ (Phrases::TypeData::arithmetic_operation(ph) == -1)) {
+current_sentence = Phrases::declaration_node(ph);
+Problems::quote_source(1, current_sentence);
+StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ReturnKindVague));
+Problems::issue_problem_segment(
+"The declaration %1 tries to set up a phrase which decides a "
+"value which is too vaguely described. For example, 'To decide "
+"which number is the target: ...' is fine, because 'number' "
+"is clear about what kind of value should emerge; but 'To "
+"decide which value is the target: ...' is not clear enough.");
+Problems::issue_problem_end();
+ }
+for (intk=1; k<=26; k++)
+if ((Kinds::Behaviour::involves_var(KR, k)) &&
+ (Phrases::TypeData::tokens_contain_variable(&(ph->type_data), k) == FALSE)) {
+current_sentence = Phrases::declaration_node(ph);
+TEMPORARY_TEXT(var_letter)
+PUT_TO(var_letter, 'A'+k-1);
+Problems::quote_source(1, current_sentence);
+Problems::quote_stream(2, var_letter);
+StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ReturnKindUndetermined));
+Problems::issue_problem_segment(
+"The declaration %1 tries to set up a phrase which decides a "
+"value which is too vaguely described, because it involves "
+"a kind variable (%2) which it can't determine through "
+"usage.");
+Problems::issue_problem_end();
+DISCARD_TEXT(var_letter)
+ }
+ }
+
§9.7. Throw problems for inline phrases named as constants9.7 =
+
+
+
+phrase *ph;
+LOOP_OVER(ph, phrase)
+if ((Phrases::TypeData::invoked_inline(ph)) &&
+ (Phrases::Usage::has_name_as_constant(&(ph->usage_data)))) {
+current_sentence = Phrases::declaration_node(ph);
+Problems::quote_source(1, current_sentence);
+StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NamedInline));
+Problems::issue_problem_segment(
+"The declaration %1 tries to give a name to a phrase which is "
+"defined using inline Inform 6 code in (- markers -). Such "
+"phrases can't be named and used as constants because they "
+"have no independent existence, being instead made fresh "
+"each time they are used.");
+Problems::issue_problem_end();
+ }
+
§10. The twilight gathers, but our work is far from done. Recall that we have
+accumulated compilation requests for "To..." phrases, but haven't actually
+acted on them yet.
+
+
+
We have to do this in quite an open-ended way, because compiling one phrase
+can easily generate fresh requests for others. For instance, suppose we have
+the definition "To expose (X - a value)" in play, and suppose that when
+compiling the phrase "To advertise", Inform runs into the line "expose the
+hoarding text". This causes it to issue a compilation request for "To expose
+(X - a text)". Perhaps we've compiled such a form already, but perhaps we
+haven't. Compilation therefore goes on until all requests have been dealt
+with.
+
+
+
Compiling phrases also produces the need for other pieces of code to be
+generated — for example, suppose our phrase being compiled, "To advertise",
+includes the text:
+
+
+
+
let Z be "Two for the price of one! Just [expose price]!";
+
+
+
We are going to need to compile "Two for the price of one! Just [expose price]!"
+later on, in its own text substitution routine; but notice that it contains
+the need for "To expose (X - a number)", and that will generate a further
+phrase request.
+
+
+
Because of this and similar problems, it's impossible to compile all the
+phrases alone: we must compile phrases, then things arising from them, then
+phrases arising from those, then things arising from the phrases arising
+from those, and so on, until we're done. The process is therefore structured
+as a set of "coroutines" which each carry out as much as they can and then
+hand over to the others to generate more work.
+
+StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_NamelessRule),
+"there are many rules in Inform",
+"so you need to give a name: 'this is the abolish dancing rule', say, "
+"not just 'this is the rule'.");
+ ==> { FALSE, - }
+
+StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UnarticledRule),
+"a rule must be given a definite name",
+"which begins with 'the', just to emphasise that it is the only one "
+"with this name: 'this is the promote dancing rule', say, not just "
+"'this is promote dancing rule'.");
+ ==> { FALSE, - }
+
+StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_PluralisedRule),
+"a rule must be given a definite name ending in 'rule' not 'rules'",
+"since the plural is only used for rulebooks, which can of course "
+"contain many rules at once.");
+ ==> { FALSE, - }
+
+StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_BareTo),
+"'to' what? No name is given",
+"which means that this would not define a new phrase.");
+ ==> { 4, - };
+
+StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_DontCallPhrasesWithCalled),
+"phrases aren't named using 'called'",
+"and instead use 'this is...'. For example, 'To salute (called saluting)' "
+"isn't allowed, but 'To salute (this is saluting)' is.");
+ ==> { 4, - };
+
§5. As a safety measure, to avoid ambiguities, Inform only allows one phrase
+definition to begin with "now". It recognises such phrases as those whose
+preambles match:
+
+voidToPhraseFamily::phud(imperative_defn *id, ph_usage_data *phud) {
+to_family_data *tfd = RETRIEVE_POINTER_to_family_data(id->family_specific_data);
+wordingW = tfd->pattern;
+phud->rule_preamble = W;
+
+if (Wordings::nonempty(tfd->constant_name)) The preamble parses to a named To phrase7.1;
+if (<now-phrase-preamble>(W)) {
+if (no_now_phrases++ == 1) {
+StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RedefinedNow),
+"creating new variants on 'now' is not allowed",
+"because 'now' plays a special role in the language. "
+"It has a wide-ranging ability to make a condition "
+"become immediately true. (To give it wider abilities, "
+"the idea is to create new relations.)");
+ }
+ }
+if (<begin-phrase-preamble>(W)) {
+phud->to_begin = TRUE;
+ }
+}
+
+
§7.1. When we parse a named phrase in coarse mode, we need to make sure that
+name is registered as a constant value; when we parse it again in fine
+mode, we can get that value back again if we look it up by name.
+
+
+
The preamble parses to a named To phrase7.1 =
+
+
+
+wordingNW = tfd->constant_name;
+
+constant_phrase *cphr = Phrases::Constants::parse(NW);
+if (Kinds::Behaviour::definite(cphr->cphr_kind) == FALSE) {
+phrase *ph = Phrases::Constants::as_phrase(cphr);
+if (ph) current_sentence = Phrases::declaration_node(ph);
+Problems::quote_source(1, Diagrams::new_UNPARSED_NOUN(Nouns::nominative_singular(cphr->name)));
+Problems::quote_wording(2, Nouns::nominative_singular(cphr->name));
+StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NamedGeneric));
+Problems::issue_problem_segment(
+"I can't allow %1, because the phrase it gives a name to "
+"is generic, that is, it has a kind which is too vague. "
+"That means there isn't any single phrase which '%2' "
+"could refer to - there would have to be different versions "
+"for every setting where it might be needed, and we can't "
+"predict in advance which one '%2' might need to be.");
+Problems::issue_problem_end();
+LOG("CPHR failed at %d, %u\n", cphr->allocation_id, cphr->cphr_kind);
+ }
+phud->explicit_name_used_in_maths = tfd->explicit_name_used_in_maths;
+phud->explicit_name_for_inverse = tfd->explicit_name_for_inverse;
+phud->explicit_name_used_in_maths = tfd->explicit_name_used_in_maths;
+phud->constant_phrase_holder = cphr;
+
§1. As with tables, equations are detected early on in Inform's run but not
parsed for their contents until later, so we store several word ranges.
@@ -135,7 +135,7 @@ instance has its own equation
CLASS_DEFINITION} equation_symbol;
-
The structure equation_symbol is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/ass2, 4/imp, 5/tc, 5/tbl, 6/tcp, 6/cu and here.
+
The structure equation_symbol is accessed in 2/ptmn, 2/cs, 2/ps, 2/is, 3/dlr, 3/pr, 3/tr, 3/nuor, 3/uor, 3/tr2, 3/dbtr, 3/rpr, 3/nar, 3/nlpr, 3/nrr, 3/npr, 3/nvr, 3/nar2, 4/rpt, 4/tc, 4/ass, 4/npa, 4/rk, 4/ass2, 4/imp, 5/adf, 5/tpf, 6/tc, 6/tbl, 7/tcp, 7/cu and here.
§3. In addition, there are some standing symbols used by all equations: the
constant "pi", for example. They're stored in this linked list:
§8.1. The above catches all of the named expressions written out in the
@@ -236,10 +236,10 @@ either case, an equation begins here:
equation *Equations::new_at(parse_node *p, intanonymous) {wordingW = Node::get_text(p);
-returnEquations::new(W, anonymous);
+returnEquations::new(W, anonymous);}
-equation *Equations::new(wordingW, intanonymous) {
+equation *Equations::new(wordingW, intanonymous) {equation *eqn;LOOP_OVER(eqn, equation)if (eqn->equation_created_at == current_sentence)
@@ -257,11 +257,11 @@ either case, an equation begins here:
wordingNO = EMPTY_WORDING, NA = EMPTY_WORDING;if (anonymous == FALSE) {
-Parse the equation's number and/or name8.1.1;
-Register any names for this equation8.1.3;
+Parse the equation's number and/or name8.1.1;
+Register any names for this equation8.1.3;if (<equation-where>(W)) {W = GET_RW(<equation-where>, 1);
-Equations::set_wherewithal(eqn, GET_RW(<equation-where>, 2));
+Equations::set_wherewithal(eqn, GET_RW(<equation-where>, 2)); } }eqn->equation_no_text = NO;
@@ -297,7 +297,7 @@ We know that this begins with the word "equation", or we wouldn't be here
"Newton's Second Law', or 'Equation 41 - Coulomb's Law'."); ==> { 0, - };
§9. A "where" clause following an equation defines its symbols, as we shall
see. That can be detected in the above parsing process where the equation
is displayed, but for anonymous equations occurring inline, the S-parser
@@ -378,7 +378,7 @@ has to discover it; and the S-parser then calls this routine:
§12. Declaring symbols. Equations are allowed to end with a "where..." clause, explaining what
@@ -436,9 +436,9 @@ is expected to declare every symbol occurring in it.
§16.2. At this point we know the user means the variable named at word wn
to have the temporary value spec, and we have to identify that as one
of the symbols:
@@ -701,7 +701,7 @@ of the symbols:
"This one doesn't seem to occur there.");returnFALSE;
-
-equation_node *Equations::enode_new(intt) {
+equation_node *Equations::enode_new(intt) {equation_node *enode = CREATE(equation_node);enode->eqn_type = t;enode->eqn_operation = -1;
@@ -859,20 +859,20 @@ equation. (The other kinds can be created using
§26. Tokenising equations. We break up the word range \((w_1, w_2)\) into tokens of equation matter. Word
@@ -935,9 +935,9 @@ has to be issued, or else a pointer to the parsed tree if we succeed.
§26.1.1. Note that symbols are identified by recognition: without knowing the identities
of the symbols, the syntax alone wouldn't tell us how to break them. We can only
break mc^2 as m followed by c^2 if we know that m and c are symbols,
@@ -996,7 +996,7 @@ allow implicit multiplication.)
for (j=0; (j<14) && (Characters::isalnum(p[i+j])) && (token == NULL); j++)PUT_TO(text_of_symbol, p[i+j]);for (equation_symbol *ev = standard_equation_symbols; ev; ev = ev->next)
-Look for this symbol name26.1.1.1;
+Look for this symbol name26.1.1.1;if (token == NULL)for (j=1; (j<15) && (Characters::isalnum(p[i+j-1])) && (token == NULL); j++) { copy the first j characters into a C string:
@@ -1005,7 +1005,7 @@ allow implicit multiplication.)
try to identify this as one of the declared symbols:equation_symbol *ev;for (ev = eqn->symbol_list; ev; ev = ev->next)
-Look for this symbol name26.1.1.1;
+Look for this symbol name26.1.1.1; }if (token == NULL) {StandardProblems::equation_problem_S(_p_(PM_EquationTokenUnrecognised), eqn, text_of_symbol,
@@ -1016,18 +1016,18 @@ allow implicit multiplication.)
}DISCARD_TEXT(text_of_symbol)
§26.1.2. The following is reliable because a string of digits not starting with a
0 is always a valid number to Inform unless it overflows the virtual machine's
capacity; and so is the number 0 itself.
@@ -1045,7 +1045,7 @@ capacity; and so is the number 0 itself.
}TEMPORARY_TEXT(text_of_number)
-Copy the literal number into a C string, flanked by spaces26.1.2.1;
+Copy the literal number into a C string, flanked by spaces26.1.2.1; now sneakily add this to the word stream, and let the S-parser read it:wordingNW = Feeds::feed_text(text_of_number);DISCARD_TEXT(text_of_number)
@@ -1060,9 +1060,9 @@ capacity; and so is the number 0 itself.
} this can only go wrong if there was an overflow, and a problem will have been issued for that:if (Node::is(spec, CONSTANT_NT) == FALSE) returnNULL;
-token = Equations::enode_new_constant(spec);
+token = Equations::enode_new_constant(spec);
§26.2. So now we have our next token, and are ready to ship it. But if we
detect an implicit multiplication, for instance between m and c^2
in E=mc^2, we issue that as an IMPLICIT_TIMES_OPERATION enode in
@@ -1128,18 +1128,18 @@ between; and in log pi
§26.3. In case any of the enode insertions fail. It's tricky to generate good error
messages and recover well when an operator-precedence grammar fails to match in
a parser like this, so we'll fall back on this:
@@ -1162,12 +1162,12 @@ a parser like this, so we'll fall back on this:
"mathematical formula.");returnNULL;
-
§30. The start and finish are as follows. At the start, the emitter stack is
@@ -1231,8 +1231,8 @@ there will be two END_EQN
-voidEquations::enode_sr_start(void) {
-SR_stack[0] = Equations::enode_new(END_EQN);
+voidEquations::enode_sr_start(void) {
+SR_stack[0] = Equations::enode_new(END_EQN);SR_sp = 1;emitter_sp = 0;}
@@ -1242,7 +1242,7 @@ node: the head of the tree we have grown to represent the expression.
§32.2. The ASU book is a little vague about what happens if there is an underflow
here, I think because it's possible to set up the grammar such that an
underflow cannot occur. But I can see no obvious proof that it will never
@@ -1320,10 +1320,10 @@ is 1, not 0.
do { if (SR_sp <= 1) returnFALSE;
-if (Equations::enode_emit(SR_stack[--SR_sp]) == FALSE) returnFALSE;
- } while ((SR_sp >= 1) && (Equations::enode_lt(SR_stack[SR_sp-1], SR_stack[SR_sp]) == FALSE));
+if (Equations::enode_emit(SR_stack[--SR_sp]) == FALSE) returnFALSE;
+ } while ((SR_sp >= 1) && (Equations::enode_lt(SR_stack[SR_sp-1], SR_stack[SR_sp]) == FALSE));
§33. The key point is that if nodes arrive at the SR parser in their
ordinary order of mathematical writing, then they "reduce" off the
SR stack and onto the emitter stack in reverse Polish notation order.
@@ -1333,7 +1333,7 @@ easy to build a tree from.
-intEquations::enode_emit(equation_node *tok) {
+intEquations::enode_emit(equation_node *tok) {switch (tok->eqn_type) {caseSYMBOL_EQN:caseCONSTANT_EQN:emitter_stack[emitter_sp++] = tok;
@@ -1375,18 +1375,18 @@ score \(g(T)\) if they appear on the right:
@@ -1404,7 +1404,7 @@ the same precedence as explicit multiplication), and is so that
-intEquations::f_function(equation_node *tok) {
+intEquations::f_function(equation_node *tok) {switch (tok->eqn_type) {caseSYMBOL_EQN:caseCONSTANT_EQN:return16;caseOPERATION_EQN:
@@ -1429,7 +1429,7 @@ the same precedence as explicit multiplication), and is so that
-intEquations::g_function(equation_node *tok) {
+intEquations::g_function(equation_node *tok) {switch (tok->eqn_type) {caseSYMBOL_EQN:caseCONSTANT_EQN:return15;caseOPERATION_EQN:
@@ -1456,15 +1456,15 @@ out first: we want the top node in the tree to be the unique
-intEquations::eqn_typecheck(equation *eqn) {
-switch (Equations::enode_count_equals(eqn->parsed_equation)) {
+intEquations::eqn_typecheck(equation *eqn) {
+switch (Equations::enode_count_equals(eqn->parsed_equation)) {case0:StandardProblems::equation_problem(_p_(PM_EquationDoesntEquate), eqn, "","this equation doesn't seem to contain an equals sign, and ""without '=' there is no equating anything with anything.");returnFALSE;case1:
-if (Equations::enode_is_equals(eqn->parsed_equation) == FALSE) {
+if (Equations::enode_is_equals(eqn->parsed_equation) == FALSE) {StandardProblems::equation_problem(_p_(PM_EquationEquatesBadly), eqn, "","the equals sign '=' here seems to be buried inside the ""formula, not at the surface. For instance, 'F = ma' is "
@@ -1480,24 +1480,24 @@ out first: we want the top node in the tree to be the unique returnFALSE; }
-returnEquations::enode_typecheck(eqn, eqn->parsed_equation);
+returnEquations::enode_typecheck(eqn, eqn->parsed_equation);}
§38. A recursive count of instances down the tree from tok:
§39.2. The restriction on powers is needed to make it possible to know the
dimensions of the result. If \(h\) is a length, \(h^2\) is an area but \(h^3\) is
a volume; so if all we have is \(h^n\), and we don't know the value of \(n\),
@@ -1600,18 +1600,18 @@ we're unable to see what equations \(h^n\) can appear in.
if (Kinds::Dimensions::dimensionless(Kinds::FloatingPoint::underlying(base->gK_after))) {tok->gK_before = base->gK_after;tok->gK_after = base->gK_after;
- } elseTake the dimensional power of the kind of the base39.2.1;
+ } elseTake the dimensional power of the kind of the base39.2.1;intlf = Kinds::FloatingPoint::is_real(tok->enode_operands[0]->gK_after);intrf = Kinds::FloatingPoint::is_real(tok->enode_operands[1]->gK_after);if ((lf == TRUE) && (rf == FALSE))
-Equations::promote_subequation(eqn, tok->enode_operands[1], FALSE);
+Equations::promote_subequation(eqn, tok->enode_operands[1], FALSE);if ((lf == FALSE) && (rf == TRUE))
-Equations::promote_subequation(eqn, tok->enode_operands[0], FALSE);
+Equations::promote_subequation(eqn, tok->enode_operands[0], FALSE);if ((Kinds::FloatingPoint::is_real(tok->gK_after) == FALSE) && ((lf) || (rf))) {tok->gK_before = Kinds::FloatingPoint::to_real(tok->gK_before); }
-
§39.2.1. To work out the kind of \(b^n\), we use repeated multiplication or division
of dimensions; if \(n=0\) then we have a dimensionless value, and choose
"number" as the simplest possibility.
@@ -1698,7 +1698,7 @@ of dimensions; if \(n=0\) then we have a dimensionless value, and choose
Kinds::FloatingPoint::new_gk(K); }
-
§41.3.1. Solving \(x^v = y\) for \(v\) requires logs, which are not in our scheme; and
solving \(v^n = y\) for non-constant \(n\) is no better. So in either case we
surrender by returning FALSE.
@@ -2041,9 +2041,9 @@ cube roots.
old_LHS->enode_arity = 2;old_LHS->enode_operands[0] = old_RHS;equation_node *the_power = old_LHS->enode_operands[1];
-old_LHS->enode_operands[1] = Equations::enode_new_op(DIVIDE_OPERATION);
+old_LHS->enode_operands[1] = Equations::enode_new_op(DIVIDE_OPERATION);old_LHS->enode_operands[1]->enode_arity = 2;
-old_LHS->enode_operands[1]->enode_operands[0] = Equations::enode_new_constant(
+old_LHS->enode_operands[1]->enode_operands[0] = Equations::enode_new_constant(Rvalues::from_int(1, EMPTY_WORDING));old_LHS->enode_operands[1]->enode_operands[0]->gK_before =Kinds::FloatingPoint::new_gk(K_number);
@@ -2061,7 +2061,7 @@ cube roots.
RTKinds::notify_of_use(K_real_number); }
-
§41.3.2. Here we have something like log x = y and want to rewrite as x = exp y,
which is only possible if we have an inverse available for our function —
in this case, exp being the inverse of log. Thus:
@@ -2091,7 +2091,7 @@ in this case, expequation_node *fnode = old_LHS->enode_operands[0];if ((fnode->leaf_symbol == NULL) || (fnode->leaf_symbol->function_notated == NULL)) {
-Equations::log_equation_node(fnode);
+Equations::log_equation_node(fnode);internal_error("not a function being applied"); }phrase *f = fnode->leaf_symbol->function_notated;
@@ -2111,7 +2111,7 @@ in this case, expeqn->parsed_equation->enode_operands[1] = old_LHS;old_LHS->enode_operands[1] = old_RHS;
-
§41.4. The unary operations are easy in a similar way — they only have one operand,
so we always promote \(V\) and achieve property (i). A square root is rearranged
as a square, and a cube root as a cube. (It's important that everything we do
@@ -2146,27 +2146,27 @@ the other side; thus \(-V = R\) becomes \(V=-R\), and old_LHS->eqn_operation = TIMES_OPERATION;old_LHS->enode_arity = 2;old_LHS->enode_operands[0] = old_RHS;
-old_LHS->enode_operands[1] = Equations::enode_new_op(TIMES_OPERATION);
+old_LHS->enode_operands[1] = Equations::enode_new_op(TIMES_OPERATION);old_LHS->enode_operands[1]->enode_operands[0] = old_RHS;old_LHS->enode_operands[1]->enode_operands[1] = old_RHS;break;default:internal_error("unanticipated operator in rearrangement"); }
-
§42. And that's the whole rearranger, except for the utility routine which
counts instances of the magic variable v at or below a given point in the
equation tree.
@@ -2181,18 +2181,18 @@ parse the equation, then rearrange to solve it for each variable in turn.
E = GET_RW(<equation-where>, 1);WH = GET_RW(<equation-where>, 2); }
-equation *eqn = Equations::new(E, TRUE);
-Equations::set_wherewithal(eqn, WH);
-Equations::examine(eqn);
+equation *eqn = Equations::new(E, TRUE);
+Equations::set_wherewithal(eqn, WH);
+Equations::examine(eqn);InternalTests::begin_internal_reporting();
-Equations::log_equation_parsed(eqn);
+Equations::log_equation_parsed(eqn);equation_symbol *ev;for (ev = eqn->symbol_list; ev; ev = ev->next) {
-if (Equations::eqn_rearrange(eqn, ev) == FALSE)
+if (Equations::eqn_rearrange(eqn, ev) == FALSE)LOG("Too hard to rearrange to solve for %W\n", ev->name);else {LOG("Rearranged to solve for %W:\n", ev->name);
-Equations::log_equation_parsed(eqn);
+Equations::log_equation_parsed(eqn); } }InternalTests::end_internal_reporting();
@@ -2206,9 +2206,9 @@ parse the equation, then rearrange to solve it for each variable in turn.
LOG("{%W}", eqn->equation_text);}
-voidEquations::log_equation_parsed(equation *eqn) {
+voidEquations::log_equation_parsed(equation *eqn) {if (eqn == NULL) LOG("<null>\n");
-elseEquations::log_equation_node(eqn->parsed_equation);
+elseEquations::log_equation_node(eqn->parsed_equation);}voidEquations::index(OUTPUT_STREAM) {
@@ -2237,7 +2237,7 @@ parse the equation, then rearrange to solve it for each variable in turn.
}
diff --git a/docs/assertions-module/5-tbl.html b/docs/assertions-module/6-tbl.html
similarity index 97%
rename from docs/assertions-module/5-tbl.html
rename to docs/assertions-module/6-tbl.html
index e96b20044..1b258d149 100644
--- a/docs/assertions-module/5-tbl.html
+++ b/docs/assertions-module/6-tbl.html
@@ -70,10 +70,10 @@ function togglePopup(material_id) {
§1. This is how a table is stored. Note that the limit on columns per table
must not rise to 100 or beyond because that would break the system of table
@@ -110,7 +110,7 @@ column ID numbers: see CLASS_DEFINITION} table;
-
@@ -149,7 +149,7 @@ see below.
table *t;LOOP_OVER(t, table) {current_sentence = t->table_created_at->source_table;
-Tables::stock_table(t, phase);
+Tables::stock_table(t, phase); } }}
@@ -184,7 +184,7 @@ some of these fields have been properly filled in.
-table *Tables::new_table_structure(parse_node *PN) {
+table *Tables::new_table_structure(parse_node *PN) {table *t = CREATE(table);t->table_no_text = EMPTY_WORDING;t->table_name_text = EMPTY_WORDING;
@@ -205,7 +205,7 @@ some of these fields have been properly filled in.
t->no_columns = 0;t->table_created_at = NULL;RTTables::new_table(PN, t);
-Tables::add_table_contribution(t, current_sentence);
+Tables::add_table_contribution(t, current_sentence);returnt;}
@@ -213,7 +213,7 @@ some of these fields have been properly filled in.
-voidTables::add_table_contribution(table *t, parse_node *src) {
+voidTables::add_table_contribution(table *t, parse_node *src) {table_contribution *tc = CREATE(table_contribution);tc->source_table = src;tc->next = NULL;
@@ -238,7 +238,7 @@ some of these fields have been properly filled in.
returnt->no_columns;}
-intTables::get_no_rows(table *t) {
+intTables::get_no_rows(table *t) {parse_node *PN; intc=0;for (PN=t->columns[0].entries->down; PN; PN=PN->next) c++;c += t->blank_rows;
@@ -264,7 +264,7 @@ some of these fields have been properly filled in.
kind *Tables::kind_of_ith_column(table *t, inti) {if ((i<0) || (i>=t->no_columns))internal_error("tcdt for column out of range");
-returnTables::Columns::get_kind(t->columns[i].column_identity);
+returnTables::Columns::get_kind(t->columns[i].column_identity);}
§11. Oddball forms of naming:
@@ -322,7 +322,7 @@ two forms in any case.
table...-...|==> { TABLE_HAS_NUMBER_AND_NAME, - }table###|==> { TABLE_HAS_ONLY_NUMBER, - }tableof...|==> { TABLE_HAS_ONLY_NAME, - }
-table...==>Issue PM_TableMisnamed problem14.1
+table...==>Issue PM_TableMisnamed problem14.1
§17.1. Changes to the lexer mean that this shouldn't happen, but just in case:
@@ -418,7 +418,7 @@ table and then destroy the temporary one made here.
"the start of the table is too much.");return;
-
§17.4. It's not as simple as it seems to decide when a new table headline refers
back to a table which already exists — there are several ways we could play
this. What we say is that if the new headline gives both name and number,
@@ -509,7 +509,7 @@ number only, that must. Suppose that "Table 2 - Trees" already exists. Then:
existing_table_with_same_name = t2; }
-
§17.9.1. See "Table Columns" for the actual column creation: note that this makes
a node in the parse tree representing the column's use within this table.
@@ -646,12 +646,12 @@ a node in the parse tree representing the column's use within this table.
}if (col_count < MAX_COLUMNS_PER_TABLE) {LOGIF(TABLES, "Creating col %d from '%W'\n", t->no_columns, CW);
-t->columns[t->no_columns] = Tables::Columns::add_to_table(CW, t);
+t->columns[t->no_columns] = Tables::Columns::add_to_table(CW, t);if (t->columns[t->no_columns].column_identity) i.e., no Problem occurredt->no_columns++; }
-
§17.9.2. Each data cell becomes a node, and is added to the list under its column.
@@ -677,7 +677,7 @@ a node in the parse tree representing the column's use within this table.
SyntaxTree::graft(Task::syntax_tree(), cell, t->columns[col_count].entries); }
-
§17.9.3. If a row finishes early, we pad it out with blanks.
@@ -686,13 +686,13 @@ a node in the parse tree representing the column's use within this table.
while (col_count < t->no_columns) { which can only happen on data rows
-parse_node *cell = Tables::empty_cell_node();
+parse_node *cell = Tables::empty_cell_node();Annotations::write_int(cell, table_cell_unspecified_ANNOT, TRUE);SyntaxTree::graft(Task::syntax_tree(), cell, t->columns[col_count].entries);col_count++; }
§17.10.1. We assume that columns in the new and old tables will be partial permutations
of each other: for example the old might have columns "fish", "mammals", "birds"
(index j running from 0 to 2) and the new "mammals", "reptiles", "fish",
@@ -746,7 +746,7 @@ the other table at all. The result will be:
Nouns::nominative_singular(t->columns[i].column_identity->name));LOGIF(TABLES, "\n");
-
§17.10.2.1. It's a little awkward to work out what the policy is if the original table
wants a row for each man, and the continuation wants a row for each woman.
@@ -803,7 +803,7 @@ wants a row for each man, and the continuation wants a row for each woman.
old_t->blank_rows_for_each_text = t->blank_rows_for_each_text; }
-
@@ -836,7 +836,7 @@ wants a row for each man, and the continuation wants a row for each woman.
old_t->blank_rows_text = t->blank_rows_text;old_t->blank_rows_for_each_text = t->blank_rows_for_each_text;
-
§17.10.4. Amendments can't be done yet, because they depend on recognising values,
and it's far too early in Inform's run to recognise constants. So we must
postpone the work until later: note that we don't destroy the new table
@@ -847,12 +847,12 @@ structure in this case.
§17.10.2.2. Here each new column must appear once in the old table, but the new
table doesn't have to cover everything in the old table. (Blanks are
used in continuation rows for columns not mentioned.)
@@ -880,12 +880,12 @@ used in continuation rows for columns not mentioned.)
"The table %1 won't work as a continuation, because it contains ""%3 not found in the original %2.");Problems::issue_problem_end();
-Display the old and new table column names17.10.2.2.1;
+Display the old and new table column names17.10.2.2.1;DESTROY(t, table);return; }
-
§17.10.3.2. Here each old column must appear once in the new table, but the new
table is allowed to have extra columns. (This means the new table can
be "wider" than the old one.)
@@ -911,12 +911,12 @@ be "wider" than the old one.)
"The table %1 won't work as a replacement, because it's missing ""%3 found in the original %2.");Problems::issue_problem_end();
-Display the old and new table column names17.10.2.2.1;
+Display the old and new table column names17.10.2.2.1;DESTROY(t, table);return; }
-
@@ -1118,7 +1118,7 @@ us issue more contextual problem messages.
"is involved in some other way, try using 'yourself' instead."); ==> { PROBLEMATIC_TABLE_ENTRY, - };
-
§21.4. The message PM_TablePlayerEntry is so called because by far the commonest
case of this is people writing "player" as a constant value in a column of
people — it needs to be "yourself" instead, since "player" is a variable.
@@ -1159,15 +1159,15 @@ people — it needs to be "yourself" instead, since "player" is a variable.
} ==> { PROBLEMATIC_TABLE_ENTRY, - };
-
§21.5.1. (There are actually two ways this can happen, which is why it's set out like this.)
@@ -1190,24 +1190,24 @@ people — it needs to be "yourself" instead, since "player" is a variable.
"'a number') to show what sort of values will go into an otherwise blank ""row.");
-
@@ -1234,7 +1234,7 @@ people — it needs to be "yourself" instead, since "player" is a variable.
caseKIND_TABLE_ENTRY:Annotations::write_int(cell, table_cell_unspecified_ANNOT, TRUE);kind *K = Specifications::to_kind(spec);
-Tables::Columns::note_kind(t, col_count, &(t->columns[col_count]), cell,
+Tables::Columns::note_kind(t, col_count, &(t->columns[col_count]), cell,K, TRUE);return;caseACTION_TABLE_ENTRY:
@@ -1248,7 +1248,7 @@ people — it needs to be "yourself" instead, since "player" is a variable.
return; }
-
§23.1. For the actual code, see below.
@@ -1294,9 +1294,9 @@ people — it needs to be "yourself" instead, since "player" is a variable.
table *t;LOOP_OVER(t, table)if (t->amendment_of)
-Tables::amend_table(t->amendment_of, t);
+Tables::amend_table(t->amendment_of, t);
-
§24. Amending tables. Unlike continuations and replacements, table amendments depend on actual values
written into the cells, which means they can't be performed early in the run.
So for quite a long time two table structures exist: the "main table", the
@@ -1365,14 +1365,14 @@ at a time:
-voidTables::amend_table(table *main_table, table *amendments) {
+voidTables::amend_table(table *main_table, table *amendments) {LOGIF(TABLES, "Amending table $B according to $B\n", main_table, amendments);parse_node *leftmost_amend_cell = NULL;intamend_row = 1, amendment_problem_opened = FALSE;for (amend_row = 1, leftmost_amend_cell = amendments->columns[0].entries->down;leftmost_amend_cell;amend_row++, leftmost_amend_cell = leftmost_amend_cell->next)
-Apply the amendment in this row to the main table24.1;
+Apply the amendment in this row to the main table24.1;}
§24.1. The following is not so obvious. The amendment row is intended to replace a
@@ -1406,21 +1406,21 @@ Eventually this should leave only a single row, and that's the winner.
§24.1.1. We need one flag for each row in the main table; we do this with the "row
amendable" annotation for the cell nodes in the first column. (There's nothing
special about the first column, but it's guaranteed to exist, i.e., there is
@@ -1439,7 +1439,7 @@ always at least one column.)
matches_in_last_round++; }
-
§24.1.2. Set the amend-cell to this column's cell in the current amendment row24.1.2 =
@@ -1449,7 +1449,7 @@ always at least one column.)
amend_cell && (i < amend_row); i++, amend_cell = amend_cell->next) ;if (amend_cell == NULL) internal_error("columns in amendments aren't equal in length");
-
§24.1.3.2. That just leaves the problem message, a very subtle one which took a long
time to find a clear wording for:
@@ -1530,7 +1530,7 @@ time to find a clear wording for:
-Begin an amendment problem message24.1.3.2.1;
+Begin an amendment problem message24.1.3.2.1;intquoted_col = col + 1; i.e., counting from 1, not 0Problems::quote_number(1, &amend_row);Problems::quote_number(2, "ed_col);
@@ -1554,7 +1554,7 @@ time to find a clear wording for:
Problems::issue_problem_end();break; to move on to the next row in the amendments
§25. And, of course, the actual splicing of the amendment row in place of the
original:
-voidTables::splice_table_row(table *table_to, table *table_from, introw_to, introw_from) {
+voidTables::splice_table_row(table *table_to, table *table_from, introw_to, introw_from) {inti;for (i=0; i<table_to->no_columns; i++) {parse_node *cell_to, *cell_from;
@@ -1608,7 +1608,7 @@ Rules, which of course are always present. So these are hidden by default.
voidTables::index(OUTPUT_STREAM) {HTML_OPEN("p");
-intm = Tables::index_tables_in(OUT, NULL, 0);
+intm = Tables::index_tables_in(OUT, NULL, 0);HTML_CLOSE("p");HTML_OPEN("p");Index::extra_link(OUT, 2);
@@ -1617,7 +1617,7 @@ Rules, which of course are always present. So these are hidden by default.
HTML_CLOSE("p");Index::extra_div_open(OUT, 2, 1, "e0e0e0");inform_extension *E; intefc = 0;
-LOOP_OVER(E, inform_extension) Tables::index_tables_in(OUT, E, efc++);
+LOOP_OVER(E, inform_extension) Tables::index_tables_in(OUT, E, efc++);Index::extra_div_close(OUT, "e0e0e0");}
@@ -1626,9 +1626,9 @@ and does nothing at all if that number is 0.
-intTables::index_tables_in(OUTPUT_STREAM, inform_extension *E, intefc) {
+intTables::index_tables_in(OUTPUT_STREAM, inform_extension *E, intefc) {inttc = 0; table *t;
-LOOP_OVER(t, table) if (Tables::table_within(t, E)) tc++;
+LOOP_OVER(t, table) if (Tables::table_within(t, E)) tc++;if (tc > 0) {if (E) {HTML_OPEN("p");
@@ -1637,8 +1637,8 @@ and does nothing at all if that number is 0.
}HTML::begin_plain_html_table(OUT);LOOP_OVER(t, table)
-if (Tables::table_within(t, E))
-Index this table27.1;
+if (Tables::table_within(t, E))
+Index this table27.1;HTML::end_html_table(OUT); }returntc;
@@ -1660,7 +1660,7 @@ Helvetica-style lower case "x", but life is full of compromises.
Index::link(OUT, Wordings::first_wn(Node::get_text(tc->source_table))); }HTML::next_html_column_spaced(OUT, 0);
-intrc = Tables::get_no_rows(t);
+intrc = Tables::get_no_rows(t);WRITE("<i>");HTML_OPEN_WITH("span", "class=\"smaller\"");if (t->first_column_by_definition) {
@@ -1709,25 +1709,25 @@ Helvetica-style lower case "x", but life is full of compromises.
} } elseif (t->first_column_by_definition) {Kinds::Textual::write(OUT,
-Tables::Columns::get_kind(
+Tables::Columns::get_kind(t->columns[col].column_identity));WRITE(" property"); } else {WRITE("of ");Kinds::Textual::write_plural(OUT,
-Tables::Columns::get_kind(
+Tables::Columns::get_kind(t->columns[col].column_identity)); }HTML::end_html_row(OUT); }
§1. Tables are one of the most distinctive data structures of Inform. They
imitate printed tables in books or scientific papers, and the data inside
@@ -115,10 +115,10 @@ in both tables.
CLASS_DEFINITION} table_column;
-
The structure table_column is accessed in 3/nuor, 3/dbtr, 3/rpr, 4/ass, 5/tbl, 5/eqt and here.
+
The structure table_column is accessed in 3/nuor, 3/dbtr, 3/rpr, 4/ass, 5/tpf, 6/tbl, 6/eqt and here.
§2. The predicate calculus engine often finds conditions equivalent to "if A
is a C listed in T", and we implement this as a binary predicate — see
-Listed-In Relations. There is one such relation for each column, and
+Listed-In Relations. There is one such relation for each column, and
a pointer is stored in listed_in_predicate.
@@ -141,12 +141,12 @@ of any existing column.
-table_column *Tables::Columns::new_table_column(wordingW) {
+table_column *Tables::Columns::new_table_column(wordingW) {table_column *tc = CREATE(table_column);tc->name = NULL;tc->kind_stored_in_column = NULL;tc->table_from_which_kind_inferred = NULL;
-tc->listed_in_predicate = Tables::Relations::make_listed_in_predicate(tc);
+tc->listed_in_predicate = Tables::Relations::make_listed_in_predicate(tc);if (Wordings::nonempty(W)) { always happens unless recovering from a problemtc->name = Nouns::new_proper_noun(W, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT,TABLE_COLUMN_MC, Rvalues::from_table_column(tc),
@@ -176,7 +176,7 @@ of entry in the column \(C\).
-kind *Tables::Columns::get_kind(table_column *tc) {
+kind *Tables::Columns::get_kind(table_column *tc) {returntc->kind_stored_in_column;}
@@ -184,9 +184,9 @@ of entry in the column \(C\).
returnKinds::unary_con(CON_table_column, tc->kind_stored_in_column);}
-voidTables::Columns::set_kind(table_column *tc, table *t, kind *K) {
+voidTables::Columns::set_kind(table_column *tc, table *t, kind *K) {if (Kinds::get_construct(K) == CON_description)
-Issue a problem message for a description heading5.1;
+Issue a problem message for a description heading5.1;if (Kinds::eq(tc->kind_stored_in_column, K)) {LOGIF(TABLES, "Table column $C continues to have kind %u, according to $B\n",tc, K, t);
@@ -197,8 +197,8 @@ of entry in the column \(C\).
}tc->table_from_which_kind_inferred = t;if ((K_understanding) && (Kinds::eq(K, K_understanding)))
-Tables::Relations::supply_kind_for_listed_in_tc(tc->listed_in_predicate, K_snippet);
-elseTables::Relations::supply_kind_for_listed_in_tc(tc->listed_in_predicate, K);
+Tables::Relations::supply_kind_for_listed_in_tc(tc->listed_in_predicate, K_snippet);
+elseTables::Relations::supply_kind_for_listed_in_tc(tc->listed_in_predicate, K);}
§5.1. Issue a problem message for a description heading5.1 =
@@ -214,7 +214,7 @@ of entry in the column \(C\).
"should be %4. But descriptions aren't allowed as table entries - tables ""have to hold values, not descriptions of values.");
§6. Discovering columns. New TCs aren't declared ("Density is a table column."): they are discovered
by looking through the column-heading lines of tables. Each one makes:
@@ -231,15 +231,15 @@ by looking through the column-heading lines of tables. Each one makes:
structinter_name *tcu_iname; for the array holding this at run-time} table_column_usage;
-
The structure table_column_usage is accessed in 3/dbtr, 5/tbl and here.
+
The structure table_column_usage is accessed in 3/dbtr, 6/tbl and here.
§7. Each piece of heading text is passed to the following routine in turn:
-table_column_usageTables::Columns::add_to_table(wordingW, table *t) {
+table_column_usageTables::Columns::add_to_table(wordingW, table *t) {wordingEXPW = EMPTY_WORDING;table_column_usagetcu;
-table_column *tc = Tables::Columns::find_table_column(W, t, &EXPW);
+table_column *tc = Tables::Columns::find_table_column(W, t, &EXPW);for (inti=0; i<t->no_columns; i++)if (t->columns[i].column_identity == tc) {Problems::quote_wording(4, W);
@@ -283,17 +283,17 @@ what looks like text into grammar for parsing.
@@ -309,7 +309,7 @@ what looks like text into grammar for parsing.
"would be quite awkward talking about the '%4 entry', for example.)"); ==> { NEW_TC_PROBLEM, - };
-
@@ -332,7 +332,7 @@ what looks like text into grammar for parsing.
"entries, but forgot to put a name before the opening bracket.)"); ==> { NEW_TC_PROBLEM, - };
-
§10. When a column is found with a name not seen before — say, "merit points"
— the following grammar is used to construct a proper noun to refer to this
column; thus, "merit points column".
@@ -349,7 +349,7 @@ text of any explicit kind declaration used within it.
§12.2. Issue a problem message for an incomprehensible column heading12.2 =
@@ -449,7 +449,7 @@ column in turn:
"table column names when giving the kind of value which will be stored in ""the column. So 'poems (text)' is legal, but not 'poems (chiefly lyrical)'.");
-
§13. Secondly, the actual entries are checked in turn, and their kinds passed
to the following routine. Again, "topic" columns are a complication, since
their kind is ostensibly K_understanding but the actual entries must be
@@ -457,35 +457,35 @@ their kind is ostensibly K_un
§13.2. Issue a problem for a second kind name in the column13.2 =
@@ -545,7 +545,7 @@ their kind is ostensibly K_un
"tell me what might eventually go there - but only once; and ""this is the second time. (The first was %6.)");
-
§13.3. Issue a problem for a value lower in the column than a kind name13.3 =
@@ -566,7 +566,7 @@ their kind is ostensibly K_un
"kind by myself, working it out from the actual values in the column, or ""you can put the kind in brackets after the column's name, at the top.)");
-
§13.4. Issue a problem for kind mismatch within column13.4 =
@@ -579,7 +579,7 @@ their kind is ostensibly K_un
"In %1, column %6 (%2), the entry %3 (row %7) doesn't fit what I know ""about '%2' - it's %4, whereas I think every entry ought to be %5.");
-
-voidTables::Columns::approve_kind(table *t, inti, table_column_usage *tcu) {
-kind *K = Tables::Columns::get_kind(tcu->column_identity);
+voidTables::Columns::approve_kind(table *t, inti, table_column_usage *tcu) {
+kind *K = Tables::Columns::get_kind(tcu->column_identity);LOGIF(TABLES, "Column %d '%W' has kind %u with data:\n$T",i, Nouns::nominative_singular(tcu->column_identity->name), K, tcu->entries);if ((Kinds::get_construct(K) == CON_list_of) &&
@@ -651,12 +651,12 @@ happens:
"which means that I don't know how to deal with it. You should ""either put a value into the column somewhere, or else write ""the kind in as part of the heading: '%2 (a number)', say.");
-Tables::Columns::set_kind(tcu->column_identity, t, K_number);
+Tables::Columns::set_kind(tcu->column_identity, t, K_number); }}
diff --git a/docs/assertions-module/6-aa.html b/docs/assertions-module/7-aa.html
similarity index 95%
rename from docs/assertions-module/6-aa.html
rename to docs/assertions-module/7-aa.html
index d9c13e75f..be4f031c0 100644
--- a/docs/assertions-module/6-aa.html
+++ b/docs/assertions-module/7-aa.html
@@ -88,10 +88,10 @@ function togglePopup(material_id) {
§1. Adjectives can have multiple meanings. For example, it is legal to define
both of these in the same source text:
@@ -112,7 +112,7 @@ and for a table name, the second.
So, then, every adjective has the following data attached to it:
typedefstructadjective_meaning_data {
@@ -157,7 +157,7 @@ memory to keep the sorted list as a second linked list.
adjective_meaning *am;LOOP_OVER_LINKED_LIST(am, adjective_meaning, adj->adjective_meanings.in_defn_order) {LOG("%d: %W ", n, am->indexing_text);
-AdjectiveMeaningDomains::log(&(am->domain));
+AdjectiveMeaningDomains::log(&(am->domain));n++; }}
@@ -200,13 +200,13 @@ early in the run when sorting cannot yet be done.
-intAdjectiveAmbiguity::can_be_applied_to(adjective *adj, kind *K) {
+intAdjectiveAmbiguity::can_be_applied_to(adjective *adj, kind *K) {if (adj) {adjective_meaning *am;LOOP_OVER_LINKED_LIST(am, adjective_meaning, adj->adjective_meanings.in_defn_order) {
-if (AdjectiveMeaningDomains::determine_avoiding_circularity(am) == FALSE)
+if (AdjectiveMeaningDomains::determine_avoiding_circularity(am) == FALSE)returnFALSE;
-kind *am_kind = AdjectiveMeaningDomains::get_kind(am);
+kind *am_kind = AdjectiveMeaningDomains::get_kind(am);if (Kinds::Behaviour::is_object(am_kind)) {if (K == NULL) returnTRUE;if (Kinds::Behaviour::is_object(K)) returnTRUE;
@@ -233,7 +233,7 @@ value, or an either/or property? If so we return the earliest known.
returnNULL;}
-property *AdjectiveAmbiguity::has_either_or_property_meaning(adjective *adj, int *sense) {
+property *AdjectiveAmbiguity::has_either_or_property_meaning(adjective *adj, int *sense) {adjective_meaning *am;if (adj)LOOP_OVER_LINKED_LIST(am, adjective_meaning, adj->adjective_meanings.in_defn_order)
@@ -251,7 +251,7 @@ value, or an either/or property? If so we return the earliest known.
§8. With that sorting done, we can begin to use an adjective. Suppose there has
been an assertion sentence like this:
@@ -346,7 +346,7 @@ kind we think this has. parit
What happens is that the list of definitions for "fixed in place" is checked
-in logical precedence order, and AdjectiveMeanings::assert called
+in logical precedence order, and AdjectiveMeanings::assert called
on any kind which the "ormolu clock" matches. (That will probably be the
definition for the "fixed in place" either/or property for things, unless
someone has given the adjective some special meaning unique to the clock.) The
@@ -361,37 +361,37 @@ asserted for it.
§1. Meanings. For example, "odd" in the sense of numbers is a single meaning. Each meaning
is an instance of:
@@ -99,7 +99,7 @@ is an instance of:
CLASS_DEFINITION} adjective_meaning;
-
The structure adjective_meaning is accessed in 3/nrr, 6/tap, 6/tcp, 6/aa, 6/amd and here.
+
The structure adjective_meaning is accessed in 3/nrr, 5/id, 5/adf, 5/tpf, 5/rf, 7/tap, 7/tcp, 7/aa, 7/amd and here.
§2. This can be created in two ways: straightforwardly —
@@ -110,13 +110,13 @@ is an instance of:
am->defined_at = current_sentence;am->indexing_text = W;am->owning_adjective = NULL;
-am->domain = AdjectiveMeaningDomains::new_from_text(EMPTY_WORDING);
+am->domain = AdjectiveMeaningDomains::new_from_text(EMPTY_WORDING);am->family = family;am->family_specific_data = details;am->has_been_compiled_in_support_function = FALSE;am->schemas_prepared = FALSE;am->negated_from = NULL;
-AdjectiveMeanings::initialise_all_task_data(am);
+AdjectiveMeanings::initialise_all_task_data(am);returnam;}
@@ -137,12 +137,12 @@ might be created as the negation of "even" for numbers):
am->has_been_compiled_in_support_function = FALSE;am->schemas_prepared = FALSE;am->negated_from = other;
-AdjectiveMeanings::negate_task_data(am, other);
+AdjectiveMeanings::negate_task_data(am, other);for (inti=1; i<=NO_ATOM_TASKS; i++) {intj = i;if (i == NOW_ATOM_TRUE_TASK) j = NOW_ATOM_FALSE_TASK;if (i == NOW_ATOM_FALSE_TASK) j = NOW_ATOM_TRUE_TASK;
-AdjectiveMeanings::copy_task_data(&(am->task_data[j]), &(other->task_data[i]));
+AdjectiveMeanings::copy_task_data(&(am->task_data[j]), &(other->task_data[i]));Calculus::Schemas::modify(&(am->task_data[j].call_to_support_function), ""); }returnam;
@@ -151,7 +151,7 @@ might be created as the negation of "even" for numbers):
§4. Task data. When Inform needs to compile code for testing if an adjective is true as
applied to something, or to make it now true (or false), it does this by
compiling code for the associated unary predicate — see
-The Adjectival Predicates. What to compile depends on the meaning or
+The Adjectival Predicates. What to compile depends on the meaning or
meanings which might apply; if it's this meaning, then we will need an
I6 schema to carry out one of three tasks, TEST_ATOM_TASK,
NOW_ATOM_TRUE_TASK, or NOW_ATOM_FALSE_TASK.
@@ -167,13 +167,13 @@ I6 schema to carry out one of three tasks, structi6_schemacode_to_perform; where TRUE} adjective_task_data;
-voidAdjectiveMeanings::initialise_task_data(adjective_task_data *atd) {
+voidAdjectiveMeanings::initialise_task_data(adjective_task_data *atd) {atd->task_mode = NO_TASKMODE;Calculus::Schemas::modify(&(atd->code_to_perform), "");Calculus::Schemas::modify(&(atd->call_to_support_function), "");}
-voidAdjectiveMeanings::copy_task_data(adjective_task_data *to, adjective_task_data *from) {
+voidAdjectiveMeanings::copy_task_data(adjective_task_data *to, adjective_task_data *from) {to->task_mode = from->task_mode;to->code_to_perform = from->code_to_perform;to->call_to_support_function = from->call_to_support_function;
@@ -186,17 +186,17 @@ switched around from the original.
By default, an adjective meaning is unable to perform any of the three tasks,
-and the creator of it has to call AdjectiveMeanings::make_schema to say
+and the creator of it has to call AdjectiveMeanings::make_schema to say
otherwise. This puts us by default into DIRECT_TASKMODE, unless we're working
in the world of objects where run-time typechecking will be needed — in which
case VIA_SUPPORT_FUNCTION_TASKMODE. But the creator can insist on the latter
-anyway with a subsequent call to AdjectiveMeanings::perform_task_via_function.
+anyway with a subsequent call to AdjectiveMeanings::perform_task_via_function.
enumNO_TASKMODEfrom1
@@ -225,7 +225,7 @@ anyway with a subsequent call to Adject
-i6_schema *AdjectiveMeanings::get_schema(adjective_meaning *am, intT) {
-AdjectiveMeanings::prepare_schemas(am, T);
+i6_schema *AdjectiveMeanings::get_schema(adjective_meaning *am, intT) {
+AdjectiveMeanings::prepare_schemas(am, T);switch (am->task_data[T].task_mode) {caseDIRECT_TASKMODE:return &(am->task_data[T].code_to_perform);caseVIA_SUPPORT_FUNCTION_TASKMODE:if (Calculus::Schemas::empty(&(am->task_data[T].call_to_support_function)))
-Construct a schema for calling the support function7.1;
+Construct a schema for calling the support function7.1;return &(am->task_data[T].call_to_support_function); }returnNULL;}
-i6_schema *AdjectiveMeanings::get_schema_without_call(adjective_meaning *am, intT) {
-AdjectiveMeanings::prepare_schemas(am, T);
+i6_schema *AdjectiveMeanings::get_schema_without_call(adjective_meaning *am, intT) {
+AdjectiveMeanings::prepare_schemas(am, T);switch (am->task_data[T].task_mode) {caseDIRECT_TASKMODE:caseVIA_SUPPORT_FUNCTION_TASKMODE:
@@ -285,11 +285,11 @@ negation does not, and so must use those of the original.
} }inter_name *iname = RTAdjectives::iname(use_adj, task,
-RTKinds::weak_id(AdjectiveMeaningDomains::get_kind(am)));
+RTKinds::weak_id(AdjectiveMeaningDomains::get_kind(am)));Calculus::Schemas::modify(&(am->task_data[T].call_to_support_function),"*=-(%s%n(*1))", negation_operator, iname);
§8. Families of adjective meanings. The above API would allow us to make fairly arbitrary one-off adjectives,
but in practice we have a number of distinct purposes and want to make a
whole pile of related adjectives for each one. So we actually create
@@ -313,7 +313,7 @@ adjective meanings in "families".
returnf;}
-
The structure adjective_meaning_family is private to this section.
+
The structure adjective_meaning_family is accessed in 5/id and here.
§9. Families provide a number of methods to tweak how adjectives behave,
and here goes. All of these methods are optional.
@@ -358,7 +358,7 @@ is ascending order of the family's adjective_meaning_family *f;LOOP_OVER(f, adjective_meaning_family)if (f->definition_claim_priority == priority)
-Try the f family9.1;
+Try the f family9.1; }returnNULL;}
@@ -373,7 +373,7 @@ is ascending order of the family's AW, DNW, CONW, CALLW);if (rv) returnam;
-
§10. By default, an adjective meaning cannot be asserted, that is, said to be
true of something (an inference subject) in the model world. So if "fizzy"
is a newly created adjective, the sentence "The drink is fizzy" would be
@@ -392,7 +392,7 @@ subject subj, a
INT_METHOD_TYPE(ASSERT_ADJM_MTID, adjective_meaning_family *f, adjective_meaning *am,inference_subject *subj, intparity)
-intAdjectiveMeanings::assert(adjective_meaning *am, inference_subject *subj,
+intAdjectiveMeanings::assert(adjective_meaning *am, inference_subject *subj,intparity) {if (am->negated_from) {am = am->negated_from; parity = (parity)?FALSE:TRUE;
@@ -415,7 +415,7 @@ creation time), but there is no obligation.
VOID_METHOD_TYPE(PREPARE_SCHEMAS_ADJM_MTID, adjective_meaning_family *f,adjective_meaning *am, inttask)
-voidAdjectiveMeanings::prepare_schemas(adjective_meaning *am, inttask) {
+voidAdjectiveMeanings::prepare_schemas(adjective_meaning *am, inttask) {VOID_METHOD_CALL(am->family, PREPARE_SCHEMAS_ADJM_MTID, am, task);am->schemas_prepared = TRUE;}
@@ -456,19 +456,19 @@ whether it is able to do this or not.
§14. At last, something simpler. INDEX_ADJM_MTID, if provided, should print
a description suitable for use in the lexicon part of the index, and return
TRUE. If not provided, or it returns FALSE, something sensible is done
@@ -526,7 +526,7 @@ not for one which is the negated form of another.
}
diff --git a/docs/assertions-module/6-amd.html b/docs/assertions-module/7-amd.html
similarity index 94%
rename from docs/assertions-module/6-amd.html
rename to docs/assertions-module/7-amd.html
index 060faabab..61043d14a 100644
--- a/docs/assertions-module/6-amd.html
+++ b/docs/assertions-module/7-amd.html
@@ -88,12 +88,12 @@ MathJax = {
§1. Introduction. Each adjective_meaning structure contains one of these. The "domain" of
+
§1. Introduction. Each adjective_meaning structure contains one of these. The "domain" of
an adjective meaning is the set of values to which it can validly apply. For
example, the meaning of "odd" for numbers has the set of all numbers as its
domain, whereas the sense here:
@@ -130,21 +130,21 @@ and "boojum" is a kind yet to be created, we're stuck.
intproblems_thrown; number of problems thrown about this domain} adjective_domain_data;
-voidAdjectiveMeaningDomains::log(adjective_domain_data *domain) {
+voidAdjectiveMeaningDomains::log(adjective_domain_data *domain) {if (domain->domain_infs == NULL) LOG("domain:'%W'?", domain->domain_text);elseLOG("domain:($j, %u)", domain->domain_infs, domain->domain_kind);}
-
The structure adjective_domain_data is accessed in 6/aa and here.
+
The structure adjective_domain_data is accessed in 7/aa and here.
§5. This variant is useful to catch circularities like "A big container is big
@@ -204,10 +204,10 @@ if...", where the adjective's domain directly or indirectly involves itself:
§7. Finally, then, we can read what we currently believe the kind of the domain
is with the following. Note that:
@@ -357,7 +357,7 @@ is with the following. Note that:
● if the domain is a single instance, we return the kind of that instance.
-kind *AdjectiveMeaningDomains::get_kind(adjective_meaning *am) {
+kind *AdjectiveMeaningDomains::get_kind(adjective_meaning *am) {if (am == NULL) returnNULL;if (am->domain.domain_infs == NULL) returnNULL;returnam->domain.domain_kind;
@@ -385,15 +385,15 @@ inside "object" are treated as just "object", "container" weakly matches "animal
specific instance, then it must definitely lie within the domain.
-intAdjectiveMeaningDomains::weak_match(kind *K1, adjective_meaning *am) {
-kind *K2 = AdjectiveMeaningDomains::get_kind(am);
+intAdjectiveMeaningDomains::weak_match(kind *K1, adjective_meaning *am) {
+kind *K2 = AdjectiveMeaningDomains::get_kind(am);if (RTKinds::weak_id(K1) == RTKinds::weak_id(K2)) returnTRUE;returnFALSE;}
-intAdjectiveMeaningDomains::strong_match(kind *K1, inference_subject *infs,
+intAdjectiveMeaningDomains::strong_match(kind *K1, inference_subject *infs,adjective_meaning *am) {
-if (AdjectiveMeaningDomains::weak_match(K1, am)) {
+if (AdjectiveMeaningDomains::weak_match(K1, am)) {instance *I = InstanceSubjects::to_object_instance(infs);if (I == NULL) returnTRUE;while (infs) {
@@ -405,7 +405,7 @@ specific instance, then it must definitely lie within the domain.
}
§10. The following sorting function is used in the process of sorting the meanings
-of an adjective into precedence order — see AdjectiveAmbiguity::sort.
+of an adjective into precedence order — see AdjectiveAmbiguity::sort.
It takes two domains \(D_1\) and \(D_2\), and returns
@@ -417,7 +417,7 @@ It takes two domains \(D_1\) and \(D_2\), and returns
domains are set up.
↩
§1. Creation propositions. We start with some elementary propositions which create things, by asserting
their existence.
@@ -80,15 +80,15 @@ their existence.
§8.1.1. The node has text in the form "property name property value", with no
obvious division of punctuation between the two. What makes matters worse
is that we do not yet know all the property names, nor do we have the
@@ -317,7 +317,7 @@ that the rest is property name; and otherwise
PW = Wordings::up_to(W, Wordings::first_wn(W) + name_length - 1);VW = Wordings::from(W, Wordings::first_wn(W) + name_length);
-
§8.2. An ADJECTIVE_NT node, on the other hand, is annotated with a valid
property name property already, and may also have a value ready to put
into that property, stored in evaluation. Nodes like this have been
@@ -352,17 +352,17 @@ which is by now inside the "creation proposition".
intnegate_me = FALSE;unary_predicate *pred = Node::get_predicate(p);if (pred == NULL) internal_error("adjective without predicate");
-if (AdjectivalPredicates::parity(pred) == FALSE) negate_me = TRUE;
+if (AdjectivalPredicates::parity(pred) == FALSE) negate_me = TRUE;if (Node::get_creation_proposition(p))prop = Propositions::conjoin(prop, Node::get_creation_proposition(p));
-pcalc_prop *adj_prop = AdjectivalPredicates::new_atom_on_x(
-AdjectivalPredicates::to_adjective(pred), FALSE);
+pcalc_prop *adj_prop = AdjectivalPredicates::new_atom_on_x(
+AdjectivalPredicates::to_adjective(pred), FALSE);if (negate_me) adj_prop = Propositions::negate(adj_prop);prop = Propositions::conjoin(prop, adj_prop);
-
§1. Managing the BPs generated. The relations created in this section belong to the "explicit" family,
named so because their definitions are explicit in the source text. Initially,
@@ -111,20 +111,20 @@ there are none.
-intRelations::Explicit::typecheck(bp_family *self, binary_predicate *bp,
+intRelations::Explicit::typecheck(bp_family *self, binary_predicate *bp,kind **kinds_of_terms, kind **kinds_required, tc_problem_kit *tck) {returnDECLINE_TO_MATCH;}
@@ -248,26 +248,26 @@ to behave as if \(B(y, x)\) had also been asserted whenever \(B(x, y)\) has, if
@@ -304,7 +304,7 @@ to behave as if \(B(y, x)\) had also been asserted whenever \(B(x, y)\) has, if
"to try to put 'Mr Cogito' and 'nothing' into a relationship.");returnTRUE;
-
§8. This routine converts the knowledge that \(R(ox, oy)\) into a single
inference. It can only be used for a simple subclass of the relations:
those which store oy, the only thing related to ox, in a given property
@@ -315,12 +315,12 @@ inferences for \(y\) and \(z\).
§2. Typechecking. This is a very polymorphic relation, in that it can accept terms of almost
@@ -102,7 +102,7 @@ any kind.
-intEqualityDetails::typecheck(bp_family *self, binary_predicate *bp,
+intEqualityDetails::typecheck(bp_family *self, binary_predicate *bp,kind **kinds_of_terms, kind **kinds_required, tc_problem_kit *tck) {LOGIF(MATCHING, "Typecheck %u '==' %u\n", kinds_of_terms[0], kinds_of_terms[1]);if ((K_understanding) && (Kinds::eq(kinds_of_terms[0], K_understanding)) &&
@@ -120,7 +120,7 @@ any kind.
returnALWAYS_MATCH;if ((Kinds::Behaviour::is_object(kinds_of_terms[0])) && (Properties::can_name_coincide_with_kind(kinds_of_terms[1])))
-Apply rule for "is" applied to an object and a value2.1
+Apply rule for "is" applied to an object and a value2.1elseif ((K_understanding) && (Kinds::eq(kinds_of_terms[1], K_understanding)) && (Kinds::eq(kinds_of_terms[0], K_snippet)))returnALWAYS_MATCH;
@@ -131,7 +131,7 @@ any kind.
(Kinds::eq(kinds_of_terms[0], K_response)))returnALWAYS_MATCH;else
-Allow comparison only where left domain and right domain are not disjoint2.2;
+Allow comparison only where left domain and right domain are not disjoint2.2;returnALWAYS_MATCH;}
@@ -158,7 +158,7 @@ for a fairly common mistake:
returnNEVER_MATCH; }
-
§2.2. With comparisons there is no restriction on the two kinds except that they
must match each other; \({\it is}(t, s)\) is allowed if \(K(t)\subseteq K(s)\) or
vice versa. So rules and rulebooks are comparable, for instance, but numbers
@@ -169,11 +169,11 @@ and scenes are not.
diff --git a/docs/assertions-module/P-wtmd.html b/docs/assertions-module/P-wtmd.html
index 180d924a9..e96892a99 100644
--- a/docs/assertions-module/P-wtmd.html
+++ b/docs/assertions-module/P-wtmd.html
@@ -216,13 +216,13 @@ usually wearable" do not immediately lead to propositions being drawn up.
§6. Other gadgets. At the top level, Inform source text consists of more than just assertion
sentences. Rules and phrases are left to imperative to look after, but we
-will take care of Tables (and their Table Columns) here, along with
-the quirkier inclusion of Equations.
+will take care of Tables (and their Table Columns) here, along with
+the quirkier inclusion of Equations.
-
§7. Making use of the calculus module. Chapter 5: Other Gadgets simply stocks up our predicate calculus system with some
+
§7. Making use of the calculus module. Chapter 5: Imperative Code simply stocks up our predicate calculus system with some
basic unary and binary predicates, and provides a few shorthand functions
-to make commonly-needed propositions (see Calculus Utilities).
+to make commonly-needed propositions (see Calculus Utilities).
More specialised predicates will also be added by other modules, so the
@@ -230,7 +230,7 @@ roster here is not complete, but these are the essentials.
Listed-In Relations -
To define the binary predicates corresponding to table columns, and which determine whether a given value is listed in that column.
Calculus Utilities -
Utility functions for creating basic propositions using these predicates.
diff --git a/docs/core-module/1-cp.html b/docs/core-module/1-cp.html
index f67ebe978..11f952e64 100644
--- a/docs/core-module/1-cp.html
+++ b/docs/core-module/1-cp.html
@@ -95,9 +95,11 @@ We begin with core itself.
enumimperative_defn_family_CLASSenumimplication_CLASSenumrelation_guard_CLASS
+enumrule_family_data_CLASSenumtable_CLASSenumtable_column_CLASSenumtable_contribution_CLASS
+enumto_family_data_CLASSenumuse_option_CLASS
@@ -113,9 +115,11 @@ We begin with core itself.
DECLARE_CLASS(imperative_defn_family)DECLARE_CLASS(implication)DECLARE_CLASS(relation_guard)
+DECLARE_CLASS(rule_family_data)DECLARE_CLASS(table)DECLARE_CLASS(table_column)DECLARE_CLASS_ALLOCATED_IN_ARRAYS(table_contribution, 100)
+DECLARE_CLASS(to_family_data)DECLARE_CLASS(use_option)
§3. values —
diff --git a/docs/core-module/3-pc.html b/docs/core-module/3-pc.html
index 0b22f4273..e288f3794 100644
--- a/docs/core-module/3-pc.html
+++ b/docs/core-module/3-pc.html
@@ -260,7 +260,7 @@ this to spot that a sentence will create a new direction.
PLUGINS_CALL(NEW_ASSERTION_NOTIFY_PLUG, p);}
-
§14. Called from The Equality Relation Revisited (in assertions) when we have
to decide if it's valid to ask or declare that two things are the same.
Returning TRUE says that it is always valid; returning FALSE leaves
it to the regular machinery. This plug can therefore only be used to permit
diff --git a/docs/imperative-module/1-im.html b/docs/imperative-module/1-im.html
index bacc6b2fe..f0dff5605 100644
--- a/docs/imperative-module/1-im.html
+++ b/docs/imperative-module/1-im.html
@@ -89,7 +89,7 @@ which use this module:
COMPILE_WRITER(ph_type_data *, Phrases::TypeData::Textual::log)COMPILE_WRITER(local_variable *, LocalVariables::log)COMPILE_WRITER(phrase *, Phrases::log)
-COMPILE_WRITER(ph_usage_data *, Phrases::Usage::log)
+COMPILE_WRITER(ph_usage_data *, Phrases::Usage::log)voidImperativeModule::start(void) {Writers::register_writer('L', &LocalVariables::writer);
@@ -98,7 +98,7 @@ which use this module:
REGISTER_WRITER('h', Phrases::TypeData::Textual::log);REGISTER_WRITER('k', LocalVariables::log);REGISTER_WRITER('R', Phrases::log);
-REGISTER_WRITER('U', Phrases::Usage::log);
+REGISTER_WRITER('U', Phrases::Usage::log);Memory::reason_name(INV_LIST_MREASON, "lists for type-checking invocations");Log::declare_aspect(DESCRIPTION_COMPILATION_DA, L"description compilation", FALSE, FALSE);Log::declare_aspect(EXPRESSIONS_DA, L"expressions", FALSE, FALSE);
diff --git a/docs/imperative-module/2-bl.html b/docs/imperative-module/2-bl.html
index 0a545bdd0..3526dbd7e 100644
--- a/docs/imperative-module/2-bl.html
+++ b/docs/imperative-module/2-bl.html
@@ -404,8 +404,8 @@ BEFORE a FIRST one.)
intBookingLists::is_contextually_empty(booking_list *L, rule_contextrc) {LOOP_OVER_BOOKINGS(br, L) {
-imperative_defn *id = Rules::get_imperative_definition(RuleBookings::get_rule(br));
-if ((id) && (Phrases::Context::phrase_fits_rule_context(id->defines, rc)))
+imperative_defn *id = Rules::get_imperative_definition(RuleBookings::get_rule(br));
+if ((id) && (Phrases::Context::phrase_fits_rule_context(id->defines, rc)))returnFALSE; }returnTRUE;
@@ -432,8 +432,8 @@ BEFORE a FIRST one.)
intBookingLists::contains_ph(booking_list *L, phrase *ph_to_find) {LOOP_OVER_BOOKINGS(br, L) {
-imperative_defn *id = Rules::get_imperative_definition(RuleBookings::get_rule(br));
-if ((id) && (id->defines == ph_to_find))
+imperative_defn *id = Rules::get_imperative_definition(RuleBookings::get_rule(br));
+if ((id) && (id->defines == ph_to_find))returnTRUE; }returnFALSE;
diff --git a/docs/imperative-module/2-rb.html b/docs/imperative-module/2-rb.html
index 51288244e..2141789b9 100644
--- a/docs/imperative-module/2-rb.html
+++ b/docs/imperative-module/2-rb.html
@@ -167,20 +167,20 @@ the rulebook; instead, the booking is marked for automatic placement later on.
-intRuleBookings::cmp(booking *br1, booking *br2, intlog_this) {
+intRuleBookings::cmp(booking *br1, booking *br2, intlog_this) {if ((br1 == NULL) || (br2 == NULL)) internal_error("compared null specificity");if (log_this) LOG("Comparing specificity of rules:\n(1) $b\n(2) $b\n", br1, br2);returnRules::cmp(br1->rule_being_booked, br2->rule_being_booked, log_this);
@@ -218,7 +218,7 @@ is used only for code comments and the index.
structtext_stream *law_applied; name of Law used to sort} booking_commentary;
-booking_commentaryRuleBookings::new_commentary(void) {
+booking_commentaryRuleBookings::new_commentary(void) {booking_commentarybc;bc.next_rule_specificity = 0;bc.tooltip_text = NULL;
@@ -226,7 +226,7 @@ is used only for code comments and the index.
returnbc;}
-voidRuleBookings::comment(OUTPUT_STREAM, booking *br) {
+voidRuleBookings::comment(OUTPUT_STREAM, booking *br) {text_stream *law = br->commentary.law_applied;switch(br->commentary.next_rule_specificity) {case -1: WRITE(" <<< %S <<<", law); break;
diff --git a/docs/imperative-module/2-rlb.html b/docs/imperative-module/2-rlb.html
index 2bd016ece..6398dec60 100644
--- a/docs/imperative-module/2-rlb.html
+++ b/docs/imperative-module/2-rlb.html
@@ -242,12 +242,12 @@ being analogous to a function \(X\to Y\).
-intRulebooks::action_focus(rulebook *B) {
+intRulebooks::action_focus(rulebook *B) {if (B) returnFocusAndOutcome::action_focus(&(B->my_focus));returnFALSE;}
-kind *Rulebooks::get_focus_kind(rulebook *B) {
+kind *Rulebooks::get_focus_kind(rulebook *B) {returnFocusAndOutcome::get_focus_parameter_kind(&(B->my_focus));}
@@ -409,7 +409,7 @@ that action are automatically created, and similarly for activities and scenes.
returnBookingLists::first(B->contents);}
-intRulebooks::runs_during_activities(rulebook *B) {
+intRulebooks::runs_during_activities(rulebook *B) {returnB->runs_during_activities;}
@@ -436,7 +436,7 @@ It marks a rulebook as definitely needing to check the actor.
-voidRulebooks::log_name_only(rulebook *B) {
+voidRulebooks::log_name_only(rulebook *B) {LOG("Rulebook %d (%W)", B->allocation_id, B->primary_name);}
diff --git a/docs/imperative-module/2-rls.html b/docs/imperative-module/2-rls.html
index 392a700f8..59ce6a2c2 100644
--- a/docs/imperative-module/2-rls.html
+++ b/docs/imperative-module/2-rls.html
@@ -108,7 +108,7 @@ different dynamics altogether. In short, then: rules are not phrases.
structkind *kind_of_rule; determined from its rulebook(s)structrulebook *kind_of_rule_set_from;
-structimperative_defn *defn_as_I7_source; if defined by an I7 phrase
+structimperative_defn *defn_as_I7_source; if defined by an I7 phrasestructstacked_variable_owner_list *variables_visible_in_definition; if sostructtext_stream *defn_as_Inter_function; if not
@@ -145,7 +145,7 @@ rule called W,
-voidRules::request_automatic_placement(rule *R) {
+voidRules::request_automatic_placement(rule *R) {if (R->automatic_booking == NULL)R->automatic_booking = RuleBookings::new(R);RuleBookings::request_automatic_placement(R->automatic_booking);
@@ -562,30 +562,30 @@ it's possible to change the way that applicability testing is done.
Each IMPERATIVE node in the syntax tree makes a definition of a phrase or rule.
-
-
§1. When this function starts, the tree contains a number of top-level IMPERATIVE_NT
-nodes with INVOCATION_LIST_NT nodes hanging from them, but we haven't looked at
-any of the text in the IMPERATIVE_NT head nodes and therefore we have no idea what
-they define. Some will be rules, some will define To... phrases, and so on.
-
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_BareTo),
-"'to' what? No name is given",
-"which means that this would not define a new phrase.");
- ==> { FALSE, - };
-
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_DontCallPhrasesWithCalled),
-"phrases aren't named using 'called'",
-"and instead use 'this is...'. For example, 'To salute (called saluting)' "
-"isn't allowed, but 'To salute (this is saluting)' is.");
- ==> { FALSE, - };
-
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_NamelessRule),
-"there are many rules in Inform",
-"so you need to give a name: 'this is the abolish dancing rule', say, "
-"not just 'this is the rule'.");
- ==> { FALSE, - }
-
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UnarticledRule),
-"a rule must be given a definite name",
-"which begins with 'the', just to emphasise that it is the only one "
-"with this name: 'this is the promote dancing rule', say, not just "
-"'this is promote dancing rule'.");
- ==> { FALSE, - }
-
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_PluralisedRule),
-"a rule must be given a definite name ending in 'rule' not 'rules'",
-"since the plural is only used for rulebooks, which can of course "
-"contain many rules at once.");
- ==> { FALSE, - }
-
§13. The rulebooks are now complete and final. It is time to
-compile the Inter code which will provide the run-time definitions of all
-these phrases. This will be a long task, and we can only do most of it now,
-because more phrases will appear later.
-
§13.4. This doesn't compile all adjective definitions, only the ones which supply
-a whole multi-step phrase to define them — a relatively little-used feature
-of Inform.
-
§13.5. As we'll see, it's legal in Inform to define "To..." phrases with vague
-kinds: "To expose (X - a value)", for example. This can't be compiled as
-vaguely as the definition implies, since there would be no way to know how
-to store X. Instead, for each different kind of X which is actually needed,
-a fresh version of the phrase is compiled — one where X is a number, one
-where it's a text, and so on. This is handled by making a "request" for the
-phrase, indicating that a compiled version of it will be needed.
-
-
-
Since "To..." phrases are only compiled on request, we must remember to
-request the boring ones with straightforward kinds ("To award (N - a number)
-points", say). This is where we do it:
-
-
-
Mark To... phrases which have definite kinds for future compilation13.5 =
-
§13.6. Throw problems for phrases with return kinds too vaguely defined13.6 =
-
-
-
-phrase *ph;
-LOOP_OVER(ph, phrase) {
-kind *KR = Phrases::TypeData::get_return_kind(&(ph->type_data));
-if ((Kinds::Behaviour::semidefinite(KR) == FALSE) &&
- (Phrases::TypeData::arithmetic_operation(ph) == -1)) {
-current_sentence = Phrases::declaration_node(ph);
-Problems::quote_source(1, current_sentence);
-StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ReturnKindVague));
-Problems::issue_problem_segment(
-"The declaration %1 tries to set up a phrase which decides a "
-"value which is too vaguely described. For example, 'To decide "
-"which number is the target: ...' is fine, because 'number' "
-"is clear about what kind of value should emerge; but 'To "
-"decide which value is the target: ...' is not clear enough.");
-Problems::issue_problem_end();
- }
-for (intk=1; k<=26; k++)
-if ((Kinds::Behaviour::involves_var(KR, k)) &&
- (Phrases::TypeData::tokens_contain_variable(&(ph->type_data), k) == FALSE)) {
-current_sentence = Phrases::declaration_node(ph);
-TEMPORARY_TEXT(var_letter)
-PUT_TO(var_letter, 'A'+k-1);
-Problems::quote_source(1, current_sentence);
-Problems::quote_stream(2, var_letter);
-StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ReturnKindUndetermined));
-Problems::issue_problem_segment(
-"The declaration %1 tries to set up a phrase which decides a "
-"value which is too vaguely described, because it involves "
-"a kind variable (%2) which it can't determine through "
-"usage.");
-Problems::issue_problem_end();
-DISCARD_TEXT(var_letter)
- }
- }
-
§13.7. Throw problems for inline phrases named as constants13.7 =
-
-
-
-phrase *ph;
-LOOP_OVER(ph, phrase)
-if ((Phrases::TypeData::invoked_inline(ph)) &&
- (Phrases::Usage::has_name_as_constant(&(ph->usage_data)))) {
-current_sentence = Phrases::declaration_node(ph);
-Problems::quote_source(1, current_sentence);
-StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NamedInline));
-Problems::issue_problem_segment(
-"The declaration %1 tries to give a name to a phrase which is "
-"defined using inline Inform 6 code in (- markers -). Such "
-"phrases can't be named and used as constants because they "
-"have no independent existence, being instead made fresh "
-"each time they are used.");
-Problems::issue_problem_end();
- }
-
§14. The twilight gathers, but our work is far from done. Recall that we have
-accumulated compilation requests for "To..." phrases, but haven't actually
-acted on them yet.
-
-
-
We have to do this in quite an open-ended way, because compiling one phrase
-can easily generate fresh requests for others. For instance, suppose we have
-the definition "To expose (X - a value)" in play, and suppose that when
-compiling the phrase "To advertise", Inform runs into the line "expose the
-hoarding text". This causes it to issue a compilation request for "To expose
-(X - a text)". Perhaps we've compiled such a form already, but perhaps we
-haven't. Compilation therefore goes on until all requests have been dealt
-with.
-
-
-
Compiling phrases also produces the need for other pieces of code to be
-generated — for example, suppose our phrase being compiled, "To advertise",
-includes the text:
-
-
-
-
let Z be "Two for the price of one! Just [expose price]!";
-
-
-
We are going to need to compile "Two for the price of one! Just [expose price]!"
-later on, in its own text substitution routine; but notice that it contains
-the need for "To expose (X - a number)", and that will generate a further
-phrase request.
-
-
-
Because of this and similar problems, it's impossible to compile all the
-phrases alone: we must compile phrases, then things arising from them, then
-phrases arising from those, then things arising from the phrases arising
-from those, and so on, until we're done. The process is therefore structured
-as a set of "coroutines" which each carry out as much as they can and then
-hand over to the others to generate more work.
-
-
-
-
-
-
-
diff --git a/docs/imperative-module/3-itp.html b/docs/imperative-module/3-itp.html
index afbc8e6dd..388154e57 100644
--- a/docs/imperative-module/3-itp.html
+++ b/docs/imperative-module/3-itp.html
@@ -228,7 +228,7 @@ significant timing difficulties.
diff --git a/docs/imperative-module/3-pav.html b/docs/imperative-module/3-pav.html
index eed3184e6..d41c17ffd 100644
--- a/docs/imperative-module/3-pav.html
+++ b/docs/imperative-module/3-pav.html
@@ -98,7 +98,7 @@ own right, a functional-programming sort of device. For example:
-constant_phrase *Phrases::Constants::create(wordingNW, wordingRW) {
+constant_phrase *Phrases::Constants::create(wordingNW, wordingRW) {constant_phrase *cphr = CREATE(constant_phrase);cphr->phrase_meant = NULL; we won't know until latercphr->cphr_kind = NULL; nor this
@@ -113,7 +113,7 @@ own right, a functional-programming sort of device. For example:
-constant_phrase *Phrases::Constants::parse(wordingNW) {
+constant_phrase *Phrases::Constants::parse(wordingNW) {if (<s-value>(NW)) {parse_node *spec = <<rp>>;if (Rvalues::is_CONSTANT_construction(spec, CON_phrase)) {
@@ -132,7 +132,7 @@ the following takes a patch-it-later approach.
typedefstructphrase {
-structimperative_defn *from;
+structimperative_defn *from;intinline_wn; word number of inline I6 definition, or -1 if not inlinestructinter_schema *inter_head_defn; inline definition translated to inter, if possible
@@ -133,7 +133,7 @@ code below.
CLASS_DEFINITION} phrase;
-
The structure phrase is accessed in 2/rls, 2/rb, 3/id, 3/pu, 3/prcd, 3/ptd, 3/dptd, 3/po, 3/pav, 3/tph, 3/tp, 6/inv, 6/pi, 6/ci, 6/cii, 6/cp, 6/cste and here.
+
The structure phrase is accessed in 2/rls, 2/rb, 3/pu, 3/prcd, 3/ptd, 3/dptd, 3/po, 3/pav, 3/tph, 3/tp, 6/inv, 6/pi, 6/ci, 6/cii, 6/cp, 6/cste and here.
§4. "To..." phrases, though no others, are listed in logical precedence order:
@@ -149,8 +149,8 @@ invocation which is given as verbatim I6.
-voidPhrases::create_from_preamble(imperative_defn *id) {
-parse_node *p = id->at;
+voidPhrases::create_from_preamble(imperative_defn *id) {
+parse_node *p = id->at;if ((p == NULL) || (Node::get_type(p) != IMPERATIVE_NT))internal_error("a phrase preamble should be at a IMPERATIVE_NT node");intinline_wn = -1; the word number of an inline I6 definition if any
@@ -170,7 +170,7 @@ invocation which is given as verbatim I6.
if ((inline_wn >= 0) && (id->family != TO_PHRASE_EFF_family)) Inline is for To... phrases only5.10;
-if ((id->family != DEFINITIONAL_PHRASE_EFF_family) && (p->down == NULL))
+if ((id->family != DEFINITIONAL_PHRASE_EFF_family) && (p->down == NULL))There seems to be no definition5.9;Construct the PHTD, find the phrase options, find the documentation reference5.3;
@@ -180,7 +180,7 @@ invocation which is given as verbatim I6.
phrase *new_ph;Create the phrase structure5.8;
-id->defines = new_ph;
+id->defines = new_ph;Tell other parts of Inform about this new phrase5.7;}
@@ -202,20 +202,20 @@ invocation which is given as verbatim I6.
§5.7.1. If a phrase defines an adjective, like so:
-
-
-
-
Definition: A container is capacious if: ...
-
-
-
we need to make the pronoun "it" a local variable of kind "container" in the
-stack frame used to compile the "..." part. If it uses a calling, like so:
-
-
-
-
Definition: A container (called the sack) is capacious if: ...
-
-
-
then we also want the name "sack" to refer to this. Here's where we take care
-of it:
-
-
-
Give this phrase a local variable for the subject of the definition5.7.1 =
-
-voidPhrases::parse_possible_inline_defn(wordingW, int *wn, int *mor) {
+voidPhrases::parse_possible_inline_defn(wordingW, int *wn, int *mor) {LOGIF(MATCHING, "form of inline: %W\n", W); *wn = -1;if (<inline-phrase-definition>(W)) { *wn = <<inlinecode>>; *mor = <<r>>; }
@@ -427,13 +383,13 @@ what number is...", for instance.
§11. Compilation. The following is called to give us an opportunity to compile a routine defining
@@ -503,10 +459,10 @@ response to "requests". All other phrases are compiled just once.
ph->imported = TRUE;}
-voidPhrases::compile(phrase *ph, int *i, intmax_i,
+voidPhrases::compile(phrase *ph, int *i, intmax_i,stacked_variable_owner_list *legible, to_phrase_request *req, rule *R) {if (ph->imported) return;
-if (ph->from->family == TO_PHRASE_EFF_family) {
+if (ph->from->family == TO_PHRASE_EFF_family) {Routines::Compile::routine(ph, legible, req, R);Move along the progress bar if it's this phrase's first compilation11.1; } elseif (ph->at_least_one_compiled_form_needed) {
@@ -571,7 +527,7 @@ response to "requests". All other phrases are compiled just once.
}
diff --git a/docs/imperative-module/3-po.html b/docs/imperative-module/3-po.html
index d2a497a53..2bfe76292 100644
--- a/docs/imperative-module/3-po.html
+++ b/docs/imperative-module/3-po.html
@@ -407,7 +407,7 @@ by "and":
diff --git a/docs/imperative-module/3-prcd.html b/docs/imperative-module/3-prcd.html
index af7344b04..eae7928d8 100644
--- a/docs/imperative-module/3-prcd.html
+++ b/docs/imperative-module/3-prcd.html
@@ -182,7 +182,7 @@ the following only blanks out a PHRCD structure ready for that to happen.
The structure activity_list is accessed in 2/rlb, 2/act, 3/id, 3/phr, 3/tph, 3/tp, 4/lv, 4/sv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
+
The structure activity_list is accessed in 2/rlb, 2/act, 3/phr, 3/tph, 3/tp, 4/lv, 4/sv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
§11. Run-time contexts are seen in the "while" clauses at the end of rules.
For example:
@@ -902,7 +902,7 @@ values, of the kind to which the activity applies.
}
diff --git a/docs/imperative-module/3-ptd.html b/docs/imperative-module/3-ptd.html
index d8cc32dbc..24e114f62 100644
--- a/docs/imperative-module/3-ptd.html
+++ b/docs/imperative-module/3-ptd.html
@@ -326,7 +326,7 @@ whistles and doodads which regular phrases don't.
returnphtd->manner_of_return;}
-kind *Phrases::TypeData::get_return_kind(ph_type_data *phtd) {
+kind *Phrases::TypeData::get_return_kind(ph_type_data *phtd) {if (phtd->manner_of_return == DECIDES_CONDITION_MOR) returnK_truth_state;returnphtd->return_kind;}
@@ -403,7 +403,7 @@ logic, since one argument is in effect a kind rather than a value.)
-kind *Phrases::TypeData::kind(ph_type_data *phtd) {
+kind *Phrases::TypeData::kind(ph_type_data *phtd) {kind *argument_kinds[MAX_TOKENS_PER_PHRASE];inti, j = 0;for (i=0; i<phtd->no_tokens; i++)
@@ -427,7 +427,7 @@ logic, since one argument is in effect a kind rather than a value.)
-intPhrases::TypeData::tokens_contain_variable(ph_type_data *phtd, intv) {
+intPhrases::TypeData::tokens_contain_variable(ph_type_data *phtd, intv) {for (inti=0; i<phtd->no_tokens; i++)if (Kinds::Behaviour::involves_var(phtd->token_sequence[i].token_kind, v))returnTRUE;
@@ -437,7 +437,7 @@ logic, since one argument is in effect a kind rather than a value.)
@@ -528,7 +528,7 @@ variables "new entry" and "L" with those kinds.
-voidPhrases::TypeData::into_stack_frame(ph_stack_frame *phsf,
+voidPhrases::TypeData::into_stack_frame(ph_stack_frame *phsf,ph_type_data *phtd, kind *kind_in_this_compilation, intfirst) {if (Kinds::get_construct(kind_in_this_compilation) != CON_phrase)internal_error("no function kind");
@@ -558,7 +558,7 @@ see Phrases for the return codes.
-intPhrases::TypeData::comparison(ph_type_data *phtd1, ph_type_data *phtd2) {
+intPhrases::TypeData::comparison(ph_type_data *phtd1, ph_type_data *phtd2) {if (phtd1 == phtd2) returnEQUAL_PH;
@@ -738,7 +738,7 @@ variable" is more specific than "new variable", which isn't helpful.
defineTHE_PRIMORDIAL_SAY_PHRASE2
-say_detailsPhrases::TypeData::new_say_details(void) {
+say_detailsPhrases::TypeData::new_say_details(void) {say_detailssd;sd.say_phrase = NOT_A_SAY_PHRASE;sd.say_phrase_running_on = FALSE;
@@ -751,7 +751,7 @@ variable" is more specific than "new variable", which isn't helpful.
intfirst_say_made = FALSE;
-voidPhrases::TypeData::make_sd(say_details *sd, intro, intcs, intpos, intat, intcat) {
+voidPhrases::TypeData::make_sd(say_details *sd, intro, intcs, intpos, intat, intcat) {sd->say_phrase = A_MISCELLANEOUS_SAY_PHRASE;if (first_say_made == FALSE) {sd->say_phrase = THE_PRIMORDIAL_SAY_PHRASE;
@@ -764,7 +764,7 @@ variable" is more specific than "new variable", which isn't helpful.
if (cat >= 0) sd->say_phrase_stream_closing_token_at = cat;}
-voidPhrases::TypeData::log_say_details(say_detailssd) {
+voidPhrases::TypeData::log_say_details(say_detailssd) {switch (sd.say_phrase) {caseNOT_A_SAY_PHRASE:break;caseA_MISCELLANEOUS_SAY_PHRASE:LOG(" A_MISCELLANEOUS_SAY_PHRASE\n"); break;
@@ -783,7 +783,7 @@ variable" is more specific than "new variable", which isn't helpful.
}}
-intPhrases::TypeData::is_a_say_phrase(phrase *ph) {
+intPhrases::TypeData::is_a_say_phrase(phrase *ph) {if ((ph) && (ph->type_data.as_say.say_phrase)) returnTRUE;returnFALSE;}
@@ -810,7 +810,7 @@ variable" is more specific than "new variable", which isn't helpful.
returnFALSE;}
-voidPhrases::TypeData::get_say_data(say_details *sd,
+voidPhrases::TypeData::get_say_data(say_details *sd,int *say_cs, int *ssp_tok, int *ssp_ctok, int *ssp_pos) { *say_cs = sd->say_control_structure; *ssp_tok = sd->say_phrase_stream_token_at;
@@ -818,7 +818,7 @@ variable" is more specific than "new variable", which isn't helpful.
*ssp_pos = sd->say_phrase_stream_position;}
-intPhrases::TypeData::preface_for_say_HTML(OUTPUT_STREAM, say_detailssd, intpaste_format) {
+intPhrases::TypeData::preface_for_say_HTML(OUTPUT_STREAM, say_detailssd, intpaste_format) {if (sd.say_phrase) {if (sd.say_phrase != THE_PRIMORDIAL_SAY_PHRASE) {switch (paste_format) {
@@ -836,7 +836,7 @@ variable" is more specific than "new variable", which isn't helpful.
returnFALSE;}
-voidPhrases::TypeData::epilogue_for_say_HTML(OUTPUT_STREAM, say_detailssd, intpaste_format) {
+voidPhrases::TypeData::epilogue_for_say_HTML(OUTPUT_STREAM, say_detailssd, intpaste_format) {if (sd.say_phrase) {if (sd.say_phrase != THE_PRIMORDIAL_SAY_PHRASE) {if (paste_format == PASTE_PHRASE_FORMAT) WRITE("]");
@@ -847,7 +847,7 @@ variable" is more specific than "new variable", which isn't helpful.
}}
-intPhrases::TypeData::ssp_matches(ph_type_data *phtd, intssp_tok, intlist_pos,
+intPhrases::TypeData::ssp_matches(ph_type_data *phtd, intssp_tok, intlist_pos,wording *W) {intthis_tok = phtd->as_say.say_phrase_stream_token_at;intthis_pos = phtd->as_say.say_phrase_stream_position;
@@ -869,7 +869,7 @@ by than name.
defineLOOP_BODY_BLOCK_FOLLOWS3
-inline_detailsPhrases::TypeData::new_inline_details(void) {
+inline_detailsPhrases::TypeData::new_inline_details(void) {inline_detailsid;id.invoked_inline_not_as_call = FALSE;
@@ -888,7 +888,7 @@ by than name.
-voidPhrases::TypeData::log_inline_details(inline_detailsid) {
+voidPhrases::TypeData::log_inline_details(inline_detailsid) {if (id.block_follows) LOG(" block follows\n");if (id.let_phrase != NOT_A_LET_PHRASE) LOG(" let phrase (%d)\n", id.let_phrase);if (id.only_in_loop) LOG(" may only be used in a %w body\n", id.only_in_loop);
@@ -914,11 +914,11 @@ by than name.
To parse the preamble of a phrase declaration to a phrase usage (PHUD) structure containing a mostly textual representation of the conditions for its usage.
typedefstructph_usage_data {
-structimperative_defn *from;
+structimperative_defn *from;structwordingfull_preamble; e.g. to identify nameless rules in the logstructconstant_phrase *constant_phrase_holder; for named To... phrasesintto_begin; used in Basic mode only: this is to be the main phrase
@@ -100,7 +100,7 @@ function togglePopup(material_id) {
intowning_rulebook_placement; ...and with this placement value: see Rulebooks} ph_usage_data;
-
The structure ph_usage_data is accessed in 3/id, 3/phr, 3/dptd, 3/pav, 3/tph, 3/tp, 6/cp and here.
+
The structure ph_usage_data is accessed in 3/phr, 3/dptd, 3/pav, 3/tph, 3/tp, 6/cp and here.
§2. The late-morning creations. A little later on, we've made a rule phrase, and it now has a proper PHUD.
If the rule is an anonymous one, such as:
@@ -122,7 +122,7 @@ connect this existing one to the phrase.
-rule *Phrases::Usage::to_rule(ph_usage_data *phud, imperative_defn *id) {
+rule *Phrases::Usage::to_rule(ph_usage_data *phud, imperative_defn *id) {wordingW = EMPTY_WORDING;intexplicitly = FALSE;Find the name of the phrase, and whether or not it's explicitly given2.1;
@@ -132,9 +132,9 @@ connect this existing one to the phrase.
if (R) Check that this isn't duplicating the name of a rule already made2.2elseR = Rules::obtain(W, explicitly);if (Wordings::empty(W))
-Hierarchy::markup_wording(R->compilation_data.rule_package, RULE_NAME_HMD, Node::get_text(id->at));
+Hierarchy::markup_wording(R->compilation_data.rule_package, RULE_NAME_HMD, Node::get_text(id->at));Rules::set_imperative_definition(R, id);
-phrase *ph = id->defines;
+phrase *ph = id->defines;package_request *P = RTRules::package(R);ph->ph_iname = Hierarchy::make_localised_iname_in(RULE_FN_HL, P, ph->owning_module);
@@ -159,7 +159,7 @@ connect this existing one to the phrase.
-imperative_defn *existing_id = Rules::get_imperative_definition(R);
+imperative_defn *existing_id = Rules::get_imperative_definition(R);if ((existing_id) && (existing_id != id)) {Problems::quote_source(1, current_sentence);Problems::quote_wording(2, W);
@@ -199,45 +199,26 @@ just enough from the wording to tell what sort of rule/phrase is to follow.
§4. As a safety measure, to avoid ambiguities, Inform only allows one phrase
-definition to begin with "now". It recognises such phrases as those whose
-preambles match:
-
§6. Much later on, Inform returns to the definition. If the preamble matches
+
§4. Much later on, Inform returns to the definition. If the preamble matches
either of the final two productions of <rule-preamble>, then we definitely
have a rule rather than a phrase definition or a timed event; and in that
case the rule's preamble (without its name, if given) has to match the
@@ -267,7 +248,7 @@ following grammar. (Parsing this is "fine mode".)
rule==> { FALSE, - }
§7. The following turns the preamble text into a PHUD. It can be used as often
+
§5. The following turns the preamble text into a PHUD. It can be used as often
as necessary in "coarse mode", but should be run once and once only on any
given phrase when in "fine mode".
-phud.rule_preamble = W;
-
-if (<<named>>) The preamble parses to a named To phrase7.2.1;
-if (<now-phrase-preamble>(W)) {
-if (no_now_phrases++ == 1) {
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RedefinedNow),
-"creating new variants on 'now' is not allowed",
-"because 'now' plays a special role in the language. "
-"It has a wide-ranging ability to make a condition "
-"become immediately true. (To give it wider abilities, "
-"the idea is to create new relations.)");
- }
- }
-if (<begin-phrase-preamble>(W)) {
-phud.to_begin = TRUE;
- }
-
§7.2.1. When we parse a named phrase in coarse mode, we need to make sure that
-name is registered as a constant value; when we parse it again in fine
-mode, we can get that value back again if we look it up by name.
-
-
-
The preamble parses to a named To phrase7.2.1 =
-
-
-
-wordingRW = GET_RW(<rule-preamble>, 1);
-wordingNW = GET_RW(<rule-preamble>, 2);
-
-if (coarse_mode) {
-if (<s-type-expression>(NW)) {
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_PhraseNameDuplicated),
-"that name for this new phrase is not allowed",
-"because it already has a meaning.");
- }
-phud.constant_phrase_holder = Phrases::Constants::parse(NW);
-if (phud.constant_phrase_holder == NULL)
-phud.constant_phrase_holder =
-Phrases::Constants::create(NW, RW);
- } else {
-constant_phrase *cphr = Phrases::Constants::parse(NW);
-if (Kinds::Behaviour::definite(cphr->cphr_kind) == FALSE) {
-phrase *ph = Phrases::Constants::as_phrase(cphr);
-if (ph) current_sentence = Phrases::declaration_node(ph);
-Problems::quote_source(1, Diagrams::new_UNPARSED_NOUN(Nouns::nominative_singular(cphr->name)));
-Problems::quote_wording(2, Nouns::nominative_singular(cphr->name));
-StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NamedGeneric));
-Problems::issue_problem_segment(
-"I can't allow %1, because the phrase it gives a name to "
-"is generic, that is, it has a kind which is too vague. "
-"That means there isn't any single phrase which '%2' "
-"could refer to - there would have to be different versions "
-"for every setting where it might be needed, and we can't "
-"predict in advance which one '%2' might need to be.");
-Problems::issue_problem_end();
-LOG("CPHR failed at %d, %u\n", cphr->allocation_id, cphr->cphr_kind);
- }
-if (<<written>>) {
-phud.explicit_name_used_in_maths = TRUE;
-if (<<inverted>>) {
-wordingIW = GET_RW(<rule-preamble>, 3);
-phud.explicit_name_for_inverse = Wordings::first_word(IW);
- }
- }
-phud.constant_phrase_holder = cphr;
- }
-phud.rule_preamble = RW;
-
@@ -566,8 +473,8 @@ of the stem, so we have to be very careful:
"by some description of the action or value to apply to (e.g. ""'Instead of taking something:' or 'Every turn:').");
§5.2.1.2. Disallow the definite article for anonymous rules5.2.1.2 =
@@ -578,17 +485,17 @@ of the stem, so we have to be very careful:
"so (e.g.) 'the before rule: ...' is disallowed; you should ""write 'a before rule: ...' instead.");
§16. How the PHUD translates into a PHRCD. Recall that in the early afternoon, the PHUD for a rule phrase is translated
+
§14. How the PHUD translates into a PHRCD. Recall that in the early afternoon, the PHUD for a rule phrase is translated
into a PHRCD, that is, a set of instructions about the circumstances for
the rule to fire.
@@ -743,31 +650,31 @@ seen problems in Inform. A couple of variables are needed just for that:
intNAP_problem_explained = FALSE; pertains to Named Action Patternsintissuing_ANL_problem = FALSE; pertains to Action Name Lists
-
§17.
+
§15.
-ph_runtime_context_dataPhrases::Usage::to_runtime_context_data(ph_usage_data *phud) {
+ph_runtime_context_dataPhrases::Usage::to_runtime_context_data(ph_usage_data *phud) {ph_runtime_context_dataphrcd = Phrases::Context::new();
-if (phud->from->family == RULE_NOT_IN_RULEBOOK_EFF_family)
-phrcd.permit_all_outcomes = TRUE;
-
-if (phud->from->family == RULE_IN_RULEBOOK_EFF_family)
-Finish work parsing the conditions for the rule to fire17.1;
-
+if (RuleFamily::is(phud->from)) {
+if (RuleFamily::not_in_rulebook(phud->from))
+phrcd.permit_all_outcomes = TRUE;
+else
+Finish work parsing the conditions for the rule to fire15.1;
+ }returnphrcd;}
-
§17.1. All of this is just dumb copying...
+
§15.1. All of this is just dumb copying...
-
Finish work parsing the conditions for the rule to fire17.1 =
+
Finish work parsing the conditions for the rule to fire15.1 =
phrcd.compile_for_rulebook = &(phud->owning_rulebook);
-if (Wordings::nonempty(phud->rule_parameter)) Parse what used to be the bud into the PHRCD17.1.1;
+if (Wordings::nonempty(phud->rule_parameter)) Parse what used to be the bud into the PHRCD15.1.1;if (Wordings::nonempty(phud->whenwhile)) {phrcd.activity_context =
@@ -781,11 +688,11 @@ seen problems in Inform. A couple of variables are needed just for that:
if (phud->during_scene_spec) phrcd.during_scene = phud->during_scene_spec; #endif
§15.1.1.1. All that's left is to issue a "good" problem message, but this is quite
a large undertaking, because the situation as we currently know it is just
that something's wrong with the rule preamble — which covers an enormous
range of different faults.
@@ -833,26 +740,26 @@ range of different faults.
parser, recording how it most recently failed.
-
Issue a problem message for a bad action17.1.1.1 =
+
Issue a problem message for a bad action15.1.1.1 =
@@ -901,8 +808,8 @@ parser, recording how it most recently failed.
"would make different use of objects from each other.)");Problems::issue_problem_end();
@@ -940,8 +847,8 @@ parser, recording how it most recently failed.
"location'; but the same thing with '...and when Peter is...' is not allowed.");Problems::issue_problem_end();
§15.1.1.1.5.3. If the action pattern contains what looks like a list of action names, as
for example
@@ -1008,7 +915,7 @@ apparent number of action names. We then run the grammar again, but this time
allowing it to print comments on each apparent action name it sees.
-
Break down the action list and say which are okay17.1.1.1.5.3 =
+
Break down the action list and say which are okay15.1.1.1.5.3 =
@@ -1029,37 +936,37 @@ allowing it to print comments on each apparent action name it sees.
Problems::issue_problem_segment(" so"); }
@@ -1069,8 +976,8 @@ is used to choose a problem message if the value makes no sense.
"special rulebooks, 'When play begins' and 'When play ends', ""and I think you probably mean to refer to one of those.");
@@ -1081,18 +988,18 @@ is used to choose a problem message if the value makes no sense.
"that should have described %3.");Problems::issue_problem_end();
§19. The following is used to choose a problem when the trouble with the rule
occurred in a when/while condition at the end; while all five cases produce
the PM_APWithBadWhen problem, they each provide different clues as to what
might have gone wrong.
@@ -1139,7 +1046,7 @@ might have gone wrong.
...{when/while...}==> { 5, -, <<cw1>> = Wordings::first_wn(WR[2]), <<cw2>> = Wordings::last_wn(WR[2]) }
diff --git a/docs/imperative-module/3-tp.html b/docs/imperative-module/3-tp.html
index 3c5e7b718..4b7b40f8c 100644
--- a/docs/imperative-module/3-tp.html
+++ b/docs/imperative-module/3-tp.html
@@ -92,7 +92,7 @@ defined as "At 9:00 AM: ..." But two values are special:
CLASS_DEFINITION} use_as_event;
-
The structure use_as_event is accessed in 2/rlb, 2/act, 3/id, 3/phr, 3/prcd, 3/tph, 4/lv, 4/sv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
+
The structure use_as_event is accessed in 2/rlb, 2/act, 3/phr, 3/prcd, 3/tph, 4/lv, 4/sv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
§3. Timed events are stored in two simple arrays, processed by run-time code.
@@ -103,7 +103,7 @@ defined as "At 9:00 AM: ..." But two values are special:
intwhen_count = 0;phrase *ph;LOOP_OVER(ph, phrase) {
-intt = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
+intt = Phrases::Usage::get_timing_of_event(&(ph->usage_data));if (t == NOT_A_TIMED_EVENT) continue;if (t == NO_FIXED_TIME) when_count++;elseEmit::array_iname_entry(Phrases::iname(ph));
@@ -123,7 +123,7 @@ defined as "At 9:00 AM: ..." But two values are special:
intwhen_count = 0;phrase *ph;LOOP_OVER(ph, phrase) {
-intt = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
+intt = Phrases::Usage::get_timing_of_event(&(ph->usage_data));if (t == NOT_A_TIMED_EVENT) continue;if (t == NO_FIXED_TIME) when_count++;elseEmit::array_numeric_entry((inter_ti) t);
@@ -142,7 +142,7 @@ defined as "At 9:00 AM: ..." But two values are special:
voidPhrases::Timed::note_usage(phrase *ph, parse_node *at) {
-intt = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
+intt = Phrases::Usage::get_timing_of_event(&(ph->usage_data));if (t == NO_FIXED_TIME) {use_as_event *uae = CREATE(use_as_event);uae->where_triggered = at;
@@ -164,9 +164,9 @@ arguably shouldn't block compilation. Then again...
voidPhrases::Timed::check_for_unused(void) {phrase *ph;LOOP_OVER(ph, phrase)
-if (Phrases::Usage::get_timing_of_event(&(ph->usage_data)) == NO_FIXED_TIME) {
+if (Phrases::Usage::get_timing_of_event(&(ph->usage_data)) == NO_FIXED_TIME) {if (ph->usage_data.uses_as_event == NULL) {
-current_sentence = ph->from->at;
+current_sentence = ph->from->at;StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UnusedTimedEvent),"this sets up a timed event which is never used","since you never use any of the phrases which could cause it. "
@@ -195,7 +195,7 @@ arguably shouldn't block compilation. Then again...
-voidRoutines::ToPhrases::new(phrase *ph) {
+voidRoutines::ToPhrases::new(phrase *ph) {phrase *previous_phrase = NULL;phrase *current_phrase = first_in_logical_order;ph->requests_package = Hierarchy::package(ph->owning_module, PHRASES_HAP);
@@ -189,17 +189,17 @@ reasons, that is, to make the compiled code more legible.
-voidRoutines::ToPhrases::register_all(void) {
+voidRoutines::ToPhrases::register_all(void) {phrase *ph;intc = 0;for (ph = first_in_logical_order; ph; ph = ph->next_in_logical_order) {
-current_sentence = ph->from->at;
+current_sentence = ph->from->at;Phrases::Parser::register_excerpt(ph);ph->sequence_count = c++; }}
-intRoutines::ToPhrases::sequence_count(phrase *ph) {
+intRoutines::ToPhrases::sequence_count(phrase *ph) {if (ph == NULL) return0;if (ph->sequence_count == -1) {Phrases::log(ph);
@@ -234,7 +234,7 @@ values in force, so that there is no possible ambiguity in how we read K.
-to_phrase_request *Routines::ToPhrases::make_request(phrase *ph, kind *K,
+to_phrase_request *Routines::ToPhrases::make_request(phrase *ph, kind *K,kind_variable_declaration *kvd, wordingW) {if ((ph == NULL) || (K == NULL)) internal_error("bad request");
@@ -252,7 +252,7 @@ values in force, so that there is no possible ambiguity in how we read K.
req->requested_exact_kind = K;req->requested_phrase = ph;compilation_unit *cm = CompilationUnits::current();
-if (ph->from->at) cm = CompilationUnits::find(ph->from->at);
+if (ph->from->at) cm = CompilationUnits::find(ph->from->at);package_request *P = Hierarchy::package_within(REQUESTS_HAP, ph->requests_package);req->req_iname = Hierarchy::make_localised_iname_in(PHRASE_FN_HL, P, cm);
@@ -296,7 +296,7 @@ I6 routine.
-inter_name *Routines::ToPhrases::make_iname(phrase *ph, kind *req_kind) {
+inter_name *Routines::ToPhrases::make_iname(phrase *ph, kind *req_kind) {if (Phrases::TypeData::invoked_inline(ph)) {TEMPORARY_TEXT(identifier)wchar_t *p = Phrases::get_inline_definition(ph);
@@ -338,7 +338,7 @@ since the last time it was called.
to_phrase_request *latest_request_granted = NULL;
-intRoutines::ToPhrases::compilation_coroutine(int *i, intmax_i) {
+intRoutines::ToPhrases::compilation_coroutine(int *i, intmax_i) {intN = 0;while (TRUE) {to_phrase_request *req;
@@ -359,7 +359,7 @@ to write a comment about this:
-voidRoutines::ToPhrases::comment_on_request(to_phrase_request *req) {
+voidRoutines::ToPhrases::comment_on_request(to_phrase_request *req) {if (req == NULL) Produce::comment(Emit::tree(), I"No specific request");else {TEMPORARY_TEXT(C)
@@ -374,12 +374,12 @@ to write a comment about this:
-kind *Routines::ToPhrases::kind_of_request(to_phrase_request *req) {
+kind *Routines::ToPhrases::kind_of_request(to_phrase_request *req) {if (req == NULL) internal_error("null request");returnreq->requested_exact_kind;}
-kind **Routines::ToPhrases::kind_variables_for_request(to_phrase_request *req) {
+kind **Routines::ToPhrases::kind_variables_for_request(to_phrase_request *req) {if (req == NULL) internal_error("null request");returnreq->kind_variables_interpretation;}
@@ -403,7 +403,7 @@ is confined to the current Chapter.
}
diff --git a/docs/imperative-module/4-lv.html b/docs/imperative-module/4-lv.html
index a3523605b..6285ed147 100644
--- a/docs/imperative-module/4-lv.html
+++ b/docs/imperative-module/4-lv.html
@@ -148,7 +148,7 @@ marks it as deallocated.
CLASS_DEFINITION} local_variable;
-
The structure local_variable is accessed in 2/rlb, 2/act, 3/id, 3/phr, 3/prcd, 3/tph, 3/tp, 4/sv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
+
The structure local_variable is accessed in 2/rlb, 2/act, 3/phr, 3/prcd, 3/tph, 3/tp, 4/sv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
§3. A local variable needs to be stored somewhere at run-time. The obvious
correspondence is to put these into I6 local variables, which are, in effect,
CPU registers. We won't need to do much in the way of register-allocation,
@@ -751,7 +751,7 @@ fake up a call parameter pro tem.)
phsf->local_value_variables.its_form_allowed = TRUE;}
-local_variable *LocalVariables::add_pronoun(ph_stack_frame *phsf, wordingW, kind *K) {
+local_variable *LocalVariables::add_pronoun(ph_stack_frame *phsf, wordingW, kind *K) {phsf->local_value_variables.it_variable_exists = TRUE;returnLocalVariables::add_call_parameter(phsf, W, K);}
@@ -841,7 +841,7 @@ the text "X":
-local_variable *LocalVariables::ensure_called_local(wordingW, kind *K) {
+local_variable *LocalVariables::ensure_called_local(wordingW, kind *K) {ph_stack_frame *phsf = Frames::current_stack_frame();if (phsf == NULL) returnNULL; in case callings are made from parsing alone<new-called-name>(W);
@@ -990,7 +990,7 @@ an instance of the kind "bystander".
-intLocalVariables::permit_as_new_local(parse_node *found, intas_calling) {
+intLocalVariables::permit_as_new_local(parse_node *found, intas_calling) {if (Node::is(found, AMBIGUITY_NT)) found = found->down;if ((Specifications::is_kind_like(found)) && (Kinds::Behaviour::is_object(Specifications::to_kind(found)) == FALSE)) returnFALSE;
@@ -1009,7 +1009,7 @@ an instance of the kind "bystander".
§34. Logging.
-voidLocalVariables::log(local_variable *lvar) {
+voidLocalVariables::log(local_variable *lvar) {LocalVariables::write(DL, lvar);}
@@ -1037,7 +1037,7 @@ an instance of the kind "bystander".
-kind *LocalVariables::kind(local_variable *lvar) {
+kind *LocalVariables::kind(local_variable *lvar) {if (lvar == NULL) internal_error("Tried to find kind of nonexistent local variable");returnlvar->kind_as_declared;}
@@ -1052,7 +1052,7 @@ exists to fix that:
-voidLocalVariables::set_kind(local_variable *lvar, kind *K) {
+voidLocalVariables::set_kind(local_variable *lvar, kind *K) {if (lvar == NULL) internal_error("Tried to set kind of nonexistent local variable");LOGIF(LOCAL_VARIABLES, "Kind of local $k set to %u\n", lvar, K);lvar->kind_as_declared = K;
@@ -1066,12 +1066,12 @@ worth making the change, even though the disruption would be small.)
-voidLocalVariables::unprotect(local_variable *lvar) {
+voidLocalVariables::unprotect(local_variable *lvar) {if (lvar->lv_purpose == LET_VALUE_LV)lvar->protected = FALSE;}
-intLocalVariables::protected(local_variable *lvar) {
+intLocalVariables::protected(local_variable *lvar) {if ((lvar->lv_purpose == LET_VALUE_LV) && (lvar->protected)) {Problems::quote_source(1, current_sentence);Problems::quote_wording(2, lvar->varname);
@@ -1095,7 +1095,7 @@ and when the block ends it decrements.
-voidLocalVariables::set_scope_to(local_variable *lvar, ints) {
+voidLocalVariables::set_scope_to(local_variable *lvar, ints) {if ((s > 0) && (lvar) && (lvar->lv_purpose == LET_VALUE_LV)) {lvar->block_scope = s;LOGIF(LOCAL_VARIABLES, "Setting scope of $k to block level %d\n", lvar, s);
@@ -1106,11 +1106,11 @@ and when the block ends it decrements.
-voidLocalVariables::mark_to_free_at_end_of_scope(local_variable *lvar) {
+voidLocalVariables::mark_to_free_at_end_of_scope(local_variable *lvar) {lvar->free_at_end_of_scope = TRUE;}
-voidLocalVariables::end_scope(ints) {
+voidLocalVariables::end_scope(ints) {ph_stack_frame *phsf = Frames::current_stack_frame();if (phsf == NULL) internal_error("relinquishing locals where no stack frame exists");if (s <= 0) internal_error("the outermost scope cannot end");
@@ -1173,7 +1173,7 @@ value.
intcallings_session_number[MAX_CALLINGS_IN_MATCH];local_variable *callings_in_condition[MAX_CALLINGS_IN_MATCH];
-voidLocalVariables::add_calling_to_condition(local_variable *lvar) {
+voidLocalVariables::add_calling_to_condition(local_variable *lvar) {if (current_session_number < 0) internal_error("no PM session");if (callings_in_condition_sp + 1 == MAX_CALLINGS_IN_MATCH)StandardProblems::sentence_problem(Task::syntax_tree(), _p_(BelievedImpossible), or very hard, anyway
@@ -1185,13 +1185,13 @@ value.
}}
-voidLocalVariables::begin_condition_emit(void) {
+voidLocalVariables::begin_condition_emit(void) {current_session_number++;Produce::inv_primitive(Emit::tree(), OR_BIP);Produce::down(Emit::tree());}
-voidLocalVariables::end_condition_emit(void) {
+voidLocalVariables::end_condition_emit(void) {if (current_session_number < 0) internal_error("unstarted PM session");intNC = 0, x = callings_in_condition_sp, downs = 1;
@@ -1237,7 +1237,7 @@ lvalue which can be used to evaluate or assign to the variable:
-voidLocalVariables::writer(OUTPUT_STREAM, char *format_string, void *vL) {
+voidLocalVariables::writer(OUTPUT_STREAM, char *format_string, void *vL) {local_variable *lvar = (local_variable *) vL;if (lvar == NULL) internal_error("no such variable");switch (format_string[0]) {
@@ -1313,7 +1313,7 @@ need in the compilation of any given routine:
}}
-inter_symbol *LocalVariables::declare_this(local_variable *lvar, intshell_mode, intreason) {
+inter_symbol *LocalVariables::declare_this(local_variable *lvar, intshell_mode, intreason) {inter_symbol *S = Produce::local_exists(Emit::tree(), lvar->lv_lvalue);if (S) returnS;
@@ -1339,7 +1339,7 @@ need in the compilation of any given routine:
-voidLocalVariables::comment_on(OUTPUT_STREAM, local_variable *lvar, intpurpose) {
+voidLocalVariables::comment_on(OUTPUT_STREAM, local_variable *lvar, intpurpose) {switch (purpose) {caseTOKEN_CALL_PARAMETER_LV:if (Wordings::nonempty(lvar->varname))
diff --git a/docs/imperative-module/4-sf.html b/docs/imperative-module/4-sf.html
index 8038841b5..51cdf8d24 100644
--- a/docs/imperative-module/4-sf.html
+++ b/docs/imperative-module/4-sf.html
@@ -159,7 +159,7 @@ wants to compile an I6 routine for some purpose other than to define a phrase.
return &nonphrasal_stack_frame;}
-voidFrames::remove_nonphrase_stack_frame(void) {
+voidFrames::remove_nonphrase_stack_frame(void) {nonphrasal_stack_frame = Frames::new(); to prevent accidental lucky misusenonphrasal_stack_frame_is_current = FALSE;Frames::remove_current();
@@ -187,16 +187,16 @@ if that's active, and otherwise must be set as needed.
The structure stacked_variable is accessed in 2/rls, 2/fao, 2/act, 3/pu, 3/dptd, 3/po, 3/pav, 6/cii, 6/cste and here.
The structure stacked_variable_list is accessed in 2/rlb, 2/act, 3/id, 3/phr, 3/prcd, 3/tph, 3/tp, 4/lv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
The structure stacked_variable_owner is private to this section.
The structure stacked_variable_owner_list is accessed in 2/rlb, 2/act, 3/id, 3/phr, 3/prcd, 3/tph, 3/tp, 4/lv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
+
The structure stacked_variable is accessed in 2/rls, 2/fao, 2/act, 3/pu, 3/dptd, 3/po, 3/pav, 6/cii, 6/cste and here.
The structure stacked_variable_list is accessed in 2/rlb, 2/act, 3/phr, 3/prcd, 3/tph, 3/tp, 4/lv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
The structure stacked_variable_owner is private to this section.
The structure stacked_variable_owner_list is accessed in 2/rlb, 2/act, 3/phr, 3/prcd, 3/tph, 3/tp, 4/lv, 4/sf, 5/dtd, 5/cdp, 6/inv, 6/pi, 6/cii, 6/cp, 6/cste and here.
§2.
diff --git a/docs/imperative-module/5-cdp.html b/docs/imperative-module/5-cdp.html
index b7c298beb..62c4f41a9 100644
--- a/docs/imperative-module/5-cdp.html
+++ b/docs/imperative-module/5-cdp.html
@@ -129,7 +129,7 @@ which create routines which... and so on.
}pcalc_prop_deferral *latest_pcd = NULL;
-intPropositions::Deferred::compilation_coroutine(void) {
+intPropositions::Deferred::compilation_coroutine(void) {intN = 0;while (TRUE) {pcalc_prop_deferral *pdef;
@@ -1972,7 +1972,7 @@ then expand it into the output.
i6_schemaloop_schema;
-pcalc_prop *Propositions::Deferred::compile_loop_header(intvar, local_variable *index_var,
+pcalc_prop *Propositions::Deferred::compile_loop_header(intvar, local_variable *index_var,pcalc_prop *proposition,intavoid_parent_optimisation, intgrouped, pcalc_prop_deferral *pdef) {
diff --git a/docs/imperative-module/6-cii.html b/docs/imperative-module/6-cii.html
index cd310de9e..6178b2da7 100644
--- a/docs/imperative-module/6-cii.html
+++ b/docs/imperative-module/6-cii.html
@@ -1244,8 +1244,8 @@ rule), and also makes a note for indexing purposes.
if (Rvalues::is_CONSTANT_construction(supplied, CON_rule)) {rule *R = Rvalues::to_rule(supplied);
-imperative_defn *id = Rules::get_imperative_definition(R);
-if (id) Phrases::Timed::note_usage(id->defines, current_sentence);
+imperative_defn *id = Rules::get_imperative_definition(R);
+if (id) Phrases::Timed::note_usage(id->defines, current_sentence); } else {Problems::quote_source(1, current_sentence);Problems::quote_wording(2, Node::get_text(supplied));
diff --git a/docs/imperative-module/6-cp.html b/docs/imperative-module/6-cp.html
index e43a406ba..f61c2c2c5 100644
--- a/docs/imperative-module/6-cp.html
+++ b/docs/imperative-module/6-cp.html
@@ -102,7 +102,7 @@ should always be supplied for "To..." phrases, but left null for rules.
voidRoutines::Compile::routine(phrase *ph,stacked_variable_owner_list *legible, to_phrase_request *req,rule *R) {
-parse_node *code_at = ph->from->at;
+parse_node *code_at = ph->from->at;if (Node::is(code_at->next, DEFN_CONT_NT)) code_at = code_at->next;LOGIF(PHRASE_COMPILATION, "Compiling phrase:\n$T", code_at);
@@ -128,7 +128,7 @@ should always be supplied for "To..." phrases, but left null for rules.
§2.2. Set up the stack frame for this compilation request2.2 =
@@ -429,8 +429,7 @@ henceforth to be true, so we simply compile empty code in that case.
current_sentence = to_compile;named_rulebook_outcome *nrbo = <<rp>>;if (phrase_being_compiled) {
-if ((phrase_being_compiled->from->family != RULE_IN_RULEBOOK_EFF_family) &&
- (phrase_being_compiled->from->family != RULE_NOT_IN_RULEBOOK_EFF_family)) {
+if (ImperativeDefinitions::goes_in_rulebooks(phrase_being_compiled->from) == FALSE) {Problems::quote_source(1, current_sentence);Problems::quote_wording(2, Node::get_text(to_compile));StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_MisplacedRulebookOutcome2));
diff --git a/docs/imperative-module/6-cste.html b/docs/imperative-module/6-cste.html
index 199cc43de..a0568c511 100644
--- a/docs/imperative-module/6-cste.html
+++ b/docs/imperative-module/6-cste.html
@@ -174,7 +174,7 @@ specified by \((w_1, w_2)\), according to the equation
§3.2. By far the hardest part of the problem is to rearrange the equation so that
the variable we want to find is the entire left hand side, but this is done
-for us by code in Equations (in assertions), so it looks easy here.
+for us by code in Equations (in assertions), so it looks easy here.
The surprising thing is the fresh round of typechecking: why do we do that?
diff --git a/docs/imperative-module/index.html b/docs/imperative-module/index.html
index 6dfd450ce..04df26c03 100644
--- a/docs/imperative-module/index.html
+++ b/docs/imperative-module/index.html
@@ -131,11 +131,6 @@
Introduction to Phrases
-
An exposition of the data structures used inside Inform to hold phrases, rules and rulebooks.
-
-
- Imperative Definitions -
- Each IMPERATIVE node in the syntax tree makes a definition of a phrase or rule.