diff --git a/docs/assertions-module/1-am.html b/docs/assertions-module/1-am.html new file mode 100644 index 000000000..69391cd97 --- /dev/null +++ b/docs/assertions-module/1-am.html @@ -0,0 +1,90 @@ + + + + Assertions Module + + + + + + + + + + + + + + + +
+ + +

Setting up the use of this module.

+ +

§1. This section simoly sets up the module in ways expected by foundation, and +contains no code of interest. The following constant exists only in tools +which use this module: +

+ +
define ASSERTIONS_MODULE TRUE
+
+

§2. Like all modules, this one must define a start and end function: +

+ +
+void AssertionsModule::start(void) {
+}
+void AssertionsModule::end(void) {
+}
+
+ + +
+ + + diff --git a/docs/assertions-module/2-ar.html b/docs/assertions-module/2-ar.html new file mode 100644 index 000000000..a1e529997 --- /dev/null +++ b/docs/assertions-module/2-ar.html @@ -0,0 +1,243 @@ + + + + Anaphoric References + + + + + + + + + + + + + + + + + + +
+ + +

To keep track of the current object and subject of discussion.

+ +

§1. Inform is deliberately minimal when allowing the use of pronouns which carry +meanings from one sentence to another. It is unclear exactly how natural +language does this, and while some theories are more persuasive than others, +all seem vulnerable to odd cases that they get "wrong". It's therefore +hard to program a computer to understand "it" so that human users are +happy with the result. +

+ +

But we try, just a little, by keeping track of the subject and object +under discussion. Even this is tricky. Consider: +

+ +
+

The Pavilion is a room. East is the Cricket Square.

+
+ +

East of where? Clearly of the current subject, the Pavilion (not +the room kind). On the other hand, +

+ +
+

On the desk is a pencil. It has description "2B."

+
+ +

"It" here is the pencil, not the desk. To disentangle such things, +we keep track of two different running references: the current subject and +the current object. English is an SVO language, so that in assertions of the +form "X is Y", X is the subject and Y the object. But it will turn out to +be more complicated than that, because we disregard all references which are +not to tangible things and kinds. +

+ +
+inference_subject *Anaphora::get_current_subject(void) {
+    return global_pass_state.subject_of_sentences;
+}
+
+inference_subject *Anaphora::get_current_object(void) {
+    return global_pass_state.object_of_sentences;
+}
+
+int Anaphora::get_current_subject_plurality(void) {
+    return global_pass_state.subject_seems_to_be_plural;
+}
+
+

§2. The routine Anaphora::new_discussion is called when we reach a +heading or other barrier in the source text, to make clear that there has +been a change of the topic discussed. +

+ +

Anaphora::change_discussion_topic is called once at the end of +processing each assertion during each pass. +

+ +

Note that we are careful to avoid changing the subject with sentences like: +

+ +
+

East is the Central Plaza.

+
+ +

where this does not have the subject "east", but has instead an implicit +subject carried over from previous sentences. +

+ +
+void Anaphora::new_discussion(void) {
+    if (global_pass_state.subject_of_sentences)
+        LOGIF(PRONOUNS, "[Forgotten subject of sentences: $j]\n",
+            global_pass_state.subject_of_sentences);
+    if (global_pass_state.subject_of_sentences)
+        LOGIF(PRONOUNS, "[Forgotten object of sentences: $j]\n",
+            global_pass_state.object_of_sentences);
+    global_pass_state.subject_of_sentences = NULL;
+    global_pass_state.object_of_sentences = NULL;
+    global_pass_state.subject_seems_to_be_plural = FALSE;
+}
+
+

§3. The slight asymmetry in what follows is partly pragmatic, partly the result +of subject-verb inversion ("in the bag is the ball" not "the ball is in the +bag"). We extract a subject from a relationship node on the left, but not on +the right, and we don't extract an object from one. Consider: +

+ +
+

A billiards table is in the Gazebo. On it is a trophy cup.

+
+ +

What does "it" mean, and why? A human reader goes for the billiards table at +once, because it seems more likely as a supporter than the Gazebo, but that's +not how Inform gets the same answer. It all hangs on "billiards table" being +the object of the first sentence, not the Gazebo; if we descended the RHS, +which is RELATIONSHIP_NT -> PROPER_NOUN_NT pointing to the Gazebo, that's the +conclusion we would have reached. +

+ +
+void Anaphora::change_discussion_from_coupling(parse_node *px, parse_node *py) {
+    inference_subject *infsx = NULL, *infsy = NULL, *infsy_full = NULL;
+    infsx = Anaphora::discussed_at_node(px);
+    infsy_full = Anaphora::discussed_at_node(py);
+    if (Node::get_type(py) != KIND_NT) infsy = Node::get_subject(py);
+    Anaphora::change_discussion_topic(infsx, infsy, infsy_full);
+    if (Node::get_type(px) == AND_NT) Anaphora::subject_of_discussion_a_list();
+    if (Annotations::read_int(current_sentence, clears_pronouns_ANNOT))
+        Anaphora::new_discussion();
+}
+
+void Anaphora::change_discussion_topic(inference_subject *infsx,
+    inference_subject *infsy, inference_subject *infsy_full) {
+    inference_subject *old_sub = global_pass_state.subject_of_sentences,
+        *old_obj = global_pass_state.object_of_sentences;
+    global_pass_state.subject_seems_to_be_plural = FALSE;
+    if (Wordings::length(Node::get_text(current_sentence)) > 1)
+        global_pass_state.near_start_of_extension = 0;
+    Node::set_interpretation_of_subject(current_sentence,
+        global_pass_state.subject_of_sentences);
+
+    if (Annotations::node_has(current_sentence, implicit_in_creation_of_ANNOT))
+        return;
+    #ifdef IF_MODULE
+    if ((PL::Map::is_a_direction(infsx)) &&
+            ((InferenceSubjects::as_object_instance(infsx) == NULL) ||
+                (InferenceSubjects::as_object_instance(infsy_full)))) infsx = NULL;
+    #endif
+    if (infsx) global_pass_state.subject_of_sentences = infsx;
+    if ((infsy) && (InferenceSubjects::domain(infsy) == NULL))
+        global_pass_state.object_of_sentences = infsy;
+    else if (infsx) global_pass_state.object_of_sentences = infsx;
+
+    if (global_pass_state.subject_of_sentences != old_sub)
+        LOGIF(PRONOUNS, "[Changed subject of sentences to $j]\n",
+            global_pass_state.subject_of_sentences);
+    if (global_pass_state.object_of_sentences != old_obj)
+        LOGIF(PRONOUNS, "[Changed object of sentences to $j]\n",
+            global_pass_state.object_of_sentences);
+}
+
+

§4.

+ +
+inference_subject *Anaphora::discussed_at_node(parse_node *pn) {
+    inference_subject *infs = NULL;
+    if (Node::get_type(pn) != KIND_NT) infs = Node::get_subject(pn);
+    if ((Node::get_type(pn) == RELATIONSHIP_NT) && (pn->down) &&
+        (Node::get_type(pn->down) == PROPER_NOUN_NT))
+        infs = Node::get_subject(pn->down);
+    if ((Node::get_type(pn) == WITH_NT) && (pn->down) &&
+        (Node::get_type(pn->down) == PROPER_NOUN_NT))
+        infs = Node::get_subject(pn->down);
+    return infs;
+}
+
+

§5. Occasionally we need to force the issue, though: +

+ +
+void Anaphora::subject_of_discussion_a_list(void) {
+    global_pass_state.subject_seems_to_be_plural = TRUE;
+}
+
+ + +
+ + + diff --git a/docs/assertions-module/2-bv.html b/docs/assertions-module/2-bv.html new file mode 100644 index 000000000..6e42cec59 --- /dev/null +++ b/docs/assertions-module/2-bv.html @@ -0,0 +1,246 @@ + + + + Booting Verbs + + + + + + + + + + + + + + + + +
+ + +

In Inform even verbs are created with natural language sentences, but this process has to start somewhere.

+ +

§1. "Booting" is the traditional computing term for "pulling yourself up by +your own bootstraps": when a computer switches on it has no program to run, +but to load in a program would require a program. The circularity is broken +by having a minimal "boot" program wired into the hardware. +

+ +

So too with Inform. The opening sentence of the Basic Inform extension, always +the first sentence read in, is: +

+ +
+

The verb to mean means the meaning relation.

+
+ +

(See Preamble (in basic_inform).) But this is circular: if we have not yet +defined "to mean", how can we recognise "means" as the verb, or know what it +means? We break this circularity by hard-wiring it, as follows. +

+ +
+void BootVerbs::make_built_in(void) {
+    verb *to_mean;
+    special_meaning_holder *meaning_of_mean;
+    Create the special meanings1.3;
+    Create the verbs to be and to mean1.5;
+    Give meaning to mean1.6;
+}
+
+

§1.1. "Regular" meanings involve relations between two values: for example, carrying +and numerical greater-than are both regular meanings, of the verbs "to carry" +and > respectively. +

+ +

"Special" meanings are different. The noun phrases need not represent values, +there need not be two of them, and the meaning can have internal significance +to the Inform compiler. For example, +

+ +
+

Black king chess piece translates into Unicode as 9818.

+
+ +

is one of three special meanings of "to translate into". The linguistics +module decides which if any is meant in a given case by calling the "special +meaning functions" to see if wants to accept the sentence in question. +

+ +

§1.2. When the linguistics module looks for a primary verb, it may find +multiple candidates: consider "fruit flies like a banana", where "flies" and +"like" are both candidate verbs. We decide by (a) ranking verbs in tiers by +"priority number", and failing that (b) choosing the leftmost. Priority 0 +verbs are never considered, but otherwise low priority numbers beat higher. +(See Verb Usages (in linguistics).) +

+ +

Inform adopts the following convention for the priority of regular meanings: +

+ + +

As can be seen below, special meanings have priorities between 1 and 4. Note +that "to mean" itself has both a special meaning (priority 3) and a regular +meaning (priority 4). This is why the sentence: +

+ +
+

The verb to mean means the meaning relation.

+
+ +

is not circular. It uses the special meaning of "mean" (priority 3) to create +the regular one (4). +

+ +

§1.3. So, then, here are the core module's special meanings. Just like regular +meanings, which have names like "containment relation", special meanings have +names. But as these names are only used in early boot sentences in the +basic_inform extension, the user never sees them. They are required to +be a single word, and are hyphenated. +

+ +

Create the special meanings1.3 = +

+ +
+    SpecialMeanings::declare(RelationRequests::new_relation_SMF,			I"new-relation", 1);
+    SpecialMeanings::declare(Rules::Placement::substitutes_for_SMF,			I"rule-substitutes-for", 1);
+    SpecialMeanings::declare(Rules::Placement::does_nothing_SMF,			I"rule-does-nothing", 1);
+    SpecialMeanings::declare(Rules::Placement::does_nothing_if_SMF,			I"rule-does-nothing-if", 1);
+    SpecialMeanings::declare(Rules::Placement::does_nothing_unless_SMF,		I"rule-does-nothing-unless", 1);
+    SpecialMeanings::declare(Translations::translates_into_unicode_as_SMF,	I"translates-into-unicode", 1);
+    SpecialMeanings::declare(Translations::translates_into_Inter_as_SMF,	I"translates-into-i6", 1);
+    SpecialMeanings::declare(Translations::translates_into_language_as_SMF,	I"translates-into-language", 1);
+
+    SpecialMeanings::declare(TestRequests::test_with_SMF,			        I"test-with", 1);
+
+    SpecialMeanings::declare(NewVerbRequests::new_verb_SMF, 				I"new-verb", 2);
+    SpecialMeanings::declare(Plurals::plural_SMF, 							I"new-plural", 2);
+    SpecialMeanings::declare(ActivityRequests::new_activity_SMF, 			I"new-activity", 2);
+    SpecialMeanings::declare(NewAdjectiveRequests::new_adjective_SMF,		I"new-adjective", 2);
+    SpecialMeanings::declare(NewPropertyRequests::either_SMF,				I"new-either-or", 2);
+    SpecialMeanings::declare(DefineByTable::defined_by_SMF,					I"defined-by-table", 2);
+    SpecialMeanings::declare(Rules::Placement::listed_in_SMF,				I"rule-listed-in", 2);
+    SpecialMeanings::declare(NewPropertyRequests::optional_either_SMF,		I"can-be", 2);
+
+    meaning_of_mean = SpecialMeanings::declare(NewVerbRequests::verb_means_SMF, 	I"verb-means", 3);
+
+    SpecialMeanings::declare(LPRequests::specifies_SMF, 					I"specifies-notation", 4);
+    SpecialMeanings::declare(NewUseOptions::use_translates_as_SMF,			I"use-translates", 4);
+    SpecialMeanings::declare(UseOptions::use_SMF,							I"use", 4);
+    SpecialMeanings::declare(Sentences::DLRs::include_in_SMF,				I"include-in", 4);
+    SpecialMeanings::declare(Sentences::DLRs::omit_from_SMF,				I"omit-from", 4);
+
+    #ifdef MULTIMEDIA_MODULE
+    MultimediaMeanings::bootstrap();
+    #endif
+    #ifdef IF_MODULE
+    IFModuleMeanings::bootstrap();
+    #endif
+
+ +

§1.4. We need the English infinitive forms of two verbs to get started. In each +case we use the inflections module to conjugate them — i.e., to generate +all the other forms, "is", "did not mean" and so on — and then hand them to +the linguistics module to add to its stock of known verbs. (It starts out +with none, so these are initially the only two.) +

+ +

We need to create "to be" first because (a) it is the only copular verb in +Inform, and there is no way to create a copular verb using Inform source text; +and (b) because this enables us to conjugate forms of "mean" such as "X is +meant by" — note the use of "is". +

+ +
+<bootstrap-verb> ::=
+    be |
+    mean
+
+ +

§1.5. Create the verbs to be and to mean1.5 = +

+ +
+    word_assemblage infinitive = PreformUtilities::wording(<bootstrap-verb>, 0);
+    verb_conjugation *vc = Conjugation::conjugate(infinitive, DefaultLanguage::get(NULL));
+    verb *to_be = Verbs::new_verb(vc, TRUE);  note that "to be" is created as copular
+    vc->vc_conjugates = to_be;
+    VerbUsages::register_all_usages_of_verb(to_be, FALSE, 2, NULL);
+
+    infinitive = PreformUtilities::wording(<bootstrap-verb>, 1);
+    vc = Conjugation::conjugate(infinitive, DefaultLanguage::get(NULL));
+    to_mean = Verbs::new_verb(vc, FALSE);  but "to mean" is not
+    vc->vc_conjugates = to_mean;
+    VerbUsages::register_all_usages_of_verb(to_mean, FALSE, 3, NULL);
+
+ +

§1.6. Those two verbs are now part of our linguistic stock, but do not yet mean +anything. We need to give the build-in "verb-means" meaning to "to mean": +

+ +

Give meaning to mean1.6 = +

+ +
+    if ((to_mean == NULL) || (meaning_of_mean == NULL)) internal_error("could not make to mean");
+    Verbs::add_form(to_mean, NULL, NULL, VerbMeanings::special(meaning_of_mean), SVO_FS_BIT);
+
+ + + +
+ + + diff --git a/docs/assertions-module/2-cs.html b/docs/assertions-module/2-cs.html new file mode 100644 index 000000000..5b1fc6e28 --- /dev/null +++ b/docs/assertions-module/2-cs.html @@ -0,0 +1,450 @@ + + + + Classifying Sentences + + + + + + + + + + + + + + + + + + + +
+ + +

To work out the verbs used and to diagram sentences in the source.

+ +
+ +

§1. Traversing for primary verbs. The story so far: the supervisor module has arranged for the source +text to be read in by words and has made a rudimentary parse tree for +it using syntax. Certain "structural" sentences, such as headings, have +been taken care of, and turned into nodes with types like HEADING_NT. +

+ +

But the assertions we want to read — such as "The Mona Lisa is in the Louvre", +or "The plural of major general is majors general" — are all simply +SENTENCE_NT nodes with no children. The following traverse begins Inform's +compilation process in earnest: for each such SENTENCE_NT node, it asks +the linguistics module to identify a primary verb, noun phrases and so +on, placing them in a subtree. +

+ +

§2. Textual sentences. "Textual" sentences are not really sentences at all, and are just double-quoted +text used in isolation — Inform sometimes recognises these as being implicit +property values, as for the description of a room just created. These sentences +are necessarily exempt from having a primary verb. +

+ +
+int Classifying::sentence_is_textual(parse_node *p) {
+    if ((Wordings::length(Node::get_text(p)) == 1) &&
+            (Vocabulary::test_flags(
+                Wordings::first_wn(Node::get_text(p)), TEXT_MC+TEXTWITHSUBS_MC)))
+        return TRUE;
+    return FALSE;
+}
+
+

§3. Classifying a single sentence. Every SENTENCE_NT node, however it is constructed, therefore ends up here, +and we ask the linguistics module to "diagram" it. +

+ +

See About Sentence Diagrams (in linguistics) for many examples. +

+ +
+void Classifying::sentence(parse_node *p) {
+    if (Annotations::read_int(p, classified_ANNOT)) return;
+    Annotations::write_int(p, classified_ANNOT, TRUE);
+    parse_node *save = current_sentence;
+    current_sentence = p;
+    if (Classifying::sentence_is_textual(p) == FALSE) {
+        wording W = Node::get_text(p);
+        if (<sentence-without-occurrences>(W)) {
+            parse_node *VP_PN = <<rp>>;
+            switch (Annotations::read_int(VP_PN, linguistic_error_here_ANNOT)) {
+                case TwoLikelihoods_LINERROR: Issue PM_TwoLikelihoods problem3.1; break;
+            }
+            SyntaxTree::graft(Task::syntax_tree(), VP_PN, p);
+            if (SyntaxTree::is_trace_set(Task::syntax_tree())) LOG("$T\n", p);
+            Check that this is allowed, if it occurs in the Options file3.3;
+            #ifdef IF_MODULE
+            PL::MapDirections::look_for_direction_creation(p);
+            #endif
+            PropertySentences::look_for_property_creation(p);
+            Issue problem message if either subject or object contains mismatched brackets3.4;
+            Issue problem message if subject starts with double-quoted literal text3.5;
+            if ((VP_PN->next) && (VP_PN->next->next) && (Diagrams::is_possessive_RELATIONSHIP(VP_PN->next->next)))
+                Diagram property callings3.6;
+        } else {
+            LOG("$T\n", p);
+            <no-primary-verb-diagnosis>(W);
+        }
+    }
+    current_sentence = save;
+}
+
+

§3.1. Issue PM_TwoLikelihoods problem3.1 = +

+ +
+    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_TwoLikelihoods),
+        "this sentence seems to have a likelihood qualification on both "
+        "sides of the verb",
+        "which is not allowed. 'The black door certainly is usually open' "
+        "might possibly be grammatical English in some idioms, but Inform "
+        "doesn't like a sentence in this shape because the 'certainly' "
+        "on one side of the verb and the 'usually' on the other are "
+        "rival indications of certainty.");
+
+ +

§3.2. Only special-meaning sentences are allowed in Options files, and not all +of those. +

+ +
enum ALLOW_IN_OPTIONS_FILE_SMFT
+
+

§3.3. Check that this is allowed, if it occurs in the Options file3.3 = +

+ +
+    if (Wordings::within(Node::get_text(p), options_file_wording)) {
+        special_meaning_holder *sm = Node::get_special_meaning(p->down);
+        if ((sm == NULL) ||
+            (SpecialMeanings::call(sm, ALLOW_IN_OPTIONS_FILE_SMFT, NULL, NULL) == FALSE)) {
+            StandardProblems::unlocated_problem(Task::syntax_tree(),
+                _p_(BelievedImpossible),  not convenient to test automatically, anyway
+                "The options file placed in this installation of Inform's folder "
+                "is incorrect, making use of a sentence form which isn't allowed "
+                "in that situation. The options file is only allowed to contain "
+                "use options, Test ... with..., and Release along with... "
+                "instructions.");
+            return;
+        }
+    }
+
+ +

§3.4. The linguistics module no longer makes sentence diagrams with this defect, +so the following problem ought now to be impossible to generate. But I'm leaving +the test here in case of future changes. +

+ +

Issue problem message if either subject or object contains mismatched brackets3.4 = +

+ +
+    if ((VP_PN->next) && (VP_PN->next->next)) {
+        if ((Wordings::mismatched_brackets(Node::get_text(VP_PN->next))) ||
+            (Wordings::mismatched_brackets(Node::get_text(VP_PN->next->next)))) {
+            Problems::quote_source(1, current_sentence);
+            Problems::quote_wording(2,
+                Wordings::one_word(Wordings::last_wn(Node::get_text(VP_PN->next)) + 1));
+            Problems::quote_wording(3, Node::get_text(VP_PN->next));
+            Problems::quote_wording(4, Node::get_text(VP_PN->next->next));
+            StandardProblems::handmade_problem(Task::syntax_tree(), _p_(BelievedImpossible));
+            if (Wordings::nonempty(Node::get_text(VP_PN->next->next)))
+                Problems::issue_problem_segment(
+                    "I must be misreading the sentence %1. The verb "
+                    "looks to me like '%2', but then the brackets don't "
+                    "match in what I have left: '%3' and '%4'.");
+            else
+                Problems::issue_problem_segment(
+                    "I must be misreading the sentence %1. The verb "
+                    "looks to me like '%2', but then the brackets don't "
+                    "match in what I have left: '%3'.");
+            Problems::issue_problem_end();
+            return;
+        }
+    }
+
+ +

§3.5. This is a pragmatic sort of problem message. A priori, assertion sentences +like this might be okay, but in practice they cannot be useful and are far +more likely to occur as a result of something like: +

+ +
+

"This is a dining room" East is the Ballroom.

+
+ +

where the lack of a closing full stop in the quoted text means that linguistics +read this as one single sentence, equating "This is a dining room" East +with the Ballroom. +

+ +

Special-meaning sentences are exempt; this is needed because subject phrases +for "Understand ... as ..." are indeed sometimes multiword clauses the first +word of which is quoted. +

+ +

Issue problem message if subject starts with double-quoted literal text3.5 = +

+ +
+    special_meaning_holder *sm = Node::get_special_meaning(VP_PN);
+    if ((sm == NULL)
+        && (Wordings::length(Node::get_text(VP_PN->next)) > 1)
+        && (Vocabulary::test_flags(
+            Wordings::first_wn(Node::get_text(VP_PN->next)), TEXT_MC+TEXTWITHSUBS_MC))) {
+        StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_TextNotClosing),
+            "it looks as if perhaps you did not intend that to read as a "
+            "single sentence",
+            "and possibly the text in quotes was supposed to stand as "
+            "as a sentence on its own? (The convention is that if text "
+            "ends in a full stop, exclamation or question mark, perhaps "
+            "with a close bracket or quotation mark involved as well, then "
+            "that punctuation mark also closes the sentence to which the "
+            "text belongs: but otherwise the words following the quoted "
+            "text are considered part of the same sentence.)");
+        return;
+    }
+
+ +

§3.6. Here py is a CALLED_NT subtree for "an A called B", which we relabel +as a PROPERTYCALLED_NT subtree and hang beneath an ALLOWED_NT node; +or else it's a property or list of properties, as in "carrying capacity 7". +

+ +

Diagram property callings3.6 = +

+ +
+    parse_node *px = VP_PN->next;
+    parse_node *py = VP_PN->next->next->down;
+    if (Node::get_type(py) == CALLED_NT) {
+        if (Wordings::match(Node::get_text(py->down->next), Node::get_text(py->down))) {
+            StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_SuperfluousCalled),
+                "'called' should be used only when the name is different from the kind",
+                "so this sentence should be simplified. For example, 'A door has a "
+                "colour called colour' should be written more simply as 'A door has "
+                "a colour'; but 'called' can be used for something like 'A door has "
+                "a number called the street number'.");
+            return;
+        }
+        Node::set_type(py, PROPERTYCALLED_NT);
+        if (Node::get_type(py->down) == AND_NT) {
+internal_error("Og yeah?");
+            int L = Node::left_edge_of(py->down),
+                R = Node::right_edge_of(py->down);
+            <np-articled>(Wordings::new(L, R));
+            parse_node *pn = <<rp>>;
+            pn->next = py->down->next;
+            py->down = pn;
+            LOG("Thus $T", py);
+        }
+        px->next = Node::new(ALLOWED_NT);
+        px->next->down = py;
+        int prohibited = <prohibited-property-owners>(Node::get_text(px));
+        if (!prohibited) {
+            <np-articled-list>(Node::get_text(py->down->next));
+            py->down->next = <<rp>>;
+        }
+    } else {
+        Node::set_type(py, PROPERTY_LIST_NT);
+    }
+
+ +

§4. From the earliest beta-testing, the problem message for "I can't find a verb" +split into cases. Inform is quite sensitive to punctuation errors as between +comma, paragraph break and semicolon, and this is where that sensitivity begins +to bite. The grammar below is just a set of heuristics, really: once we enter +this, a problem message of some kind will certainly result. +

+ +
+<no-primary-verb-diagnosis> ::=
+    ... <no-primary-verb-diagnosis-tail> |
+    before/every/after/when/instead/check/carry/report ... | ==> Issue PM_RuleWithoutColon problem4.1
+    if ... |												 ==> Issue PM_IfOutsidePhrase problem4.2
+    ... , ... |												 ==> Issue PM_NoSuchVerbComma problem4.3
+    ...														 ==> Issue PM_NoSuchVerb problem4.4
+
+<no-primary-verb-diagnosis-tail> ::=
+    <rc-marker> <certainty> <nonimperative-verb> ... |  ==> { advance Wordings::delta(WR[1], W) }
+    <rc-marker> <nonimperative-verb> ... |              ==> { advance Wordings::delta(WR[1], W) }
+    <past-tense-verb> ... |                             ==> Issue PM_NonPresentTense problem4.5
+    <negated-verb> ...                                  ==> Issue PM_NegatedVerb1 problem4.6
+
+ +

§4.1. Issue PM_RuleWithoutColon problem4.1 = +

+ +
+    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RuleWithoutColon),
+        "I can't find a verb that I know how to deal with, so can't do anything "
+        "with this sentence. It looks as if it might be a rule definition",
+        "but if so then it is lacking the necessary colon (or comma). "
+        "The punctuation style for rules is 'Rule conditions: do this; "
+        "do that; do some more.' Perhaps you used a full stop instead "
+        "of the colon?");
+
+ +

§4.2. Issue PM_IfOutsidePhrase problem4.2 = +

+ +
+    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_IfOutsidePhrase),
+        "I can't find a verb that I know how to deal with. This looks like an 'if' "
+        "phrase which has slipped its moorings",
+        "so I am ignoring it. ('If' phrases, like all other such "
+        "instructions, belong inside definitions of rules or phrases - "
+        "not as sentences which have no context. Maybe a full stop or a "
+        "skipped line was accidentally used instead of semicolon, so that you "
+        "inadvertently ended the last rule early?)");
+
+ +

§4.3. Issue PM_NoSuchVerbComma problem4.3 = +

+ +
+    Problems::quote_source(1, current_sentence);
+    StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NoSuchVerbComma));
+    Problems::issue_problem_segment(
+        "In the sentence %1, I can't find a verb that I know how to deal with. "
+        "(I notice there's a comma here, which is sometimes used to abbreviate "
+        "rules which would normally be written with a colon - for instance, "
+        "'Before taking: say \"You draw breath.\"' can be abbreviated to 'Before "
+        "taking, say...' - but that's only allowed for Before, Instead and "
+        "After rules. I mention all this in case you meant this sentence "
+        "as a rule in some rulebook, but used a comma where there should "
+        "have been a colon ':'?)");
+    Problems::issue_problem_end();
+
+ +

§4.4. Issue PM_NoSuchVerb problem4.4 = +

+ +
+    Problems::quote_source(1, current_sentence);
+    StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NoSuchVerb));
+    Problems::issue_problem_segment(
+        "In the sentence %1, I can't find a verb that I know how to deal with.");
+    Problems::issue_problem_end();
+
+ +

§4.5. Issue PM_NonPresentTense problem4.5 = +

+ +
+    if (Annotations::read_int(current_sentence, verb_problem_issued_ANNOT) == FALSE) {
+        Annotations::write_int(current_sentence, verb_problem_issued_ANNOT, TRUE);
+        StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_NonPresentTense),
+            "assertions about the initial state of play must be given in the "
+            "present tense",
+            "so 'The cat is in the basket' is fine but not 'The cat has been in "
+            "the basket'. Time is presumed to start only when the game begins, so "
+            "there is no anterior state which we can speak of.");
+    }
+
+ +

§4.6. Issue PM_NegatedVerb1 problem4.6 = +

+ +
+    if (Annotations::read_int(current_sentence, verb_problem_issued_ANNOT) == FALSE) {
+        Annotations::write_int(current_sentence, verb_problem_issued_ANNOT, TRUE);
+        StandardProblems::negative_sentence_problem(Task::syntax_tree(), _p_(PM_NegatedVerb1));
+    }
+
+ +

§5. The following is needed to handle something like "colour of the box", +where "colour" is a property name. We must be careful, though, to avoid +confusion with variable declarations: +

+ +
+

The interesting var is a description of numbers that varies.

+
+ +

which would otherwise be misread as an attempt to set the "description" +property of something. +

+ +
define ALLOW_OF_LINGUISTICS_CALLBACK Classifying::allow_of
+
+
+<allow-of-x> ::=
+    in the presence |    ==> { fail }
+    <property-name-v>    ==> { -, - }
+
+<allow-of-y> ::=
+    ... that varies |    ==> { fail}
+    ... variable |       ==> { fail }
+    ...                  ==> { -, - }
+
+ +

§6.

+ +
+int Classifying::allow_of(wording XW, wording YW) {
+    if ((<allow-of-x>(XW)) && (<allow-of-y>(YW))) return TRUE;
+    return FALSE;
+}
+
+ + +
+ + + diff --git a/docs/assertions-module/2-ptmn.html b/docs/assertions-module/2-ptmn.html new file mode 100644 index 000000000..80de1c0dc --- /dev/null +++ b/docs/assertions-module/2-ptmn.html @@ -0,0 +1,398 @@ + + + + Passes through Major Nodes + + + + + + + + + + + + + + + + + + +
+ + +

To manage the overall process of traversing the parse tree for top-level declarations and assertion sentences.

+ +

§1. The first thing Inform does when compiling source text is to make three +passes through its top-level definitions: a "pre-pass", in which names of +things like tables and equations are discovered, and assertion sentences +are diagrammed; "pass 1", when instance, kinds, properties and so on are +created; and "pass 2", when property values and relationships are found. +

+ +
+void MajorNodes::pre_pass(void) {
+    MajorNodes::traverse(0);
+}
+void MajorNodes::pass_1(void) {
+    MajorNodes::traverse(1);
+}
+void MajorNodes::pass_2(void) {
+    MajorNodes::traverse(2);
+}
+
+

§2. During these passes, some global state is kept here. This is not elegant, +but saves a deal of passing parameters around. +

+ +
+typedef struct pass_state {
+    int pass;  during a pass, 0, 1 or 2: 0 is the pre-pass
+    int near_start_of_extension;
+    struct parse_node *assembly_position;
+    struct inference_subject *object_of_sentences;
+    struct inference_subject *subject_of_sentences;
+    int subject_seems_to_be_plural;
+} pass_state;
+
+pass_state global_pass_state = { -1, 0, NULL, NULL, NULL, FALSE };
+
+void MajorNodes::traverse(int pass) {
+    global_pass_state.pass = pass;
+    global_pass_state.near_start_of_extension = 0;
+    global_pass_state.assembly_position = NULL;
+    global_pass_state.object_of_sentences = NULL;
+    global_pass_state.subject_of_sentences = NULL;
+    global_pass_state.subject_seems_to_be_plural = FALSE;
+    SyntaxTree::clear_trace(Task::syntax_tree());
+    Anaphora::new_discussion();
+
+    parse_node *last = NULL;
+    SyntaxTree::traverse_nodep(Task::syntax_tree(), MajorNodes::visit, &last);
+
+    if (pass == 1) Extend the pass to invented sentences from kinds2.1;
+    if (pass == 2) Extend the pass to sentences needed when implicit kinds are set2.2;
+}
+
+ +

§2.1. Extend the pass to invented sentences from kinds2.1 = +

+ +
+    parse_node *extras = last;
+    ParseTreeUsage::add_kind_inventions();
+    current_sentence = extras;
+    global_pass_state.assembly_position = extras;
+    global_pass_state.pass = 0;
+    SyntaxTree::traverse_nodep_from(extras, MajorNodes::visit, &last);
+    current_sentence = extras;
+    global_pass_state.assembly_position = extras;
+    global_pass_state.pass = 1;
+    SyntaxTree::traverse_nodep_from(extras, MajorNodes::visit, &last);
+
+ +

§2.2. Here's a tricky timing problem, or rather, here's the fix for it. Assemblies +are made when the kinds of objects are set, and they're made by inserting +appropriate sentences. For instance, given the generalisation: +

+ +
+

Every room contains a vehicle.

+
+ +

we would insert the following sentence into the tree: +

+ +
+

Ballroom West contains a vehicle.

+
+ +

as soon as we discover that Ballroom West is a room. That works fine if we +discover this fact during traverses 1 or 2, but sometimes the room-ness of +a room cannot be established until the world model is constructed. So we +call the model-maker right now, and prolong pass 2 artificially to pick up +any additional sentences generated. +

+ +

Extend the pass to sentences needed when implicit kinds are set2.2 = +

+ +
+    current_sentence = last;
+    global_pass_state.assembly_position = current_sentence;
+    Plugins::Call::complete_model(1);
+    SyntaxTree::traverse_nodep_from(last, MajorNodes::visit, &last);
+
+ +

§3. Let us go, and make our visit: +

+ +
+void MajorNodes::visit(parse_node *p, parse_node **last) {
+    global_pass_state.assembly_position = current_sentence;
+    compilation_unit *cm = CompilationUnits::current();
+    CompilationUnits::set_current(p);
+    *last = p;
+    Deal with an individual major node3.1;
+    CompilationUnits::set_current_to(cm);
+}
+
+

§3.1. Headings cause us to begin a fresh topic of discussion, on a fresh piece of +paper, as it were: this wipes out any meanings of pronouns like "it" making +anaphoric references to previous sentences. In other respects, headings are for +organisation, and are not directly functional in themselves. +

+ +

Deal with an individual major node3.1 = +

+ +
+    if ((SyntaxTree::is_trace_set(Task::syntax_tree())) && (Node::get_type(p) != TRACE_NT))
+        LOG("\n[%W]\n", Node::get_text(p));
+
+    switch (Node::get_type(p)) {
+        case ROOT_NT: break;
+
+        case HEADING_NT:   Anaphora::new_discussion(); break;
+        case BEGINHERE_NT: Anaphora::new_discussion();
+                           global_pass_state.near_start_of_extension = 1; break;
+        case ENDHERE_NT:   Anaphora::new_discussion();
+                           global_pass_state.near_start_of_extension = 0; break;
+
+        case RULE_NT: Pass through a RULE node3.1.1; break;
+        case SENTENCE_NT: Pass through a SENTENCE node3.1.2; break;
+        case TRACE_NT: Pass through a TRACE node3.1.5; break;
+
+        case TABLE_NT: if (global_pass_state.pass == 0) Tables::create_table(p);
+            break;
+        case EQUATION_NT: if (global_pass_state.pass == 0) Equations::new_at(p, FALSE);
+            break;
+        case INFORM6CODE_NT:
+            if (global_pass_state.pass == 2) Config::Inclusions::inform_6_inclusion(p);
+            break;
+        case BIBLIOGRAPHIC_NT:
+            #ifdef IF_MODULE
+            if (global_pass_state.pass == 2) PL::Bibliographic::bibliographic_data(p);
+            #endif
+            break;
+
+        case INVOCATION_LIST_NT: break;  for error recovery; shouldn't be here otherwise
+
+        default:
+            LOG("$T\n", p);
+            internal_error("passed through major node of unexpected type");
+    }
+
+ +

§3.1.1. This is a little convoluted. The linguistics module turns sentences in +rule form into a RULE_NT node followed by subsequent INVOCATION_NT nodes, +and the first call here makes them into a neat subtree. After that, we look +out for adjectives defined by phrases, and for phrases with names, since +both will affect how we read sentences in passes 1 and 2. +

+ +

Pass through a RULE node3.1.1 = +

+ +
+    if (global_pass_state.pass == 0) {
+        SyntaxTree::traverse_run(p, RuleSubtrees::demote_command_nodes, RULE_NT);
+        Phrases::Adjectives::look_for_headers(p);
+        Phrases::Usage::predeclare_name_in(p);
+    }
+
+ +

§3.1.2. SENTENCE_NT nodes are by far the most varied and difficult. In the pre-pass, +we call Classifying::sentence to have them diagrammed, which determines +whether they have special or regular meanings. +

+ +

Pass through a SENTENCE node3.1.2 = +

+ +
+    if (global_pass_state.pass == 0) {
+        Classifying::sentence(p);
+    } else {
+        if (SyntaxTree::is_trace_set(Task::syntax_tree())) LOG("$T", p);
+        if ((Annotations::read_int(p, language_element_ANNOT) == FALSE) &&
+            (Annotations::read_int(p, you_can_ignore_ANNOT) == FALSE)) {
+            if (Classifying::sentence_is_textual(p)) {
+                if (global_pass_state.pass == 2) {
+                    prevailing_mood = UNKNOWN_CE;
+                    Assertions::make_appearance(p);
+                }
+            } else {
+                if (p->down == NULL) internal_error("sentence misclassified");
+                internal_error_if_node_type_wrong(Task::syntax_tree(), p->down, VERB_NT);
+                prevailing_mood = Annotations::read_int(p->down, verbal_certainty_ANNOT);
+                if (Node::get_special_meaning(p->down)) Act on special meaning3.1.2.2
+                else Act on regular meaning3.1.2.3;
+            }
+        }
+    }
+
+ +

§3.1.2.1. Special meanings are handled just by calling the relevant SMF functions +with one of the following task codes. They don't get the benefit of +"refinement" (see below) unless they arrange for it themselves. +

+ +
enum PASS_1_SMFT
+enum PASS_2_SMFT
+
+

§3.1.2.2. Act on special meaning3.1.2.2 = +

+ +
+    if (global_pass_state.pass == 1)
+        MajorNodes::try_special_meaning(PASS_1_SMFT, p->down);
+    if (global_pass_state.pass == 2)
+        MajorNodes::try_special_meaning(PASS_2_SMFT, p->down);
+
+ +

§3.1.2.3. Regular meanings are more subtle: on pass 1, we "refine" them, which means +identifying unparsed noun phrases. Refiner::refine_coupling +returns TRUE if it succeeds in this. +

+ +

After that, there are two cases: existential sentences (such as "there are +two cases") and all others (such as "regular meaning are more subtle"). +

+ +

Act on regular meaning3.1.2.3 = +

+ +
+    parse_node *px = p->down->next;
+    parse_node *py = px->next;
+    if ((global_pass_state.pass > 1) ||
+        (Refiner::refine_coupling(px, py, FALSE))) {
+        if (Node::get_type(px) == DEFECTIVE_NOUN_NT) {
+            Assertions::make_existential(py);
+            Anaphora::change_discussion_from_coupling(py, py);
+        } else {
+            Assertions::make_coupling(px, py);
+            Anaphora::change_discussion_from_coupling(px, py);
+        }
+    }
+
+ +

§3.1.3.

+ +
+void MajorNodes::try_special_meaning(int task, parse_node *p) {
+    SpecialMeanings::call(Node::get_special_meaning(p), task, p, NULL);
+}
+
+

§3.1.4. A few "invention" sentences only come along later than the pre-pass, which +means they miss out on being classified at that time. When that happens, the +syntax module signals us by calling this function: +

+ +
define NEW_NONSTRUCTURAL_SENTENCE_SYNTAX_CALLBACK MajorNodes::extra_sentence
+
+
+void MajorNodes::extra_sentence(parse_node *new) {
+    if (global_pass_state.pass >= 0) Classifying::sentence(new);
+}
+
+

§3.1.5. TRACE_NT nodes result from asterisked sentences; this is a debugging feature of +Inform. An asterisk on its own toggles logging of work on sentences. An asterisk +followed by double-quoted text is a note for the telemetry file. +

+ +

Pass through a TRACE node3.1.5 = +

+ +
+    if (Wordings::length(Node::get_text(p)) > 1) {
+        int tr = telemetry_recording;
+        telemetry_recording = TRUE;
+        Telemetry::write_to_telemetry_file(
+            Lexer::word_text(Wordings::last_wn(Node::get_text(p))));
+        telemetry_recording = FALSE;
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_TelemetryAccepted),
+            "that's a message for the Author, not me",
+            "so I'll note it down in the Telemetry file (if you're keeping one.)");
+         telemetry_recording = tr;
+    } else {
+        SyntaxTree::toggle_trace(Task::syntax_tree());
+        text_stream *pass_name = NULL;
+        switch (global_pass_state.pass) {
+            case 0: pass_name = I"Pre-Pass"; break;
+            case 1: pass_name = I"Pass 1"; break;
+            case 2: pass_name = I"Pass 2"; break;
+        }
+        Log::tracing_on(SyntaxTree::is_trace_set(Task::syntax_tree()), pass_name);
+    }
+
+ +

§4.

+ +
define TRACING_LINGUISTICS_CALLBACK MajorNodes::trace_parsing
+
+
+int MajorNodes::trace_parsing(int A) {
+    if (SyntaxTree::is_trace_set(Task::syntax_tree())) return TRUE;
+    return FALSE;
+}
+
+ + +
+ + + diff --git a/docs/assertions-module/3-dlr.html b/docs/assertions-module/3-dlr.html new file mode 100644 index 000000000..2cda68585 --- /dev/null +++ b/docs/assertions-module/3-dlr.html @@ -0,0 +1,193 @@ + + + + Debugging Log Requests + + + + + + + + + + + + + + + + + + + +
+ + +

Special sentences for changing what goes into the debugging log.

+ +

§1. These are the special meaning functions for the sentences: +

+ +
+

Include ... in the debugging log. Omit ... from the debugging log.

+
+ +

Which have identical semantics except for the positive or negative sense. +The object phrase has to be exactly "the debugging log", so: +

+ +
+<debugging-log-sentence-object> ::=
+    the debugging log
+
+ +

§2.

+ +
+int Sentences::DLRs::include_in_SMF(int task, parse_node *V, wording *NPs) {
+    return Sentences::DLRs::dl_SMF(task, V, NPs, TRUE);
+}
+
+int Sentences::DLRs::omit_from_SMF(int task, parse_node *V, wording *NPs) {
+    return Sentences::DLRs::dl_SMF(task, V, NPs, FALSE);
+}
+
+

§3. The subject phrase, however, can be a list... +

+ +
+int Sentences::DLRs::dl_SMF(int task, parse_node *V, wording *NPs, int sense) {
+    wording SW = (NPs)?(NPs[2]):EMPTY_WORDING;
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    switch (task) {
+        case ACCEPT_SMFT:
+            if (<debugging-log-sentence-object>(OW)) {
+                <np-articled-list>(SW);
+                V->next = <<rp>>;
+                Sentences::DLRs::switch_dl_mode(V->next, sense);
+                return TRUE;
+            }
+            return FALSE;
+        case ALLOW_IN_OPTIONS_FILE_SMFT:
+            return TRUE;
+    }
+    return FALSE;
+}
+
+void Sentences::DLRs::switch_dl_mode(parse_node *PN, int sense) {
+    if (Node::get_type(PN) == AND_NT) {
+        Sentences::DLRs::switch_dl_mode(PN->down, sense);
+        Sentences::DLRs::switch_dl_mode(PN->down->next, sense);
+        return;
+    }
+    Sentences::DLRs::set_aspect_from_text(Node::get_text(PN), sense);
+}
+
+

§4. Each list entry must match the following, which returns a bitmap of +modifiers and a pointer to a Preform nonterminal if one has been named. +

+ +
define ONLY_DLR 1
+define EVERYTHING_DLR 2
+define NOTHING_DLR 4
+define SOMETHING_DLR 8
+define PREFORM_DLR 16
+
+
+<debugging-log-sentence-subject> ::=
+    only <debugging-log-request> |  ==> { R[1] | ONLY_DLR, RP[1] }
+    <debugging-log-request>         ==> { pass 1 }
+
+<debugging-log-request> ::=
+    everything |                    ==> { EVERYTHING_DLR, NULL }
+    nothing |                       ==> { NOTHING_DLR, NULL }
+    <preform-nonterminal> |         ==> { PREFORM_DLR, RP[1] }
+    ...                             ==> { SOMETHING_DLR, NULL }
+
+ +

§5.

+ +
+void Sentences::DLRs::set_aspect_from_text(wording W, int new_state) {
+    LOGIF(DEBUGGING_LOG_INCLUSIONS,
+        "Set contents of debugging log: %W -> %s\n",
+        W, new_state?"TRUE":"FALSE");
+
+    <debugging-log-sentence-subject>(W);
+    if (<<r>> & ONLY_DLR) Log::set_all_aspects(new_state?FALSE:TRUE);
+    if (<<r>> & EVERYTHING_DLR) { Log::set_all_aspects(new_state); return; }
+    if (<<r>> & NOTHING_DLR) { Log::set_all_aspects(1-new_state); return; }
+    if (<<r>> & SOMETHING_DLR) {
+        TEMPORARY_TEXT(req)
+        WRITE_TO(req, "%W", GET_RW(<debugging-log-request>, 1));
+        int rv = Log::set_aspect_from_command_line(req, FALSE);
+        DISCARD_TEXT(req)
+        if (rv) return;
+    }
+    if (<<r>> & PREFORM_DLR) { Instrumentation::watch(<<rp>>, new_state); return; }
+
+    Problems::quote_source(1, current_sentence);
+    Problems::quote_wording(2, W);
+    StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_UnknownDA));
+    Problems::issue_problem_segment(
+        "In the sentence %1, you asked to include '%2' in the "
+        "debugging log, but there is no such debugging log topic.");
+    Problems::issue_problem_end();
+}
+
+ + +
+ + + diff --git a/docs/assertions-module/3-nuor.html b/docs/assertions-module/3-nuor.html new file mode 100644 index 000000000..b5b941b85 --- /dev/null +++ b/docs/assertions-module/3-nuor.html @@ -0,0 +1,397 @@ + + + + New Use Option Requests + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Special sentences for creating new use options.

+ +

§1. Use options in Inform are akin to #pragma directives for the C family of +compilers: they are written in the source code of the program being compiled, +but they're not really part of that program, and are instead instructions to +the compiler to do something in a different way.1 +

+ +

Use options have natural-language names, and are created with sentences like: +

+ +
+

Use American dialect translates as (- Constant DIALECT_US; -).

+
+ +

This syntax is now rather odd-looking, but most users never need it: it's used +mainly in the Basic Inform extension to create the standard set of use options. +Note the Inform 6 notation used for the Inter code between the (- and -) +brackets. +

+ + +

§2. A "... translates as ..." sentence has this special meaning if its SP and +OP match the following: +

+ +
+<use-translates-as-sentence-subject> ::=
+    use <np-unparsed>  ==> { TRUE, RP[1] }
+
+<use-translates-as-sentence-object> ::=
+    (- ### |           ==> { -, - }
+    ...                ==> Issue PM_UseTranslatesNotI6 problem2.1
+
+ +

§2.1. Issue PM_UseTranslatesNotI6 problem2.1 = +

+ +
+    StandardProblems::sentence_problem(Task::syntax_tree(),
+        _p_(PM_UseTranslatesNotI6),
+        "that translates into something which isn't a simple Inter inclusion",
+        "placed in '(-' and '-)' markers.");
+    ==> { FALSE, - };
+
+ +

§3.

+ +
+int NewUseOptions::use_translates_as_SMF(int task, parse_node *V, wording *NPs) {
+    wording SW = (NPs)?(NPs[0]):EMPTY_WORDING;
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    switch (task) {  "Use American dialect means ..."
+        case ACCEPT_SMFT:
+            if ((<use-translates-as-sentence-object>(OW)) &&
+                (<use-translates-as-sentence-subject>(SW))) {
+                V->next = <<rp>>;
+                <np-unparsed>(OW);
+                V->next->next = <<rp>>;
+                return TRUE;
+            }
+            break;
+        case PASS_1_SMFT:
+            Create a new use option3.2;
+            break;
+    }
+    return FALSE;
+}
+
+

§3.1. Use options correspond to instances of the following: +

+ +
+typedef struct use_option {
+    struct wording name;  word range where name is stored
+    struct wording expansion;  definition as given in source
+    struct parse_node *where_used;  where the option is taken in the source
+    int option_used;  set if this option has been taken
+    int source_file_scoped;  scope is the current source file only?
+    int minimum_setting_value;  for those which are numeric
+    int notable_option_code;  or negative if not notable
+    CLASS_DEFINITION
+} use_option;
+
+ +

§3.2. Create a new use option3.2 = +

+ +
+    wording SP = Node::get_text(V->next);
+    wording OP = Node::get_text(V->next->next);
+    <use-setting>(SP);  always passes
+    int N = <<r>>;
+
+    use_option *uo = CREATE(use_option);
+    uo->name = GET_RW(<use-setting>, 1);
+    uo->expansion = OP;
+    uo->option_used = FALSE;
+    uo->minimum_setting_value = (N > 0) ? N : -1;
+    uo->source_file_scoped = FALSE;
+    uo->notable_option_code = -1;
+    if (<notable-use-option-name>(uo->name)) uo->notable_option_code = <<r>>;
+    if (uo->notable_option_code == AUTHORIAL_MODESTY_UO) uo->source_file_scoped = TRUE;
+    Nouns::new_proper_noun(uo->name, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT,
+        MISCELLANEOUS_MC, Rvalues::from_use_option(uo), Task::language_of_syntax());
+
+ +

§4. Having registered the use option names as miscellaneous, we need to parse +them back that way too: +

+ +
+use_option *NewUseOptions::parse_uo(wording OW) {
+    parse_node *p = Lexicon::retrieve(MISCELLANEOUS_MC, OW);
+    if (Rvalues::is_CONSTANT_of_kind(p, K_use_option)) return Rvalues::to_use_option(p);
+    return NULL;
+}
+
+

§5. The following sets an option. +

+ +
+void NewUseOptions::set(use_option *uo, int min_setting, source_file *from) {
+    if (uo->minimum_setting_value == -1) {
+        if (min_setting != -1)
+            StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UONotNumerical),
+                "that 'Use' option does not have a numerical setting",
+                "but is either used or not used.");
+    } else {
+        if (min_setting >= uo->minimum_setting_value)
+            uo->minimum_setting_value = min_setting;
+    }
+    if (uo->source_file_scoped) {
+        inform_extension *E = Extensions::corresponding_to(from);
+        if (E == NULL) {  that is, if used in the main source text
+            uo->option_used = TRUE;
+            uo->where_used = current_sentence;
+        }
+    } else {
+        uo->option_used = TRUE;
+        uo->where_used = current_sentence;
+    }
+    CompilationSettings::set(uo->notable_option_code,
+        uo->minimum_setting_value, from);
+}
+
+

§6. And this is what the rest of Inform calls to find out whether a particular +pragma is set: +

+ +
+int NewUseOptions::uo_set_from(use_option *uo, int category, inform_extension *E) {
+    source_file *sf = (uo->where_used)?
+        (Lexer::file_of_origin(Wordings::first_wn(Node::get_text(uo->where_used)))):NULL;
+    inform_extension *efo = (sf)?(Extensions::corresponding_to(sf)):NULL;
+    switch (category) {
+        case 1: if ((sf) && (efo == NULL)) return TRUE; break;
+        case 2: if (sf == NULL) return TRUE; break;
+        case 3: if ((sf) && (efo == E)) return TRUE; break;
+    }
+    return FALSE;
+}
+
+

§7. We can also meddle with the I6 memory settings which will be used to finish +compiling the story file. We need this because we have no practical way to +predict when our code will break I6's limits: the only reasonable way it can +work is for the user to hit the limit occasionally, and then raise that limit +by hand with a sentence in the source text. +

+ +
+typedef struct i6_memory_setting {
+    struct text_stream *ICL_identifier;  see the DM4 for the I6 memory setting names
+    int number;  e.g., 50000 means "at least 50,000"
+    CLASS_DEFINITION
+} i6_memory_setting;
+
+ +

§8.

+ +
+void NewUseOptions::memory_setting(text_stream *identifier, int n) {
+    i6_memory_setting *ms;
+    LOOP_OVER(ms, i6_memory_setting)
+        if (Str::eq(identifier, ms->ICL_identifier)) {
+            if (ms->number < n) ms->number = n;
+            return;
+        }
+    ms = CREATE(i6_memory_setting);
+    ms->ICL_identifier = Str::duplicate(identifier);
+    ms->number = n;
+}
+
+

§9. Now for indexing, where there's nothing much to see. +

+ +
define MAIN_TEXT_UO_ORIGIN 1
+define OPTIONS_FILE_UO_ORIGIN 2
+define EXTENSION_UO_ORIGIN 3
+
+
+void NewUseOptions::index(OUTPUT_STREAM) {
+    HTML_OPEN("p"); WRITE("The following use options are in force:"); HTML_CLOSE("p");
+    NewUseOptions::index_options_in_force_from(OUT, MAIN_TEXT_UO_ORIGIN, NULL);
+    NewUseOptions::index_options_in_force_from(OUT, OPTIONS_FILE_UO_ORIGIN, NULL);
+    inform_extension *E;
+    LOOP_OVER(E, inform_extension)
+        NewUseOptions::index_options_in_force_from(OUT, EXTENSION_UO_ORIGIN, E);
+    int nt = 0;
+    use_option *uo;
+    LOOP_OVER(uo, use_option) {
+        if (uo->source_file_scoped) continue;
+        if ((uo->option_used == FALSE) && (uo->minimum_setting_value < 0)) nt++;
+    }
+    if (nt > 0) {
+        HTML_OPEN("p"); WRITE("Whereas these are not in force:"); HTML_CLOSE("p");
+        HTML::open_indented_p(OUT, 2, "tight");
+        LOOP_OVER(uo, use_option) {
+            if (uo->source_file_scoped) continue;
+            if ((uo->option_used == FALSE) && (uo->minimum_setting_value < 0)) {
+                Write in the index line for a use option not taken9.1;
+                if (--nt > 0) WRITE(", ");
+            }
+        }
+        HTML_CLOSE("p");
+    }
+}
+
+

§9.1. Write in the index line for a use option not taken9.1 = +

+ +
+    HTML_OPEN_WITH("span", "style=\"white-space:nowrap\";");
+    TEMPORARY_TEXT(TEMP)
+    WRITE_TO(TEMP, "Use %+W.", uo->name);
+    PasteButtons::paste_text(OUT, TEMP);
+    DISCARD_TEXT(TEMP)
+    WRITE("&nbsp;%+W", uo->name);
+    HTML_CLOSE("span");
+
+ +

§10.

+ +
+void NewUseOptions::index_options_in_force_from(OUTPUT_STREAM, int category, inform_extension *E) {
+    int N = 0;
+    use_option *uo;
+    LOOP_OVER(uo, use_option) {
+        if (uo->source_file_scoped) continue;
+        if ((uo->option_used) && (uo->minimum_setting_value < 0) &&
+            (NewUseOptions::uo_set_from(uo, category, E))) {
+            if (N++ == 0) Write in the use option subheading10.1;
+            Write in the index line for a use option taken10.2;
+        }
+    }
+    LOOP_OVER(uo, use_option) {
+        if (uo->source_file_scoped) continue;
+        if (((uo->option_used) && (uo->minimum_setting_value >= 0)) &&
+            (NewUseOptions::uo_set_from(uo, category, E))) {
+            if (N++ == 0) Write in the use option subheading10.1;
+            Write in the index line for a use option taken10.2;
+        }
+    }
+}
+
+

§10.1. Write in the use option subheading10.1 = +

+ +
+    HTML::open_indented_p(OUT, 2, "tight");
+    HTML::begin_colour(OUT, I"808080");
+    WRITE("Set from ");
+    switch (category) {
+        case MAIN_TEXT_UO_ORIGIN:
+            WRITE("the source text"); break;
+        case OPTIONS_FILE_UO_ORIGIN:
+            WRITE("the Options.txt configuration file");
+            Index::DocReferences::link(OUT, I"OPTIONSFILE"); break;
+        case EXTENSION_UO_ORIGIN:
+            if (Extensions::is_standard(E)) WRITE("the ");
+            else WRITE("the extension ");
+            WRITE("%S", E->as_copy->edition->work->title);
+            break;
+    }
+    WRITE(":");
+    HTML::end_colour(OUT);
+    HTML_CLOSE("p");
+
+ +

§10.2. Write in the index line for a use option taken10.2 = +

+ +
+    HTML::open_indented_p(OUT, 3, "tight");
+    WRITE("Use %+W", uo->name);
+    if (uo->minimum_setting_value >= 0) WRITE(" of at least %d", uo->minimum_setting_value);
+    if (uo->where_used) Index::link(OUT, Wordings::first_wn(Node::get_text(uo->where_used)));
+    if (uo->minimum_setting_value >= 0) {
+        WRITE("&nbsp;");
+        TEMPORARY_TEXT(TEMP)
+        WRITE_TO(TEMP, "Use %+W of at least %d.", uo->name, 2*(uo->minimum_setting_value));
+        PasteButtons::paste_text(OUT, TEMP);
+        DISCARD_TEXT(TEMP)
+        WRITE("&nbsp;<i>Double this</i>");
+    }
+    HTML_CLOSE("p");
+
+ + + +
+ + + diff --git a/docs/assertions-module/3-pr.html b/docs/assertions-module/3-pr.html new file mode 100644 index 000000000..00f9819df --- /dev/null +++ b/docs/assertions-module/3-pr.html @@ -0,0 +1,158 @@ + + + + Pluralisation Requests + + + + + + + + + + + + + + + + + + + +
+ + +

Special sentences for setting exotic plural forms of nouns.

+ +

§1. Sentences like "the plural of cherub is cherubim" are hardly needed now, +because the inflections module now contains a full implementation of +Conway's algorithm. Still, we keep the syntax around, and it may one day be +useful again for languages other than English. +

+ +

The subject phrase must match: +

+ +
+<plural-sentence-subject> ::=
+    <article> plural of <np-articled> |  ==> { pass 2 }
+    plural of <np-articled>              ==> { pass 1 }
+
+ +

§2. Note that we are saved later grief by not allowing a plural form which +would be illegal as a new noun: allowing "The plural of thing is ," would not +end well. +

+ +

Otherwise, though, we simply send the request to Pluralisation (in inflections). +

+ +
+int Plurals::plural_SMF(int task, parse_node *V, wording *NPs) {
+    wording SW = (NPs)?(NPs[0]):EMPTY_WORDING;
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    switch (task) {  "The plural of seraph is seraphim."
+        case ACCEPT_SMFT:
+            if (<plural-sentence-subject>(SW)) {
+                V->next = <<rp>>;
+                <np-unparsed>(OW);
+                V->next->next = <<rp>>;
+                wording S = Node::get_text(V->next);
+                wording P = Node::get_text(V->next->next);
+                Forbid plural declarations containing quoted text2.1;
+                if (Assertions::Creator::vet_name_for_noun(P) == FALSE) return TRUE;
+                Pluralisation::register(S, P, DefaultLanguage::get(NULL));
+                return TRUE;
+            }
+            break;
+    }
+    return FALSE;
+}
+
+

§2.1. In general names of things which we need plurals for cannot contain quoted +text anyway, so the following problem messages are not too gratuitous. +

+ +

Forbid plural declarations containing quoted text2.1 = +

+ +
+    LOOP_THROUGH_WORDING(i, S)
+        if (Vocabulary::test_flags(i, TEXT_MC + TEXTWITHSUBS_MC)) {
+            StandardProblems::sentence_problem(Task::syntax_tree(),
+                _p_(PM_PluralOfQuoted),
+                "declares a plural for a phrase containing quoted text",
+                "which is forbidden. Sentences like this are supposed to "
+                "declare plurals without quotation marks: for instance, "
+                "'The plural of attorney general is attorneys general.'");
+            return TRUE;
+        }
+    LOOP_THROUGH_WORDING(i, P)
+        if (Vocabulary::test_flags(i, TEXT_MC + TEXTWITHSUBS_MC)) {
+            StandardProblems::sentence_problem(Task::syntax_tree(),
+                _p_(PM_PluralIsQuoted),
+                "declares a plural for a phrase using quoted text",
+                "which is forbidden. Sentences like this are supposed to "
+                "declare plurals without quotation marks: for instance, "
+                "'The plural of procurator fiscal is procurators fiscal.'");
+            return TRUE;
+        }
+
+ + + +
+ + + diff --git a/docs/assertions-module/3-tr.html b/docs/assertions-module/3-tr.html new file mode 100644 index 000000000..90b60c82a --- /dev/null +++ b/docs/assertions-module/3-tr.html @@ -0,0 +1,522 @@ + + + + Translation Requests + + + + + + + + + + + + + + + + + + + +
+ + +

Three unrelated senses of "X translates into Y as Z" sentences.

+ +
+ +

§1. Translation into natural languages. The sentence "X translates into Y as Z" has this sense provided Y matches: +

+ +
+<translation-target-language> ::=
+    <natural-language>  ==> { pass 1 }
+
+ +

§2.

+ +
+int Translations::translates_into_language_as_SMF(int task, parse_node *V, wording *NPs) {
+    wording SW = (NPs)?(NPs[0]):EMPTY_WORDING;
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    wording O2W = (NPs)?(NPs[2]):EMPTY_WORDING;
+    switch (task) {  "Thing translates into French as chose"
+        case ACCEPT_SMFT:
+            if (<translation-target-language>(O2W)) {
+                inform_language *nl = (inform_language *) (<<rp>>);
+                <np-articled>(SW);
+                V->next = <<rp>>;
+                <np-articled>(OW);
+                V->next->next = <<rp>>;
+                Node::set_defn_language(V->next->next, nl);
+                return TRUE;
+            }
+            break;
+        case PASS_1_SMFT:
+            Parse subject phrase and send the translation to the linguistics module2.2;
+            break;
+    }
+    return FALSE;
+}
+
+

§2.1. The subject phrase can only be parsed on traverse 1, since it only makes +sense once kinds and instances exist. +

+ +
define TRANS_KIND 1
+define TRANS_INSTANCE 2
+
+
+<translates-into-language-sentence-subject> ::=
+    <k-kind> |  ==> { TRANS_KIND, RP[1] }
+    <instance>  ==> { TRANS_INSTANCE, RP[1] }
+
+ +

§2.2. Parse subject phrase and send the translation to the linguistics module2.2 = +

+ +
+    wording SP = Node::get_text(V->next);
+    wording OP = Node::get_text(V->next->next);
+    inform_language *L = Node::get_defn_language(V->next->next);
+    int g = Annotations::read_int(V->next->next, explicit_gender_marker_ANNOT);
+    if (L == NULL) internal_error("No such NL");
+    if (L == DefaultLanguage::get(NULL)) {
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_CantTranslateIntoEnglish),
+            "you can't translate from a language into itself",
+            "only from the current language to a different one.");
+        return FALSE;
+    }
+
+    if ((<translates-into-language-sentence-subject>(SP)) == FALSE) {
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_CantTranslateValue),
+            "this isn't something which can be translated",
+            "that is, it isn't a kind or instance.");
+        return FALSE;
+    }
+
+    switch (<<r>>) {
+        case TRANS_INSTANCE: {
+            instance *I = <<rp>>;
+            noun *t = Instances::get_noun(I);
+            if (t == NULL) internal_error("stuck on instance name");
+            Nouns::supply_text(t, OP, L, g, SINGULAR_NUMBER, ADD_TO_LEXICON_NTOPT);
+            break;
+        }
+        case TRANS_KIND: {
+            kind *K = <<rp>>;
+            kind_constructor *KC = Kinds::get_construct(K);
+            if (KC == NULL) internal_error("stuck on kind name");
+            noun *t = Kinds::Constructors::get_noun(KC);
+            if (t == NULL) internal_error("further stuck on kind name");
+            Nouns::supply_text(t, OP, L, g, SINGULAR_NUMBER,
+                ADD_TO_LEXICON_NTOPT + WITH_PLURAL_FORMS_NTOPT);
+            break;
+        }
+        default: internal_error("bad translation category");
+    }
+
+ +

§3. Translation into Unicode. The following handles sentences like: +

+ +
+

leftwards harpoon with barb upwards translates into Unicode as 8636.

+
+ +

The subject "leftwards harpoon with barb upwards" is parsed against the +Unicode character names known already to make sure that this new translation +doesn't disagree with an existing one (that is, doesn't translate to a +different code number). +

+ +

The sentence "X translates into Y as Z" has this sense provided Y matches: +

+ +
+<translation-target-unicode> ::=
+    unicode
+
+ +

§4.

+ +
+int Translations::translates_into_unicode_as_SMF(int task, parse_node *V, wording *NPs) {
+    wording SW = (NPs)?(NPs[0]):EMPTY_WORDING;
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    wording O2W = (NPs)?(NPs[2]):EMPTY_WORDING;
+    switch (task) {  "Black king chess piece translates into Unicode as 9818"
+        case ACCEPT_SMFT:
+            if (<translation-target-unicode>(O2W)) {
+                <np-articled>(SW);
+                V->next = <<rp>>;
+                <np-articled>(OW);
+                V->next->next = <<rp>>;
+                return TRUE;
+            }
+            break;
+        case PASS_2_SMFT:
+            Create the Unicode character name4.1;
+            break;
+    }
+    return FALSE;
+}
+
+

§5. And this parses the noun phrases of such sentences. Note that the numeric +values has to be given in decimal — I was tempted to allow hexadecimal here, +but life's too short. Unicode translation sentences are really only +technicalities needed by the built-in extensions, and those are mechanically +generated anyway; Inform authors never type them. +

+ +
+<translates-into-unicode-sentence-subject> ::=
+    <unicode-character-name> |     ==> { pass 1 }
+    ...                            ==> { -1, - }
+
+<translates-into-unicode-sentence-object> ::=
+    <cardinal-number-unlimited> |  ==> { UnicodeLiterals::range(R[1]), - }
+    ...                            ==> Issue PM_UnicodeNonLiteral problem5.1
+
+ +

§5.1. Issue PM_UnicodeNonLiteral problem5.1 = +

+ +
+    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UnicodeNonLiteral),
+        "a Unicode character name must be translated into a literal decimal "
+        "number written out in digits",
+        "which this seems not to be.");
+    return FALSE;
+
+ +

§4.1. And here the name is created as a miscellaneous excerpt meaning. +

+ +

Create the Unicode character name4.1 = +

+ +
+    wording SP = Node::get_text(V->next);
+    wording OP = Node::get_text(V->next->next);
+    if (<translates-into-unicode-sentence-object>(OP) == FALSE) return FALSE;
+    int cc = <<r>>;
+
+    <translates-into-unicode-sentence-subject>(SP);
+    if ((<<r>> != -1) && (<<r>> != cc)) {
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_UnicodeAlready),
+            "this Unicode character name has already been translated",
+            "so there must be some duplication somewhere.");
+        return FALSE;
+    }
+
+    Nouns::new_proper_noun(SP, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT, MISCELLANEOUS_MC,
+        Diagrams::new_PROPER_NOUN(OP), Task::language_of_syntax());
+
+ +

§6. Translation into Inter. The sentence "X translates into Y as Z" has this sense provided Y matches the +following. Before the coming of Inter code, the only conceivable compilation +target was Inform 6, but these now set Inter identifiers, so really the first +wording is to be preferred. +

+ +
+<translation-target-i6> ::=
+    inter |
+    i6 |
+    inform 6
+
+ +

§7.

+ +
enum INTER_NAMING_SMFT
+
+
+int Translations::translates_into_Inter_as_SMF(int task, parse_node *V, wording *NPs) {
+    wording SW = (NPs)?(NPs[0]):EMPTY_WORDING;
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    wording O2W = (NPs)?(NPs[2]):EMPTY_WORDING;
+    switch (task) {  "The taking inventory action translates into Inter as "Inv""
+        case ACCEPT_SMFT:
+            if (<translation-target-i6>(O2W)) {
+                <np-articled>(SW);
+                V->next = <<rp>>;
+                <np-articled>(OW);
+                V->next->next = <<rp>>;
+                return TRUE;
+            }
+            break;
+        case PASS_1_SMFT:
+        case PASS_2_SMFT:
+            Act on the Inter translation7.2;
+            break;
+        case INTER_NAMING_SMFT:
+            Act on late naming7.5;
+            break;
+    }
+    return FALSE;
+}
+
+

§8. Translations can be made in a number of contexts: +

+ +
define INVALID_I6TR -1
+define PROPERTY_I6TR 0       "The open property translates into I6 as "open"."
+define NOUN_I6TR 1           "The north object translates into I6 as "n_obj"."
+define RULE_I6TR 2           "The baffling rule translates into I6 as "BAFFLING_R"."
+define VARIABLE_I6TR 3       "The sludge count variable translates into I6 as "sldgc".
+define ACTION_I6TR 4         "The taking action translates into I6 as "Take".
+define GRAMMAR_TOKEN_I6TR 5  "The grammar token "[whatever]" translates into I6 as "WHATEVER".
+
+
+<translates-into-i6-sentence-subject> ::=
+    ... property |          ==> { PROPERTY_I6TR, - }
+    ... object/kind |       ==> { NOUN_I6TR, - }
+    {... rule} |            ==> { RULE_I6TR, - }
+    ... variable |          ==> { VARIABLE_I6TR, - }
+    ... action |            ==> { ACTION_I6TR, - }
+    understand token ... |  ==> { GRAMMAR_TOKEN_I6TR, - }
+    ...                     ==> Issue PM_TranslatedUnknownCategory problem8.1
+
+ +

§8.1. Issue PM_TranslatedUnknownCategory problem8.1 = +

+ +
+    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_TranslatedUnknownCategory),
+        "that isn't one of the things which can be translated to I6",
+        "and should be '... variable', '... property', '... object', "
+        "'... kind', '... rule', or '... action'. For instance, 'The yourself "
+        "object translates into I6 as \"selfobj\".'");
+    ==> { INVALID_I6TR, - };
+
+ +

§7.1. The object noun phrase is usually just an I6 identifier in quotation marks, +but it's also possible to list literal texts (for the benefit of rules). +Following the optional "with" is an articled list, each entry of which +will be required to pass <extra-response>. +

+ +
+<translates-into-i6-sentence-object> ::=
+    <quoted-text> with <np-articled-list> |    ==> { R[1], RP[2] }
+    <quoted-text>                              ==> { R[1], NULL }
+
+ +

§7.2. Act on the Inter translation7.2 = +

+ +
+    parse_node *p1 = V->next;
+    parse_node *p2 = V->next->next;
+    parse_node *responses_list = NULL;
+    int category = INVALID_I6TR;
+    <translates-into-i6-sentence-subject>(Node::get_text(p1));
+    category = <<r>>;
+    if (category != INVALID_I6TR) {
+        wording W = GET_RW(<translates-into-i6-sentence-subject>, 1);
+
+        if (global_pass_state.pass == 1) {
+            Annotations::write_int(V, category_of_I6_translation_ANNOT, INVALID_I6TR);
+            Ensure that we are translating to a quoted I6 identifier7.2.1;
+            Annotations::write_int(V, category_of_I6_translation_ANNOT, category);
+            if (responses_list) SyntaxTree::graft(Task::syntax_tree(), responses_list, p2);
+        } else category = Annotations::read_int(V, category_of_I6_translation_ANNOT);
+
+        Take action in pass 1 or 2 where possible7.2.2;
+    }
+
+ +

§7.2.1. Ensure that we are translating to a quoted I6 identifier7.2.1 = +

+ +
+    int valid = TRUE;
+    if (<translates-into-i6-sentence-object>(Node::get_text(p2)) == FALSE) valid = FALSE;
+    else responses_list = <<rp>>;
+    if (valid) Dequote it and see if it's valid7.2.1.1;
+    if (valid == FALSE) {
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_TranslatedToNonIdentifier),
+            "Inform 7 constructions can only translate into quoted I6 identifiers",
+            "which must be strings of 1 to 31 characters drawn from 1, 2, ..., 9, "
+            "a or A, b or B, ..., z or Z, or underscore '_', except that the "
+            "first character is not allowed to be a digit.");
+        return FALSE;
+    }
+
+ +

§7.2.1.1. If it turns out not to be, we simply set valid to false. +

+ +

Dequote it and see if it's valid7.2.1.1 = +

+ +
+    int wn = Wordings::first_wn(Node::get_text(p2));
+    Node::set_text(p2, Wordings::one_word(wn));
+    Word::dequote(wn);
+    if (valid) valid = Identifiers::valid(Lexer::word_text(wn));
+
+ +

§7.2.2. In some cases, we act on pass 1, but in others pass 2, and in the case of +NOUN_I6TR, later even than that. There are messy timing issues here. +

+ +

Take action in pass 1 or 2 where possible7.2.2 = +

+ +
+    switch(category) {
+        case PROPERTY_I6TR:
+            Properties::translates(W, p2);
+            Annotations::write_int(V, category_of_I6_translation_ANNOT, INVALID_I6TR);
+            break;
+        case NOUN_I6TR: break;
+        case RULE_I6TR:
+            if (global_pass_state.pass == 1)
+                Rules::declare_I6_written_rule(W, p2);
+            if ((global_pass_state.pass == 2) && (p2->down) && (<rule-name>(W)))
+                Translations::plus_responses(p2->down, <<rp>>);
+            break;
+        case VARIABLE_I6TR:
+            if (global_pass_state.pass == 2) NonlocalVariables::translates(W, p2);
+            break;
+        #ifdef IF_MODULE
+        case ACTION_I6TR:
+            if (global_pass_state.pass == 2) PL::Actions::translates(W, p2);
+            break;
+        case GRAMMAR_TOKEN_I6TR:
+            if (global_pass_state.pass == 2) PL::Parsing::Verbs::translates(W, p2);
+            break;
+        #endif
+    }
+
+ +

§7.3. Extra responses look just as they would in running code. +

+ +
+<extra-response> ::=
+    <quoted-text> ( <response-letter> )  ==> { pass 2 }
+
+ +

§7.4.

+ +
+void Translations::plus_responses(parse_node *p, rule *R) {
+    if (Node::get_type(p) == AND_NT) {
+        Translations::plus_responses(p->down, R);
+        Translations::plus_responses(p->down->next, R);
+    } else {
+        if (<extra-response>(Node::get_text(p))) {
+            int code = <<r>>;
+            response_message *resp = Strings::response_cue(NULL, R,
+                code, Node::get_text(p), NULL, TRUE);
+            Rules::now_rule_defines_response(R, code, resp);
+        } else {
+            StandardProblems::sentence_problem(Task::syntax_tree(),
+                _p_(PM_I6ResponsesAwry),
+                "additional information about I6 translation of a rule can "
+                "only take the form of a list of responses",
+                "each quoted and followed by a bracketed letter.");
+        }
+    }
+}
+
+

§7.5. As noted above, NOUN_I6TR renamings happen much later on. +

+ +

Act on late naming7.5 = +

+ +
+    wording SP = Node::get_text(V->next);
+    wording OP = Node::get_text(V->next->next);
+    int category = Annotations::read_int(V, category_of_I6_translation_ANNOT);
+    switch(category) {
+        case NOUN_I6TR: {
+            wording W = Wordings::trim_last_word(SP);
+            parse_node *res = Lexicon::retrieve(NOUN_MC, W);
+            if (res) {
+                noun_usage *nu = Nouns::disambiguate(res, FALSE);
+                noun *nt = (nu)?(nu->noun_used):NULL;
+                if (nt) {
+                    TEMPORARY_TEXT(i6r)
+                    WRITE_TO(i6r, "%N", Wordings::first_wn(OP));
+                    UseNouns::noun_set_I6_representation(nt, i6r);
+                    DISCARD_TEXT(i6r)
+                }
+            } else {
+                StandardProblems::sentence_problem(Task::syntax_tree(),
+                    _p_(PM_BadObjectTranslation),
+                    "there is no such object or kind of object",
+                    "so its name will never be translated into an Inter "
+                    "identifier in any event.");
+            }
+            break;
+        }
+    }
+
+ + + +
+ + + diff --git a/docs/assertions-module/3-uor.html b/docs/assertions-module/3-uor.html new file mode 100644 index 000000000..d725709e5 --- /dev/null +++ b/docs/assertions-module/3-uor.html @@ -0,0 +1,220 @@ + + + + Use Options + + + + + + + + + + + + + + + + + + + +
+ + +

Special sentences for setting compilation options.

+ +
+ +

§1. The Use sentence. Note that any sentence beginning with the word "Use" is accepted here, which +is a very wide net: unlike most special meaning sentences, there's no attempt +to cut down the risk of false positives by screening the noun phrase. +

+ +
+int UseOptions::use_SMF(int task, parse_node *V, wording *NPs) {
+    wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
+    switch (task) {  "Use American dialect."
+        case ACCEPT_SMFT:
+            <np-articled-list>(OW);
+            V->next = <<rp>>;
+            return TRUE;
+        case ALLOW_IN_OPTIONS_FILE_SMFT:
+            return TRUE;
+        case PASS_1_SMFT:
+        case PASS_2_SMFT:
+            UseOptions::set_use_options(V->next);
+            break;
+    }
+    return FALSE;
+}
+
+

§2. "Use" sentences are simple in structure. Their object noun phrases are +articled lists: +

+ +
+

Use American dialect and the serial comma.

+
+ +
+void UseOptions::set_use_options(parse_node *p) {
+    if (Node::get_type(p) == AND_NT) {
+        UseOptions::set_use_options(p->down);
+        UseOptions::set_use_options(p->down->next);
+        return;
+    }
+    Set a single use option2.2;
+}
+
+

§2.1. Each of the entries in this list must match the following; the text of the +option name is taken from the ... or ### as appropriate: +

+ +
+<use-inter-pipeline> ::=
+    inter pipeline {<quoted-text>}                 ==> { TRUE, - }
+
+<use-memory-setting> ::=
+    ### of <cardinal-number-unlimited>             ==> { R[1], - }
+
+<use-setting> ::=
+    ... of at least <cardinal-number-unlimited> |  ==> { R[1], - }
+    <definite-article> ...	|                      ==> { -1, - }
+    ...                                            ==> { -1, - }
+
+ +

§2.2. Set a single use option2.2 = +

+ +
+    wording S = Node::get_text(p);
+    if (<use-inter-pipeline>(S))
+        Set the pipeline given in this word range2.2.1
+    else if (<use-memory-setting>(S))
+        Set a memory setting2.2.2
+    else if (<use-setting>(S))
+        Set the option given in this word range2.2.3
+
+ +

§2.2.1. This is an undocumented feature used during the transition from I6 to Inter: +

+ +

Set the pipeline given in this word range2.2.1 = +

+ +
+    wording CW = GET_RW(<use-inter-pipeline>, 1);
+    if (global_pass_state.pass == 1) {
+        TEMPORARY_TEXT(p)
+        WRITE_TO(p, "%W", CW);
+        Str::delete_first_character(p);
+        Str::delete_last_character(p);
+        Supervisor::set_inter_pipeline(p);
+        DISCARD_TEXT(p)
+    }
+
+ +

§2.2.2. ICL, the "Inform 6 control language", is a set of a pragma-like settings for +the I6 compiler. Of course, in the age in Inter, those might well be ignored, +since the compiler next down the chain may no longer be I6. +

+ +

See //runtime:Use Options at Run Time// for what happens to these. +

+ +

Set a memory setting2.2.2 = +

+ +
+    int n = <<r>>, w1 = Wordings::first_wn(S);
+    TEMPORARY_TEXT(icl_identifier)
+    WRITE_TO(icl_identifier, "%+W", Wordings::one_word(w1));
+    if (Str::len(icl_identifier) > 63) {
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_BadICLIdentifier),
+            "that is too long to be an ICL identifier",
+            "so can't be the name of any I6 memory setting.");
+    }
+    NewUseOptions::memory_setting(icl_identifier, n);
+    DISCARD_TEXT(icl_identifier)
+
+ +

§2.2.3. Whereas thus is the standard use option syntax: +

+ +

Set the option given in this word range2.2.3 = +

+ +
+    int min_setting = <<r>>;
+    wording OW = GET_RW(<use-setting>, 1);
+    use_option *uo = NewUseOptions::parse_uo(OW);
+    if (uo) NewUseOptions::set(uo, min_setting,
+        Lexer::file_of_origin(Wordings::first_wn(OW)));
+    else if (global_pass_state.pass > 1) {
+        LOG("Used: %W\n", S);
+        StandardProblems::sentence_problem(Task::syntax_tree(),
+            _p_(PM_UnknownUseOption),
+            "that isn't a 'Use' option known to me",
+            "and needs to be one of the ones listed in the documentation.");
+    }
+
+ + + +
+ + + diff --git a/docs/assertions-module/P-wtmd.html b/docs/assertions-module/P-wtmd.html index 2ee1c8ea3..ea7268bcf 100644 --- a/docs/assertions-module/P-wtmd.html +++ b/docs/assertions-module/P-wtmd.html @@ -88,7 +88,7 @@ For more, see §2. Assertions. Top-level declarations are dealt with thus:

- diff --git a/docs/inflections-module/1-im.html b/docs/inflections-module/1-im.html index 1e459d47e..ea731cfa6 100644 --- a/docs/inflections-module/1-im.html +++ b/docs/inflections-module/1-im.html @@ -32,7 +32,11 @@
  • supervisor
  • Inform7 Modules

    Services

    @@ -58,14 +64,14 @@

    Setting up the use of this module.

    -

    §1. This section simoly sets up the module in ways expected by foundation, and +

    §1. This section simoly sets up the module in ways expected by foundation, and contains no code of interest. The following constant exists only in tools which use this module:

    define INFLECTIONS_MODULE TRUE
     
    -

    §2. This module defines the following classes: +

    §2. This module defines the following classes:

    enum lexical_cluster_CLASS
    @@ -79,7 +85,7 @@ which use this module:
     DECLARE_CLASS(plural_dictionary_entry)
     DECLARE_CLASS(verb_conjugation)
     
    -

    §3. Like all modules, this one must define a start and end function: +

    §3. Like all modules, this one must define a start and end function:

    enum CONSTRUCTED_PAST_PARTICIPLES_DA
    diff --git a/docs/inflections-module/2-ai.html b/docs/inflections-module/2-ai.html
    index 33dfedb39..6dbb459a1 100644
    --- a/docs/inflections-module/2-ai.html
    +++ b/docs/inflections-module/2-ai.html
    @@ -32,7 +32,11 @@
     
  • supervisor
  • Inform7 Modules

    Services

    @@ -58,7 +64,7 @@

    To inflect "a" into "an", and so forth.

    -

    §1. Here we take text such as "UNESCO document" and put an article in front, to +

    §1. Here we take text such as "UNESCO document" and put an article in front, to get "a UNESCO document" (and not "an UNESCO document": these things are much trickier than they look).

    diff --git a/docs/inflections-module/2-ga.html b/docs/inflections-module/2-ga.html index 6a398d5bb..49376d693 100644 --- a/docs/inflections-module/2-ga.html +++ b/docs/inflections-module/2-ga.html @@ -33,7 +33,11 @@
  • supervisor
  • Inform7 Modules

    Services

    @@ -59,7 +65,7 @@

    To inflect adjectives into comparative and superlative forms.

    -

    §1. In English, the comparative of an adjective can generally be formed by +

    §1. In English, the comparative of an adjective can generally be formed by suffixing the inflected form with "than"; thus, "big" to "bigger than". The following does the suffixing:

    @@ -69,7 +75,7 @@ The following does the suffixing: ... than
    -

    §2. This is essentially a wrapper function for the trie <adjective-to-comparative>. +

    §2. This is essentially a wrapper function for the trie <adjective-to-comparative>.

    @@ -96,7 +102,7 @@ The following does the suffixing:
         return PW;
     }
     
    -

    §3. This is essentially a wrapper function for the trie <adjective-to-superlative>. +

    §3. This is essentially a wrapper function for the trie <adjective-to-superlative>.

    @@ -119,7 +125,7 @@ The following does the suffixing:
         return PW;
     }
     
    -

    §4. This is essentially a wrapper function for the trie <adjective-to-quiddity>. +

    §4. This is essentially a wrapper function for the trie <adjective-to-quiddity>. There has to be a better term than "quiddity" for this grammatical concept (it is some sort of morphological nominalisation) but what I mean is the property of which the given adjective makes a comparison: for instance, diff --git a/docs/inflections-module/2-plr.html b/docs/inflections-module/2-plr.html index 9fcd118f5..718bf520d 100644 --- a/docs/inflections-module/2-plr.html +++ b/docs/inflections-module/2-plr.html @@ -40,7 +40,11 @@ function togglePopup(material_id) {

  • supervisor
  • Inform7 Modules

    Services

    @@ -68,7 +74,7 @@ function togglePopup(material_id) {
    -

    §1. Dictionary. A modest dictionary of plurals is maintained to allow the user to record +

    §1. Dictionary. A modest dictionary of plurals is maintained to allow the user to record better plurals than the ones we would make ourselves. This assumes that a plural can be constructed without knowledge of context, but that works in almost all cases. (Arguably "dwarf" should pluralise to "dwarfs" when @@ -85,7 +91,7 @@ to be hoped that few works of IF will contain both at once.) } plural_dictionary_entry;

    -

    §2. Note that we are entirely allowed to register a new plural for a phrase +

    §2. Note that we are entirely allowed to register a new plural for a phrase which already has a plural in the dictionary, even for the same language, which is why we do not trouble to search the existing dictionary here.

    @@ -99,7 +105,7 @@ which is why we do not trouble to search the existing dictionary here. LOGIF(CONSTRUCTED_PLURALS, "[Registering plural of %W as %W]\n", S, P); } -

    §3. Searching the plural dictionary. The following routine can either be called once only — in which case it +

    §3. Searching the plural dictionary. The following routine can either be called once only — in which case it yields up the best known plural for the phrase — or iteratively, in which case it serves up all known plurals of the given phrase, starting with the best (the earliest defined in the text, if any plural for this phrase has @@ -131,7 +137,7 @@ one not found in the dictionary). return NULL; } -

    §3.1. When the dictionary fails us, we use lexical rewriting to construct plurals +

    §3.1. When the dictionary fails us, we use lexical rewriting to construct plurals of phrases found only in the singular in the source. For instance, if the designer says that "A wicker basket is a kind of container" then Inform will need to recognise not only "wicker basket" but also "wicker baskets", a @@ -163,7 +169,7 @@ it can be rebuilt quickly whenever needed again. LOGIF(CONSTRUCTED_PLURALS, "[Constructing plural of %W as %W]\n", W, *PW);

    -

    §4. The pluralizing trie. The following takes a single word, assumes it to be a noun which meaningfully +

    §4. The pluralizing trie. The following takes a single word, assumes it to be a noun which meaningfully has a plural, and modifies it to the plural form.

    diff --git a/docs/inflections-module/2-pp.html b/docs/inflections-module/2-pp.html index d1825bfe5..a6c1bd6e9 100644 --- a/docs/inflections-module/2-pp.html +++ b/docs/inflections-module/2-pp.html @@ -40,7 +40,11 @@ function togglePopup(material_id) {
  • supervisor
  • Inform7 Modules

    Services

    @@ -68,7 +74,7 @@ function togglePopup(material_id) {
    -

    §1. Constructing past participles. For example, "turning away" to "turned away". +

    §1. Constructing past participles. For example, "turning away" to "turned away".

    @@ -95,7 +101,7 @@ function togglePopup(material_id) {
         return PLW;
     }
     
    -

    §2. The pasturising trie. This is the process of turning a present participle, like "turning", to +

    §2. The pasturising trie. This is the process of turning a present participle, like "turning", to a past participle, like "turned". Note that it returns NULL if it fails to recognise the word in question as a present participle; this is needed above. It expects only a single word. diff --git a/docs/inflections-module/2-tai.html b/docs/inflections-module/2-tai.html index 58253b7ed..9ecc53060 100644 --- a/docs/inflections-module/2-tai.html +++ b/docs/inflections-module/2-tai.html @@ -40,7 +40,11 @@ function togglePopup(material_id) {

  • supervisor
  • Inform7 Modules

    Services

    @@ -68,7 +74,7 @@ function togglePopup(material_id) {
    -

    §1. Suffix inflections. The following inflects the ending of the supplied text. It does so by +

    §1. Suffix inflections. The following inflects the ending of the supplied text. It does so by running the text through an avinue: see Tries and Avinues (in foundation), which is where the asterisk notation is handled.

    @@ -79,7 +85,7 @@ which is where the asterisk notation is handled. return Inflect::follow_suffix_instruction(OUT, from, result); } -

    §2. The foundation code returns a result which may be null, if no match +

    §2. The foundation code returns a result which may be null, if no match was found. In that event, we leave the text unchanged, just as if the result had been 0 — meaning "change nothing".

    @@ -96,7 +102,7 @@ had been 0 &mda return success; } -

    §2.1. In general the result either has an initial digit, in which case it removes +

    §2.1. In general the result either has an initial digit, in which case it removes that many terminal letters, or does not, in which case it removes all the letters (and thus the result text replaces the original entirely). The special character + after a digit means "duplicate the last character"; @@ -125,7 +131,7 @@ add "ize". }

    -

    §2.2. Write the output, interpreting plus signs as word breaks2.2 = +

    §2.2. Write the output, interpreting plus signs as word breaks2.2 =

    @@ -134,7 +140,7 @@ add "ize".
             else PUT(Str::get(pos));
     
    -

    §3. General tries. Here we take a word assemblage and apply suffix inflection to the first word +

    §3. General tries. Here we take a word assemblage and apply suffix inflection to the first word alone, preserving the rest: for example, "make the tea" might become "making the tea". However, if the result of this inflection contains any + signs, those once again become word boundaries. diff --git a/docs/inflections-module/3-dcl.html b/docs/inflections-module/3-dcl.html index 9c36ac6fe..318342e11 100644 --- a/docs/inflections-module/3-dcl.html +++ b/docs/inflections-module/3-dcl.html @@ -54,7 +54,11 @@ MathJax = {

  • supervisor
  • Inform7 Modules

    Services

    @@ -80,7 +86,7 @@ MathJax = {

    Declensions are sets of inflected variations of a common stem according to grammatical case.

    -

    §1. The traditional term "declension" refers to the set of inflected forms of a +

    §1. The traditional term "declension" refers to the set of inflected forms of a word which does not serve as a verb: nouns, adjectives and pronouns all have "declensions". These forms generally vary according to gender, number and also "case", which expresses context. @@ -102,7 +108,7 @@ taken care of by what are less elegantly called } declension;

    -

    §2. Cases in a language are itemised in the special nonterminal <grammatical-case-names>: +

    §2. Cases in a language are itemised in the special nonterminal <grammatical-case-names>:

    @@ -121,7 +127,7 @@ taken care of by what are less elegantly called     return -1;
     }
     
    -

    §3. The following is useful for debugging: +

    §3. The following is useful for debugging:

    @@ -150,7 +156,7 @@ taken care of by what are less elegantly called     internal_error("<grammatical-case-names> not provided for this language");
     }
     
    -

    §4. And this function extracts the right form for a given case c: +

    §4. And this function extracts the right form for a given case c:

    @@ -160,7 +166,7 @@ taken care of by what are less elegantly called     return D->wording_cased[c];
     }
     
    -

    §5. So much for using declensions; now to generate them. They are inflected from +

    §5. So much for using declensions; now to generate them. They are inflected from the stem by special Preform nonterminals:

    @@ -181,7 +187,7 @@ the stem by special Preform nonterminals: return D; } -

    §5.1. If a word comes from a given file and line number in the source text, then +

    §5.1. If a word comes from a given file and line number in the source text, then we will say that so does any inflected form of it:

    @@ -194,7 +200,7 @@ we will say that so does any inflected form of it: Lexer::set_word_location(i, Lexer::word_location(Wordings::first_wn(W))); -

    §6. For the format of the table expressed by the nonterminal nt, see +

    §6. For the format of the table expressed by the nonterminal nt, see What This Module Does.

    @@ -225,7 +231,7 @@ we will say that so does any inflected form of it: return D; } -

    §6.1. Decline according to this row in declension NT6.1 = +

    §6.1. Decline according to this row in declension NT6.1 =

    @@ -243,7 +249,7 @@ we will say that so does any inflected form of it:
         if (found) return D;
     
    -

    §7. This is for the two-token form of row, gender table: +

    §7. This is for the two-token form of row, gender table:

    @@ -284,7 +290,7 @@ we will say that so does any inflected form of it:
         return D;
     }
     
    -

    §8. And this is for the three-token form of row, gender grouper table: +

    §8. And this is for the three-token form of row, gender grouper table:

    @@ -319,7 +325,7 @@ we will say that so does any inflected form of it:
         return D;
     }
     
    -

    §8.1. Set the group number8.1 = +

    §8.1. Set the group number8.1 =

    @@ -335,7 +341,7 @@ we will say that so does any inflected form of it:
         }
     
    -

    §9. We have now found the actual declension table NT; if there are \(N\) cases +

    §9. We have now found the actual declension table NT; if there are \(N\) cases in the language, there will be \(2N\) productions in this table, each of which consists of a single word giving the rewriting instruction to use.

    @@ -375,7 +381,7 @@ consists of a single word giving the rewriting instruction to use. return D; } -

    §10. Where, finally: +

    §10. Where, finally:

    diff --git a/docs/inflections-module/3-lc.html b/docs/inflections-module/3-lc.html
    index cae5d6522..fc3f8464a 100644
    --- a/docs/inflections-module/3-lc.html
    +++ b/docs/inflections-module/3-lc.html
    @@ -54,7 +54,11 @@ MathJax = {
     
  • supervisor
  • Inform7 Modules

    Services

    @@ -82,7 +88,7 @@ MathJax = {
    -

    §1. Constants. First, we support three genders: +

    §1. Constants. First, we support three genders:

    define NO_KNOWN_GENDERS 3
    @@ -90,7 +96,7 @@ MathJax = {
     define MASCULINE_GENDER 2
     define FEMININE_GENDER 3
     
    -

    §2. There are six "persons". The sequence corresponds to the defined constants +

    §2. There are six "persons". The sequence corresponds to the defined constants in the English Language extension, which we assume will be followed by other languages.

    @@ -100,28 +106,28 @@ languages. define SECOND_PERSON 1 define THIRD_PERSON 2
    -

    §3. And two numbers: +

    §3. And two numbers:

    define NO_KNOWN_NUMBERS 2
     define SINGULAR_NUMBER 0
     define PLURAL_NUMBER 1
     
    -

    §4. And two voices: +

    §4. And two voices:

    define NO_KNOWN_VOICES 2
     define ACTIVE_VOICE 0
     define PASSIVE_VOICE 1
     
    -

    §5. And two senses: +

    §5. And two senses:

    define NO_KNOWN_SENSES 2
     define POSITIVE_SENSE 0
     define NEGATIVE_SENSE 1
     
    -

    §6. 25 cases sounds like plenty, but some languages are pretty scary this +

    §6. 25 cases sounds like plenty, but some languages are pretty scary this way: Hungarian has 18. We only require two cases to exist, the nominative and accusative, which are required to be cases 0 and 1.

    @@ -130,7 +136,7 @@ and accusative, which are required to be cases 0 and 1. define NOMINATIVE_CASE 0 define ACCUSATIVE_CASE 1 -

    §7. There are at least five tenses, the first four of which are used by Inform +

    §7. There are at least five tenses, the first four of which are used by Inform in English. Some languages can use optional extras; French, for example, uses tense 5 for the past historic.

    @@ -144,7 +150,7 @@ tense 5 for the past historic. define CUSTOM1_TENSE 5 define CUSTOM2_TENSE 6 -

    §8. Packed references. The following enables even a 32-bit integer to hold an ID reference in the +

    §8. Packed references. The following enables even a 32-bit integer to hold an ID reference in the range 0 to 128K, together with any combination of gender, person, number, voice, case, tense, and sense. This could be optimised further, exploiting for example that no grammatical concept ever simultaneously has voice and @@ -161,7 +167,7 @@ values, and at present Preform return values are define lcon_ti int -

    §9. And here's how we pack everything in: +

    §9. And here's how we pack everything in:

    @@ -268,7 +274,7 @@ values, and at present Preform return values are     }
     }
     
    -

    §10.

    +

    §10.

     int Lcon::same_but_for_gender(lcon_ti A, lcon_ti B) {
    @@ -306,7 +312,7 @@ values, and at present Preform return values are     return FALSE;
     }
     
    -

    §11. Axes. We can think of a combination of the seven grammatical attributes above as +

    §11. Axes. We can think of a combination of the seven grammatical attributes above as being like a position in seven-dimensional space, with each being a coordinate on one of these sevem axes.

    @@ -325,7 +331,7 @@ sum of these can represent a set of things we're interested in: define TENSE_LCW 32 define SENSE_LCW 64 -

    §12. And desiderata in the following function is exactly that sort of set. +

    §12. And desiderata in the following function is exactly that sort of set.

    @@ -337,7 +343,7 @@ sum of these can represent a set of things we're interested in:
             }
     }
     
    -

    §13. The parameter axis in the following must, on the other hand, be a pure power +

    §13. The parameter axis in the following must, on the other hand, be a pure power of 2, that is, it must be a single *_LCW value.

    @@ -383,7 +389,7 @@ of 2, that is, it must be a single return 0; } -

    §14. Writing sets. Suppose we have a list of lcon_ti constants and want to print out their +

    §14. Writing sets. Suppose we have a list of lcon_ti constants and want to print out their grammatical attributes. If we do that in the obvious way, by calling Lcon::write on each of the constants in turn, we tend to get a list of tiresome length. We want to abbreviate so that, e.g., @@ -408,7 +414,7 @@ code is really only needed for printing tidy debugging and test logs, so it's probably not worth any further effort.

    -

    §15. To avoid the C extension for variable-length arrays, and to avoid memory +

    §15. To avoid the C extension for variable-length arrays, and to avoid memory allocation, we're simply going to make our working arrays quite large. But this is fine — the function is for printing, so it's not used much.

    @@ -417,7 +423,7 @@ this is fine — the function is for printing, so it's not used much. NO_KNOWN_GENDERS*NO_KNOWN_PERSONS*NO_KNOWN_NUMBERS*NO_KNOWN_VOICES* NO_KNOWN_SENSES*MAX_GRAMMATICAL_CASES*NO_KNOWN_TENSES -

    §16. We are going to aggregate items in the list into numbered cuboids. The +

    §16. We are going to aggregate items in the list into numbered cuboids. The strategy is simple: start with the first item; make the largest-volume cuboid inside our set which contains that item; then take the next item not already included, and continue. @@ -434,7 +440,7 @@ included, and continue. } } -

    §16.1. Note that there is always at least one cuboid containing the item \(i\) — +

    §16.1. Note that there is always at least one cuboid containing the item \(i\) — the \(1\times 1\times 1\times 1\times 1\times 1\times 1\) cuboid containing just that one point. So the following certainly finds something. The elongated_sides value accumulates the set of axis directions in which @@ -452,7 +458,7 @@ the cuboid is longer than 1. Write the resulting cuboid out16.1.2;

    -

    §16.1.1. So now we are at item \(i\). We repeatedly do the following: try to expand +

    §16.1.1. So now we are at item \(i\). We repeatedly do the following: try to expand the cuboid into each of the seven axis directions, then choose the one which expands it the most. We stop when no further expansion is possible.

    @@ -480,7 +486,7 @@ which expands it the most. We stop when no further expansion is possible. } while (max_elongation > 0); -

    §16.1.1.1. We start with the current cuboid. The enlarged array will be the same as +

    §16.1.1.1. We start with the current cuboid. The enlarged array will be the same as the cuboid_number array except that some additional points x for which cuboid_number[x] is \(-1\) — i.e., points not yet placed in any cuboid — will have enlarged[x] set to cuboid — i.e., will be placed in the current @@ -504,7 +510,7 @@ coordinates are the same as those for \(i\). if (allow == FALSE) elongation = 0;

    -

    §16.1.1.1.1. For example, if \(i = (2, 1, 0, 0, 0, 0, 0)\) and \(d\) is the second axis, then +

    §16.1.1.1.1. For example, if \(i = (2, 1, 0, 0, 0, 0, 0)\) and \(d\) is the second axis, then one variation would be 1 (the \(d\) coordinate of \(i\) itself) and if, say, \((2, 7, 0, 0, 0, 0, 0)\) were an unplaced point then 7 would also be a variation.

    @@ -521,7 +527,7 @@ one variation would be 1 (the \(d\) coordinate of \(i\) itself) and if, say, } -

    §16.1.1.1.2. Now suppose our variation set is indeed \(\lbrace 1, 7\rbrace\), as in the +

    §16.1.1.1.2. Now suppose our variation set is indeed \(\lbrace 1, 7\rbrace\), as in the above example. The idea is that we will use this set as the new side for the cuboid. We know that we can vary \(i\) by these values; that's how they were found. But we must also check that we can vary every other point currently @@ -550,7 +556,7 @@ in the cuboid in the same way. If we can't, the attempt fails. }

    -

    §16.1.2. And finally, but also not quite trivially, printing out the cuboid. We +

    §16.1.2. And finally, but also not quite trivially, printing out the cuboid. We handle the elongated sides differently from the unelongated ones, which are relegated to the Lcon::write call at the end. Note that this prints nothing if remainder is zero. diff --git a/docs/inflections-module/3-lc2.html b/docs/inflections-module/3-lc2.html index 9b46d6152..c767f375c 100644 --- a/docs/inflections-module/3-lc2.html +++ b/docs/inflections-module/3-lc2.html @@ -40,7 +40,11 @@ function togglePopup(material_id) {

  • supervisor
  • Inform7 Modules

    Services

    @@ -68,7 +74,7 @@ function togglePopup(material_id) {
    -

    §1. Cluster. A cluster is a linked list of declensions, annotated with lingistic roles. For +

    §1. Cluster. A cluster is a linked list of declensions, annotated with lingistic roles. For example, the cluster of forms for the common noun "man" might be:

    @@ -99,7 +105,7 @@ which it would be fairly easy to convert our }
    individual_form; -

    §2. A cluster begins empty. +

    §2. A cluster begins empty.

    @@ -109,7 +115,7 @@ which it would be fairly easy to convert our     return forms;
     }
     
    -

    §3. The following can add either a single form, or a form and its plural(s): +

    §3. The following can add either a single form, or a form and its plural(s):

    @@ -131,7 +137,7 @@ which it would be fairly easy to convert our     return L;
     }
     
    -

    §3.1. The following makes all possible plurals and registers those too. (Note +

    §3.1. The following makes all possible plurals and registers those too. (Note that every instance gets a plural form: even something palpably unique, like "the Koh-i-Noor diamond".) The plural dictionary supports multiple plurals, so there may be any number of forms registered: for instance, the kind @@ -156,7 +162,7 @@ so there may be any number of forms registered: for instance, the kind } while (pde);

    -

    §4. The following is more suited to adjectives, or to words which are used +

    §4. The following is more suited to adjectives, or to words which are used adjectivally, such as past participles in French. This time we generate all possible gender and number agreements.

    @@ -173,7 +179,7 @@ possible gender and number agreements. Generate agreement form and add to the declension4.1; } -

    §4.1. We use tries to modify the base text, which is taken to be the neuter +

    §4.1. We use tries to modify the base text, which is taken to be the neuter singular form, into the other five forms.

    @@ -211,7 +217,7 @@ singular form, into the other five forms. Clusters::add(cl, FW, nl, form_gender, form_number, FALSE); -

    §4.1.1. Not much of a pipeline, really: we start with the base case and work +

    §4.1.1. Not much of a pipeline, really: we start with the base case and work through one or two tries.

    @@ -231,7 +237,7 @@ through one or two tries. FW = WordAssemblages::to_wording(&wa); -

    §5. Plural fixing. Less elegantly, we can force the plural of a form in a cluster to a given +

    §5. Plural fixing. Less elegantly, we can force the plural of a form in a cluster to a given fixed text, overwriting it if it's already there. In practice this is done only when the built-in kinds are being given plural forms; some of these (those for kind constructors with optional wordings) have a peculiar format, @@ -250,7 +256,7 @@ and wouldn't pass through the pluralising tries intact. Clusters::add(cl, W, NULL, NEUTER_GENDER, PLURAL_NUMBER, FALSE); } -

    §6. Searching declensions. These are always quite small, so there's no need for any efficient device +

    §6. Searching declensions. These are always quite small, so there's no need for any efficient device to search them.

    @@ -269,7 +275,7 @@ or plural): return EMPTY_WORDING; } -

    §7. The following variant finds the earliest form in the language of play, +

    §7. The following variant finds the earliest form in the language of play, falling back on English if there's none registered:

    @@ -286,7 +292,7 @@ falling back on English if there's none registered: return Clusters::get_form(cl, plural_flag); } -

    §8. A more specific search, which can optionally test for number and gender. +

    §8. A more specific search, which can optionally test for number and gender.

    @@ -305,7 +311,7 @@ falling back on English if there's none registered:
         return in->declined.within_language;
     }
     
    -

    §9. All of which use: +

    §9. All of which use:

    diff --git a/docs/inflections-module/3-vc.html b/docs/inflections-module/3-vc.html
    index 39d026cf4..4dca46ecb 100644
    --- a/docs/inflections-module/3-vc.html
    +++ b/docs/inflections-module/3-vc.html
    @@ -41,7 +41,11 @@ function togglePopup(material_id) {
     
  • supervisor
  • Inform7 Modules

    Services

    @@ -69,7 +75,7 @@ function togglePopup(material_id) {
    -

    §1. We will need to turn a base form of a verb — in English, this is always the +

    §1. We will need to turn a base form of a verb — in English, this is always the infinitive — into up to 123 variants; we manage this with quite an extensive data structure. There will typically only be a few dozen fully conjugated verbs in any source text, though, so the memory cost isn't too extreme. For @@ -104,7 +110,7 @@ English it looks wasteful, since so many forms are the same, but for French } verb_tabulation;

    -

    §2. Finding. Most of the time, conjugations can be identified by their infinitives: +

    §2. Finding. Most of the time, conjugations can be identified by their infinitives:

    @@ -116,7 +122,7 @@ English it looks wasteful, since so many forms are the same, but for French
         return NULL;
     }
     
    -

    §3. But in fact multiple conjugations can be given with the same infinitive... +

    §3. But in fact multiple conjugations can be given with the same infinitive...

    @@ -129,7 +135,7 @@ English it looks wasteful, since so many forms are the same, but for French
         return NULL;
     }
     
    -

    §4. ...and those may or may not be identical, so a more detailed test is: +

    §4. ...and those may or may not be identical, so a more detailed test is:

    @@ -158,7 +164,7 @@ English it looks wasteful, since so many forms are the same, but for French
         return FALSE;
     }
     
    -

    §5. The following prints out a tidy form of a verb conjugation table: +

    §5. The following prints out a tidy form of a verb conjugation table:

    @@ -195,7 +201,7 @@ English it looks wasteful, since so many forms are the same, but for French
                 &(vc->tabulations[PASSIVE_VOICE].to_be_auxiliary));
     }
     
    -

    §6. Making conjugations. The following will make more sense if read alongside the examples in "English +

    §6. Making conjugations. The following will make more sense if read alongside the examples in "English Inflections", which explains the format in full.

    @@ -230,7 +236,7 @@ conjugation to another. Use the verb forms and the tabulation to make the conjugation6.3; } -

    §6.1. Initialise all verb forms to the base text6.1 = +

    §6.1. Initialise all verb forms to the base text6.1 =

    @@ -238,7 +244,7 @@ conjugation to another.
         for (k=0; k<=MAX_FORM_TYPES; k++) verb_forms[k] = base_text;
     
    -

    §6.2. This feature is provided so that English verb definitions can override the +

    §6.2. This feature is provided so that English verb definitions can override the usual grammatical rules, which enables us to create new irregular verbs. For example, Inform will by default make the past participle "blended" out of the verb "to blend", but a definition like @@ -266,7 +272,7 @@ anybody else try this one on.) verb_forms[k] = overrides[k];

    -

    §6.3. Use the verb forms and the tabulation to make the conjugation6.3 = +

    §6.3. Use the verb forms and the tabulation to make the conjugation6.3 =

    @@ -291,7 +297,7 @@ anybody else try this one on.)
         return vc;
     
    -

    §6.3.1. Start by blanking out all the passive and active slots6.3.1 = +

    §6.3.1. Start by blanking out all the passive and active slots6.3.1 =

    @@ -308,7 +314,7 @@ anybody else try this one on.)
                     }
     
    -

    §6.3.2. A tabulation is a sort of program laying out what to put in which slots, +

    §6.3.2. A tabulation is a sort of program laying out what to put in which slots, active or passive. Each production is a step in this program, and it consists of a "selector" followed by a "line". For example, the production:

    @@ -340,7 +346,7 @@ rest. (The selector is always just a single token.) } -

    §6.3.2.1. Apply the given tabulation line to the slots selected6.3.2.1 = +

    §6.3.2.1. Apply the given tabulation line to the slots selected6.3.2.1 =

    @@ -363,7 +369,7 @@ rest. (The selector is always just a single token.)
                     }
     
    -

    §6.3.2.1.1. Apply to the active voice6.3.2.1.1 = +

    §6.3.2.1.1. Apply to the active voice6.3.2.1.1 =

    @@ -372,7 +378,7 @@ rest. (The selector is always just a single token.)
                 &(vc->tabulations[ACTIVE_VOICE].modal_auxiliary_usage[tense][sense][p][n]));
     
    -

    §6.3.2.1.2. Apply to the passive voice6.3.2.1.2 = +

    §6.3.2.1.2. Apply to the passive voice6.3.2.1.2 =

    @@ -381,7 +387,7 @@ rest. (The selector is always just a single token.)
                 &(vc->tabulations[PASSIVE_VOICE].modal_auxiliary_usage[tense][sense][p][n]));
     
    -

    §6.3.2.1.3. The selector tells us which tense(s), sense(s) and voice(s) to apply the +

    §6.3.2.1.3. The selector tells us which tense(s), sense(s) and voice(s) to apply the line to; a3, for example, means active voice, tense 3, in both positive and negative senses.

    @@ -411,7 +417,7 @@ and negative senses. } -

    §7. This routine is really an interloper from core. It provides the run-time +

    §7. This routine is really an interloper from core. It provides the run-time values representing verbs in story files compiled by Inform.

    @@ -429,7 +435,7 @@ values representing verbs in story files compiled by Inform. vc->vc_iname = Hierarchy::make_iname_in(MODAL_CONJUGATION_FN_HL, R); } else { package_request *R = - VerbsAtRunTime::package(vc->vc_conjugates, vc->where_vc_created); + RTVerbs::package(vc->vc_conjugates, vc->where_vc_created); TEMPORARY_TEXT(ANT) WRITE_TO(ANT, "to %A", &(vc->infinitive)); Hierarchy::markup(R, VERB_NAME_HMD, ANT); @@ -441,7 +447,7 @@ values representing verbs in story files compiled by Inform. } #endif -

    §8. Follow instructions. That completes the top level of the routine, but it depended on two major +

    §8. Follow instructions. That completes the top level of the routine, but it depended on two major sub-steps: a preliminary pass called Conjugation::follow_instructions and a routine to deal with the final results called Conjugation::merge.

    @@ -474,7 +480,7 @@ participles and then chooses the tabulation return tabulation_nt; } -

    §8.1. Pattern match on the base text to decide which conjugation to use8.1 = +

    §8.1. Pattern match on the base text to decide which conjugation to use8.1 =

    @@ -493,7 +499,7 @@ participles and then chooses the tabulation     }
     
    -

    §8.1.1. Each production in this language's <verb-conjugation-instructions> grammar +

    §8.1.1. Each production in this language's <verb-conjugation-instructions> grammar consists of a (possibly empty) pattern to match, followed by the name of a nonterminal to use as the conjugation if it matches. For example, in

    @@ -540,7 +546,7 @@ infinitive" form is set to the part matched by "malformed line"); -

    §8.1.1.1. Try to match the base text against the pattern part of the production8.1.1.1 = +

    §8.1.1.1. Try to match the base text against the pattern part of the production8.1.1.1 =

    @@ -563,7 +569,7 @@ infinitive" form is set to the part matched by     }
     
    -

    §8.2. In a conjugation, productions have two possible forms: either just a single +

    §8.2. In a conjugation, productions have two possible forms: either just a single nonterminal, which usually identifies the tabulation, or a number followed by some tokens.

    @@ -604,7 +610,7 @@ tokens. } -

    §8.2.1. So here we check the more interesting case. The number identifies which +

    §8.2.1. So here we check the more interesting case. The number identifies which verb form to set, and the token which follows it provides the content. For example:

    @@ -636,7 +642,7 @@ example: } else malformed = TRUE; -

    §9. Merge verb material. Now the final main step. row points to a list of ptokens containing text, +

    §9. Merge verb material. Now the final main step. row points to a list of ptokens containing text, and we have to copy that text into a word assemblage and return it.

    @@ -683,7 +689,7 @@ a different verb's conjugation "lifting". return Conjugation::shorten_with_contractions(wa); } -

    §9.1. To take the easiest case first. If we read a word like trailing, we simply +

    §9.1. To take the easiest case first. If we read a word like trailing, we simply add it. But note that Conjugation::expand_with_endings has other tricks up its sleeve, and might expand 3+ed to "trailed".

    @@ -699,7 +705,7 @@ and might expand 3+ed< }
    • This code is used in §9.
    -

    §9.2. If we read a nonterminal name, such as <fr-vivre-present>, then this must +

    §9.2. If we read a nonterminal name, such as <fr-vivre-present>, then this must be a grammar with six productions, giving the text to use for the six different persons. We consult person and extract the relevant text. For example, if person is 3, we extract "vivons". Note that this material is itself read @@ -728,7 +734,7 @@ make use of the same fancy features we're allowing here. }

    • This code is used in §9.
    -

    §9.3. A number followed by a verb in brackets, like so: +

    §9.3. A number followed by a verb in brackets, like so:

    @@ -751,7 +757,7 @@ on the next iteration.
         }
     
    • This code is used in §9.
    -

    §9.4. And now the lift takes place. We might at this point have verb_form_to_lift +

    §9.4. And now the lift takes place. We might at this point have verb_form_to_lift set, in which case we should lift a verb form, or we might not, in which case we should lift an ordinary usage, such as third-person singular in a particular tense. A lift can optionally change tense or sense: for example, @@ -804,7 +810,7 @@ make use of the numbered verb forms if we want it to. }

    • This code is used in §9.
    -

    §9.5. A plus-plus-digit indicates auxiliary modal usage9.5 = +

    §9.5. A plus-plus-digit indicates auxiliary modal usage9.5 =

    @@ -820,7 +826,7 @@ make use of the numbered verb forms if we want it to.
         }
     
    • This code is used in §9.
    -

    §10. Whenever we read a single word, it passes through the following. A word +

    §10. Whenever we read a single word, it passes through the following. A word like "fish" will pass through unchanged; a number like "7" will convert to verb form 7 in the current verb (for example, 2 becomes the present participle); a plus sign joins two pieces together; and a tilde is a tie, @@ -857,7 +863,7 @@ joining but with a space. Thus return WordAssemblages::lit_1(ve); } -

    §11. The final step in merging verb material is to pass the result through the +

    §11. The final step in merging verb material is to pass the result through the following, which attends to contractions. (Most of the time it does nothing.) For example, suppose we have:

    @@ -923,7 +929,7 @@ we see a -' return wa; } -

    §11.1. We contract if the following word starts with a (possibly accented) vowel, +

    §11.1. We contract if the following word starts with a (possibly accented) vowel, and we construe "y" (but not "h" or "w") as a vowel.

    @@ -938,7 +944,7 @@ and we construe "y" (but not "h" or "w") as a vowel. contract_this = TRUE;
    • This code is used in §11.
    -

    §12. Parsing verb form numbers. These are easy: they're just written as arabic numbers. +

    §12. Parsing verb form numbers. These are easy: they're just written as arabic numbers.

    @@ -956,7 +962,7 @@ and we construe "y" (but not "h" or "w") as a vowel.
         return -1;
     }
     
    -

    §13. Parsing tense and sense indicators. These are a little harder: for example, t2+ or t3. +

    §13. Parsing tense and sense indicators. These are a little harder: for example, t2+ or t3.

    @@ -986,7 +992,7 @@ and we construe "y" (but not "h" or "w") as a vowel.
         return -1;
     }
     
    -

    §14. Parsing utilities.

    +

    §14. Parsing utilities.

     int Conjugation::ptoken_as_bracket(ptoken *pt) {
    @@ -998,7 +1004,7 @@ and we construe "y" (but not "h" or "w") as a vowel.
         return 0;
     }
     
    -

    §15. In the following, for example, "breveter" as ve would match "-veter" +

    §15. In the following, for example, "breveter" as ve would match "-veter" as pattern.

    @@ -1017,7 +1023,7 @@ as pattern. return FALSE; } -

    §16. Errors.

    +

    §16. Errors.

     void Conjugation::error(word_assemblage base_text, nonterminal *nt,
    @@ -1026,7 +1032,7 @@ as pattern.
         exit(1);
     }
     
    -

    §17. Testing. Similarly, the following helps translators by giving them unit tests for their +

    §17. Testing. Similarly, the following helps translators by giving them unit tests for their conjugations:

    @@ -1043,7 +1049,7 @@ conjugations: DESTROY(vc, verb_conjugation); } -

    §18. This is for testing English only; it helps with the test suite cases derived +

    §18. This is for testing English only; it helps with the test suite cases derived from our dictionary of 14,000 or so present and past participles.

    @@ -1061,7 +1067,7 @@ from our dictionary of 14,000 or so present and past participles. &(vc->infinitive), &(vc->present_participle), &(vc->past_participle)); } -

    §19. As noted above, these nonterminals have no parsing function, and are used only +

    §19. As noted above, these nonterminals have no parsing function, and are used only as markers in verb conjugations.

    diff --git a/docs/inflections-module/4-dl.html b/docs/inflections-module/4-dl.html index e38047601..5a3b86c78 100644 --- a/docs/inflections-module/4-dl.html +++ b/docs/inflections-module/4-dl.html @@ -40,7 +40,11 @@ function togglePopup(material_id) {
  • supervisor
  • Inform7 Modules

    Services

    @@ -66,7 +72,7 @@ function togglePopup(material_id) {

    To keep track of what the default natural language is.

    -

    §1. The following mechanism may become more sophisticated later. +

    §1. The following mechanism may become more sophisticated later.

    diff --git a/docs/inflections-module/4-ei.html b/docs/inflections-module/4-ei.html
    index 3f4137c30..13e9efd1f 100644
    --- a/docs/inflections-module/4-ei.html
    +++ b/docs/inflections-module/4-ei.html
    @@ -33,7 +33,11 @@
     
  • supervisor
  • Inform7 Modules

    Services

    @@ -61,7 +67,7 @@
    -

    §1. Noun inflections. The following trie looks at the start of a word, which we assume to be a +

    §1. Noun inflections. The following trie looks at the start of a word, which we assume to be a noun, and decides whether to use the indefinite article "a" or "an". This is much more complicated than simply looking for a vowel as the first letter, as people often think until they try a few cases. @@ -78,7 +84,7 @@ dictionary and the "Official Scrabble Wordlist". <en-trie-indef-c>

    -

    §2. Exceptions to the exceptions: +

    §2. Exceptions to the exceptions:

    @@ -91,7 +97,7 @@ dictionary and the "Official Scrabble Wordlist".
         uvarovite*      an            a rare emerald-green garnet, Ca3Cr2(SiO4)3
     
    -

    §3. Then the exceptions: +

    §3. Then the exceptions:

    @@ -161,7 +167,7 @@ dictionary and the "Official Scrabble Wordlist".
         uvu*            a
     
    -

    §4. And finally the basic rules: +

    §4. And finally the basic rules:

    @@ -221,7 +227,7 @@ dictionary and the "Official Scrabble Wordlist".
         yw*             an
     
    -

    §5. Plural inflections. The following takes a single word, assumes it to be a noun which meaningfully +

    §5. Plural inflections. The following takes a single word, assumes it to be a noun which meaningfully has a plural, and modifies it to the plural form. ("Golf" is a noun which doesn't sensibly have a plural; the algorithm here would return "golves".)

    @@ -267,7 +273,7 @@ of a sibilant plus "o" suffix to include an "e", so that Conway produces ... <en-trie-plural-append-s> -

    §6. See Conway's table A.2. The following nouns, mostly names of kinds of animal, +

    §6. See Conway's table A.2. The following nouns, mostly names of kinds of animal, have the same plural as singular form: for example, chamois, salmon, goldfish.

    @@ -325,7 +331,7 @@ have the same plural as singular form: for example, chamois, salmon, goldfish. pincers 0 -

    §7. We may as well pluralise pronouns while we're at it. +

    §7. We may as well pluralise pronouns while we're at it.

    @@ -354,7 +360,7 @@ have the same plural as singular form: for example, chamois, salmon, goldfish.
         oneself         oneselves
     
    -

    §8. We now reach Conway step 4. These are irregular plurals mostly coming +

    §8. We now reach Conway step 4. These are irregular plurals mostly coming from archaisms.

    @@ -375,7 +381,7 @@ from archaisms. trilby trilbys -

    §9. Step 5. Now we reach a batch of irregular but fairly general inflected +

    §9. Step 5. Now we reach a batch of irregular but fairly general inflected endings; for example, protozoon to protozoa, or metamorphosis to metamorphoses. Note that we differ from Conway in pluralizing blouse as blouses, not blice.

    @@ -395,7 +401,7 @@ Note that we differ from Conway in pluralizing blouse as blouses, not blice. *xis 3xes -

    §10. Step 6. These are inflections from Latin and Greek which have survived +

    §10. Step 6. These are inflections from Latin and Greek which have survived into modern English:

    @@ -427,7 +433,7 @@ into modern English: ovum ova -

    §11. Step 11a. (We're not implementing Conway's steps in sequence: see below.) +

    §11. Step 11a. (We're not implementing Conway's steps in sequence: see below.) These -o endings are mostly loan words from Romance languages whose original inflections are assimilated.

    @@ -468,7 +474,7 @@ inflections are assimilated. tempo tempos -

    §12. Conway steps 8 to 11. These are regular inflections depending only on +

    §12. Conway steps 8 to 11. These are regular inflections depending only on word endings.

    @@ -554,7 +560,7 @@ word endings. *zo 0s -

    §13. Lastly, the fallback if none of the above cases match: append an -s, of +

    §13. Lastly, the fallback if none of the above cases match: append an -s, of course.

    @@ -563,7 +569,7 @@ course. * 0s Step 13 -

    §14. Verb inflections. "Le verbe est l'âme d'une langue" (attributed to Georges Duhamel). And the +

    §14. Verb inflections. "Le verbe est l'âme d'une langue" (attributed to Georges Duhamel). And the care of the soul is, of course, complicated. For example, the source text can say something like this:

    @@ -599,7 +605,7 @@ of the possibilities we need to make, and write a trie to handle each one. is, how the different word forms map onto the possible tenses, persons, numbers, and so on. -

    §15. This gives us a certain amount of choice. What exactly is "too irregular"? +

    §15. This gives us a certain amount of choice. What exactly is "too irregular"? In French, are all -er, -ir, and -re verbs "regular"? (Consider "aller", for example.) In English, it's possible to say that there are seven or so classes of verbs, all regular by their own standards; but most people say @@ -634,7 +640,7 @@ example, to set has just three distinct forms — to set, he sets, he set, h had set, setting.

    -

    §16. Form types are numbered from 0 up to, potentially, a constant +

    §16. Form types are numbered from 0 up to, potentially, a constant called MAX_FORM_TYPES. (This is so large that there shouldn't ever be need for more.) Form type 0 is always the original text, and is used as the basis from which the others are generated. For English verbs Inform always sets form @@ -661,7 +667,7 @@ each language. English needs two: the present (5) and past (6) forms. define ADJOINT_INFINITIVE_FORM_TYPE 4 define MAX_FORM_TYPES 123 -

    §17. We're now ready to write the <verb-conjugation-instructions>. This is +

    §17. We're now ready to write the <verb-conjugation-instructions>. This is a block which looks at the infinitive of the verb and decides which of several conjugations should be used. Badly irregular verbs get conjugations of their own, and others are grouped together. In French, @@ -687,7 +693,7 @@ least one line, and the best way to ensure that is to finish up with -

    §18. The instructions for English are quite concise, except for the presence +

    §18. The instructions for English are quite concise, except for the presence of the awkward contracted informal forms of verbs. (These aren't used in Inform assertion sentences, but are needed for text substitutions.)

    @@ -721,7 +727,7 @@ Inform assertion sentences, but are needed for text substitutions.) ... <regular-verb-conjugation> -

    §19. We will start with two auxiliary verbs, that is, verbs used to construct +

    §19. We will start with two auxiliary verbs, that is, verbs used to construct forms of other verbs. The first is "to have"; as we'll see, English uses this to construct perfect tenses:

    @@ -784,7 +790,7 @@ for "[have]". <to-have-tabulation> -

    §20. Tabulations give instructions for how to construct 120 possible versions +

    §20. Tabulations give instructions for how to construct 120 possible versions of the verb. These are divided up first into active and passive "voices":

    @@ -923,7 +929,7 @@ are used for the six persons. a2- had not -

    §21. And this is an example of splitting into cases for the six persons, +

    §21. And this is an example of splitting into cases for the six persons, 1PS, 2PS, 3PS, 1PP, 2PP, 3PP. I have, you have, he has, we have, you have, they have. (This is more excitingly varied in other languages, of course.)

    @@ -933,7 +939,7 @@ they have. (This is more excitingly varied in other languages, of course.) have | have | has | have | have | have -

    §22. Next we have "to do", which is like "to have" in being fairly regular, +

    §22. Next we have "to do", which is like "to have" in being fairly regular, as irregular verbs go. But we treat this as a special case because, again, we're going to need as an auxiliary verb when forming negatives ("Peter does not wear the hat" — note the "does not"). But this time we give @@ -999,7 +1005,7 @@ may have to revisit this for languages other than English.) do | do | does | do | do | do

    -

    §23. Regular English verbs, then, look like so. We will, for the first time, +

    §23. Regular English verbs, then, look like so. We will, for the first time, make heavy use of our numbered verb forms: for example, for the verb "to take", they would be "take" (1), "taking" (2), "taken" (3), "takes" (5) and "took" (6). We start with the infinitive ("take") @@ -1031,7 +1037,7 @@ to "grabs onto", "grabbing onto" and so on. <regular-verb-tabulation>

    -

    §24. Here we see our auxiliary verbs in use. For the negated present tense, +

    §24. Here we see our auxiliary verbs in use. For the negated present tense, "Peter does not carry the ball"; for the negated past tense, "Peter did not carry the ball" — in both cases, this is "to do" plus the infinitive "take". For the perfect tenses, "to have" plus the past participle — @@ -1055,7 +1061,7 @@ a bequest".) p* 3 by

    -

    §25. This looks odd, but what it says is that the present tense of a regular +

    §25. This looks odd, but what it says is that the present tense of a regular English verb is always the infinitive (I take, you take, we take, and so on) except for third person singular (he takes), which is different. (It's usually what the plural of the infinitive would be if the infinitive were a noun, @@ -1067,7 +1073,7 @@ as we'll see.) 1 | 1 | 5 | 1 | 1 | 1

    -

    §26. Now for our most irregular verb: "to be". +

    §26. Now for our most irregular verb: "to be".

    @@ -1093,7 +1099,7 @@ as we'll see.)
         was | were | was | were | were | were
     
    -

    §27. Except for tense formation (Peter "will" take the ball), the most common +

    §27. Except for tense formation (Peter "will" take the ball), the most common modal verb which can be used in Inform source text is "can". For example:

    @@ -1132,7 +1138,7 @@ to elide, so we always pronounce it that way and the spelling now follows. a5- will not be able to ++1 -

    §28. Inform has only a simple understanding of what "can" means, so it doesn't +

    §28. Inform has only a simple understanding of what "can" means, so it doesn't allow the source text to use "can" in combination with arbitrary verbs. Instead, each legal combination has to be declared explicitly:

    @@ -1175,7 +1181,7 @@ Jane". p ( be able to ) be 3 ( 4 ) by -

    §29. The following handles the other English modal verbs ("might", "should" +

    §29. The following handles the other English modal verbs ("might", "should" and so on) surprisingly easily. The notation ++1 means that the verb being modified should appear in verb form 1, and so on: for example, "might not lead" as "might not" plus form 1 of "to lead", i.e., "lead". @@ -1200,7 +1206,7 @@ being modified should appear in verb form 1, and so on: for example, a5- 4 not ++1

    -

    §30. That completes our basic kit of verbs nicely. What's left is used only +

    §30. That completes our basic kit of verbs nicely. What's left is used only for generating text at run-time — for printing adaptive messages, that is; none of these oddball exceptional cases is otherwise used as a verb in Inform source text. None of them has any meaning to Inform. @@ -1262,7 +1268,7 @@ dialects — and we aren't even going to try to cope with that. wasn't | weren't | wasn't | weren't | weren't | weren't

    -

    §31. And now "to 've", the contracted form of "to have". A subtle dialect +

    §31. And now "to 've", the contracted form of "to have". A subtle dialect point here concerns the negated present tense:

    @@ -1313,7 +1319,7 @@ go with those. 've | 've | 's | 've | 've | 've -

    §32. Now we come to "aren't", a negated form of "to be", but where the +

    §32. Now we come to "aren't", a negated form of "to be", but where the contraction occurs between the verb and the "not" rather than between the subject and the verb.

    @@ -1351,7 +1357,7 @@ that option here.) haven't been | haven't been | hasn't been | haven't been | haven't been | haven't been -

    §33. And finally: the contracted informal negatives of various modal verbs which +

    §33. And finally: the contracted informal negatives of various modal verbs which it's useful to be able to print, like the "can't" in

    @@ -1384,7 +1390,7 @@ of "modal" itself arguable. This is the best we can do. 1 | 1 | 7 | 1 | 1 | 1 -

    §34. Together with special rules for can't, which is inevitably slightly different: +

    §34. Together with special rules for can't, which is inevitably slightly different:

    @@ -1402,7 +1408,7 @@ of "modal" itself arguable. This is the best we can do.
         a5+        won't be able to ++1
     
    -

    §35. We have special tries just to list the forms of the cases we will +

    §35. We have special tries just to list the forms of the cases we will deal with. Tries can do fancy things (see below), but here they act just as a look-up table: for example, "won't" has present "won't", past "wouldn't" and future "won't". @@ -1450,7 +1456,7 @@ signs can be used if we absolutely have to introduce spaces. shouldn't shouldn't

    -

    §36. That's the end of the conjugations — the easy part, it turns out. We now +

    §36. That's the end of the conjugations — the easy part, it turns out. We now need to create the four tries to make verb forms out of the infinitive: the present participle, the past participle, the third-person singular present tense, and the past tense. @@ -1493,7 +1499,7 @@ no easy way to tell. Consider deter to deterring (stress on second syllable of deter), but meter to metering (stress on first syllable of meter).

    -

    §37. The following algorithm is due to Toby Nelson, who produced it from a +

    §37. The following algorithm is due to Toby Nelson, who produced it from a dictionary of 14,689 English verbs, some of them quite obscure (to torpefy, anyone? to spuilzie? to cachinnate?). It's essentially a more detailed version of Greenbaum's rules above. @@ -1508,7 +1514,7 @@ version of Greenbaum's rules above. ... <en-trie-regular-c-present-participle>

    -

    §38. First of all there are some irregular cases — some for the usual suspects, +

    §38. First of all there are some irregular cases — some for the usual suspects, but others for oddball verbs where English breaks the normal phonetic rules for the sake of clarity. For example, the participle of "singe" ought to be "singing", but in fact we write "singeing", purely to make it different @@ -1704,7 +1710,7 @@ from the act of producing a song. undersaye 1ing

    -

    §39. Now some exceptional forms where consonant doubling doesn't occur: +

    §39. Now some exceptional forms where consonant doubling doesn't occur:

    @@ -1725,7 +1731,7 @@ from the act of producing a song.
         *daub       0ing        daubing, bedaubing
     
    -

    §40. And now rules for consonant doubling: +

    §40. And now rules for consonant doubling:

    @@ -1777,7 +1783,7 @@ from the act of producing a song.
         *iz                    0zing
     
    -

    §41. Finally: +

    §41. Finally:

    @@ -1791,7 +1797,7 @@ from the act of producing a song.
         *            0ing
     
    -

    §42. Next the past participle. As noted above, for most verbs this is the same +

    §42. Next the past participle. As noted above, for most verbs this is the same as the past (e.g., he agreed and it was agreed); but there's a list of exceptions for Anglo-Saxon survivals (e.g., he chose and it was chosen). The exceptional cases were derived from Wikipedia's catalogue of irregular @@ -1958,7 +1964,7 @@ removed. write written

    -

    §43. That's the mandatory participles sorted out; so now we move on to the two +

    §43. That's the mandatory participles sorted out; so now we move on to the two additional verb forms used by English. First, the present form: a curiosity of English is that this is almost always formed as if it were the plural of the infinitive — thus "touch" becomes "touches". There are just a handful @@ -1976,7 +1982,7 @@ of exceptions to this. do does

    -

    §44. Second, the past. This is harder. Once again we have a catalogue of +

    §44. Second, the past. This is harder. Once again we have a catalogue of Anglo-Saxon past forms (e.g., he chose, not he chooses); and after those are out of the way, the rules are the same as for the present participle, except for adding -ed instead of -ing. The tricky part, again, is spotting @@ -2609,7 +2615,7 @@ when to double the consonant, which again depends on stress. * 0ed

    -

    §45. Present to past participles. Sentences like +

    §45. Present to past participles. Sentences like

    @@ -3118,7 +3124,7 @@ cases followed by two general rules. *ing 3ed e.g., "smashing" to "smashed" -

    §46. Adjective agreements. English doesn't inflect adjectives at all (let's not argue about "blond" +

    §46. Adjective agreements. English doesn't inflect adjectives at all (let's not argue about "blond" and "blonde"), so the following are just stubs.

    @@ -3139,7 +3145,7 @@ and "blonde"), so the following are just stubs. * 0 -

    §47. Grading of adjectives is more interesting. These spelling rules are taken +

    §47. Grading of adjectives is more interesting. These spelling rules are taken from the Oxford English Grammar at 4.24, "Gradability and comparison". Something we can't easily implement is that a final vowel plus consonant doesn't result in doubling the consonant (in the way that "big" becomes @@ -3171,7 +3177,7 @@ rare in English adjectives. * 0est

    -

    §48. To the best of my knowledge there's no technical term for "the noun which +

    §48. To the best of my knowledge there's no technical term for "the noun which is formed from an adjective to refer to the quality it measures", so the Inform source code calls this the "quiddity". English permits several competing forms of these to be constructed, depending on the adjective's @@ -3191,7 +3197,7 @@ sometimes less elegant, but never means the wrong thing. * 0ness

    -

    §49. English has almost no noun cases at all, with the only exceptions being +

    §49. English has almost no noun cases at all, with the only exceptions being Anglo-Saxon pronouns (thus we distinguish "they" and "them" as nominative and accusative, for example); and pronouns we handle separately in any case. We won't bother to distinguish gender: @@ -3205,7 +3211,7 @@ case. We won't bother to distinguish gender: * <en-noun-declension-group> <en-noun-declension-tables>

    -

    §50. And the sorting into groups sorts everything into "group 1", the only group: +

    §50. And the sorting into groups sorts everything into "group 1", the only group:

    @@ -3216,7 +3222,7 @@ case. We won't bother to distinguish gender:
         <en-noun-declension-uninflected>
     
    -

    §51. And in this single group, nominative and accusative forms are identical +

    §51. And in this single group, nominative and accusative forms are identical to the stem in both singular and plural.

    @@ -3226,7 +3232,7 @@ to the stem in both singular and plural. 0 | 0 -

    §52. English articles only inflect slightly, to show indefinite plurals; they +

    §52. English articles only inflect slightly, to show indefinite plurals; they don't distinguish nominative from accusative.

    diff --git a/docs/inflections-module/P-htitm.html b/docs/inflections-module/P-htitm.html index 89d4475c1..39838035f 100644 --- a/docs/inflections-module/P-htitm.html +++ b/docs/inflections-module/P-htitm.html @@ -32,7 +32,11 @@
  • supervisor
  • Inform7 Modules

    Services

    @@ -60,7 +66,7 @@
    -

    §1. Status. The inflections module is provided as one of the "services" suite of modules, +

    §1. Status. The inflections module is provided as one of the "services" suite of modules, which means that it was built with a view to potential incorporation in multiple tools. It can be found, for example, in inform7 and inflections-test. @@ -74,7 +80,7 @@ other modules except for words and syntax.

    -

    §2. Importing the module. We'll use the term "parent" to mean the tool which is importing inflections, +

    §2. Importing the module. We'll use the term "parent" to mean the tool which is importing inflections, that is, which will include its code and be able to use it. As with any imported module,

    @@ -89,7 +95,7 @@ module: InflectionsModule::end() just before it shuts down. (But just after, and just before, the corresponding calls to foundation.) -

    §3. This module has no callback functions to modify its behaviour. +

    §3. This module has no callback functions to modify its behaviour.