diff --git a/docs/if-module/5-pv.html b/docs/if-module/5-pv.html new file mode 100644 index 000000000..39889c888 --- /dev/null +++ b/docs/if-module/5-pv.html @@ -0,0 +1,211 @@ + + + + Property Visibility + + + + + + + + + + + + + + + + + + +
+ + +

Some properties can be referred to in the player's commands.

+ +

§1. "Visible" properties can be used to describe an object: for example, if +colour is a visible property of a car, then an individual instance of K_car +can be referred to by the player as GREEN CAR if and only if that instance has +the colour value "green". +

+ +

Properly speaking it is not the property itself which is visible, but the +combination of property and its owner. So we record visibility by attaching +the following blob of data to a property_permission: +

+ +
define NO_VISIBILITY_LEVEL 0
+define REFERRING_TO_VISIBILITY_LEVEL 1
+define DESCRIBING_VISIBILITY_LEVEL 2
+
+
+typedef struct parsing_pp_data {
+    int visibility_level_in_parser;  one of the *_VISIBILITY_LEVEL values above
+    struct wording visibility_condition;  (at least if...?)
+    struct parse_node *visibility_sentence;  where this is specified
+    CLASS_DEFINITION
+} parsing_pp_data;
+
+parsing_pp_data *Visibility::new_pp_data(property_permission *pp) {
+    parsing_pp_data *pd = CREATE(parsing_pp_data);
+    pd->visibility_level_in_parser = NO_VISIBILITY_LEVEL;
+    pd->visibility_condition = EMPTY_WORDING;
+    pd->visibility_sentence = NULL;
+    return pd;
+}
+
+int Visibility::new_permission_notify(property_permission *new_pp) {
+    CREATE_PLUGIN_PP_DATA(parsing, new_pp, Visibility::new_pp_data);
+    return FALSE;
+}
+
+ +

§2. The following function sets the visibility level and condition for a given +property and owner, returning FALSE if the owner cannot in fact have that +property. There's a little dance here because perhaps we want to set visibility +for "open" when its negation "closed" has the permission, or vice versa. +

+ +
+int Visibility::set(property *pr, inference_subject *subj, int level, wording WHENW) {
+    int upto = 1;
+    if (Properties::is_either_or(pr) == FALSE) upto = 0;
+    for (int parity = 0; parity <= upto; parity++) {
+        property *seek_prn = (parity == 0)?pr:(EitherOrProperties::get_negation(pr));
+        if ((seek_prn) && (PropertyPermissions::find(subj, seek_prn, TRUE))) {
+            property_permission *pp = PropertyPermissions::grant(subj, seek_prn, FALSE);
+            PP_PLUGIN_DATA(parsing, pp)->visibility_level_in_parser = level;
+            PP_PLUGIN_DATA(parsing, pp)->visibility_condition = WHENW;
+            PP_PLUGIN_DATA(parsing, pp)->visibility_sentence = current_sentence;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+

§3. Does the property owner subj have any visible properties? +

+ +
+int Visibility::any_property_visible_to_subject(inference_subject *subj,
+    int allow_inheritance) {
+    property *pr;
+    LOOP_OVER(pr, property) {
+        property_permission *pp = PropertyPermissions::find(subj, pr, allow_inheritance);
+        if ((pp) && (PP_PLUGIN_DATA(parsing, pp)->visibility_level_in_parser > 0))
+            return TRUE;
+    }
+    return FALSE;
+}
+
+

§4. For what these levels actually mean, see the code for the run-time command parser +at Parser (in CommandParserKit). +

+ +
+int Visibility::get_level(property_permission *pp) {
+    return PP_PLUGIN_DATA(parsing, pp)->visibility_level_in_parser;
+}
+
+

§5. The condition text, if supplied, says that the property is only visible +if some condition holds. +

+ +

For timing reasons, we don't parse this when it is first declared, but only +when we need it, which is now: +

+ +
+parse_node *Visibility::get_condition(property_permission *pp) {
+    wording W = PP_PLUGIN_DATA(parsing, pp)->visibility_condition;
+    if (Wordings::empty(W)) return NULL;
+    parse_node *spec = NULL;
+    if (<s-condition>(W)) spec = <<rp>>;
+    else spec = Specifications::new_UNKNOWN(W);
+    if (Dash::validate_conditional_clause(spec) == FALSE) {
+        current_sentence = PP_PLUGIN_DATA(parsing, pp)->visibility_sentence;
+        StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_BadVisibilityWhen),
+            "the condition after 'when' makes no sense to me",
+            "although otherwise this worked - it is only the part after 'when' "
+            "which I can't follow.");
+        PP_PLUGIN_DATA(parsing, pp)->visibility_condition = EMPTY_WORDING;
+        return NULL;
+    }
+    return spec;
+}
+
+

§6. Though currently unused, this function may be useful for debugging: +

+ +
+void Visibility::log_parsing_visibility(inference_subject *infs) {
+    LOG("Permissions for $j:\n", infs);
+    property_permission *pp = NULL;
+    LOOP_OVER_PERMISSIONS_FOR_INFS(pp, infs) {
+        LOG("$Y: visibility %d, condition %W\n",
+            PropertyPermissions::get_property(pp),
+            PP_PLUGIN_DATA(parsing, pp)->visibility_level_in_parser,
+            PP_PLUGIN_DATA(parsing, pp)->visibility_condition);
+    }
+    if (InferenceSubjects::narrowest_broader_subject(infs))
+        Visibility::log_parsing_visibility(
+            InferenceSubjects::narrowest_broader_subject(infs));
+}
+
+ + +
+ + + diff --git a/docs/runtime-module/5-gpr.html b/docs/runtime-module/5-gpr.html new file mode 100644 index 000000000..976b7455b --- /dev/null +++ b/docs/runtime-module/5-gpr.html @@ -0,0 +1,1335 @@ + + + + General Parsing Routines + + + + + + + + + + + + + + + + + + +
+ + +

To compile I6 general parsing routines (GPRs) and/or |parse_name| properties as required by the I7 grammar.

+ +
+ +

§1. Definitions.

+ +
+typedef struct parse_name_notice {
+    struct inter_name *pnn_iname;
+    struct inference_subject *parse_subject;
+    CLASS_DEFINITION
+} parse_name_notice;
+
+ +

§2. In this section we compile GPRs, routines to handle Consult-like text, +and also parse_name routines, which as we shall see come in two different +forms. These routines share a basic protocol for dealing with the I6 +library, which makes things considerably easier. In each case, the +routine is compiled as a head and then, subsequently, a tail: the user +of the routines is expected to compile the actual grammar in between +the two. Every head must be followed by exactly one tail of the same +sort; every tail must be preceded by exactly one head of the same sort; +but code to parse at wn may be placed in between. +

+ +

The GPRs compiled to parse literal values of given kinds of values +(for instance, exotic verbal forms of numbers, or verbal names of +the constants for new kinds of value, or literal patterns) are not +compiled here: they are in Tokens Parsing Values. +

+ +

§3. Consult routines. These are used to parse an explicit range of words (such as traditionally +found in the CONSULT command) at run time, and they are not I6 grammar +tokens, and do not appear in Verb declarations: otherwise, such +routines are very similar to GPRs. +

+ +

First, we need to look after a pointer to the CG used to hold the grammar +being matched against the snippet of words. +

+ +
+inter_name *UnderstandGeneralTokens::consult_iname(command_grammar *cg) {
+    if (cg == NULL) return NULL;
+    if (cg->compilation_data.cg_consult_iname == NULL) {
+        current_sentence = cg->where_cg_created;
+        package_request *PR = Hierarchy::local_package(CONSULT_TOKENS_HAP);
+        cg->compilation_data.cg_consult_iname = Hierarchy::make_iname_in(CONSULT_FN_HL, PR);
+    }
+    return cg->compilation_data.cg_consult_iname;
+}
+
+

§4. Parse name properties. One of the major services provided by I7, as compared with I6, is that it +automatically compiles what would otherwise be laborious parse_name +routines for its objects. This is messy, because the underlying I6 syntax +is messy. The significant complication is that the I6 parser makes two +quite different uses of parse_name: not just for parsing names, but +also for determining whether two objects are visually distinguishable, +something it needs to know in order to make plural objects work properly. +

+ +

If an object has any actual grammar attached, say a collection of grammar +lines belonging to GV3, we will compile the parse_name as an independent +I6 routine with a name like Parse_Name_GV3. If not, a parse_name may +still be needed, because of the distinguishability problem: if so then we +will simply compile a parse_name routine inline, in the usual I6 way. +

+ +
+inter_name *UnderstandGeneralTokens::get_gv_parse_name(command_grammar *cg) {
+    if (cg->compilation_data.cg_parse_name_iname == NULL) {
+        compilation_unit *C = CompilationUnits::find(cg->where_cg_created);
+        package_request *PR = Hierarchy::package(C, PARSE_NAMES_HAP);
+        cg->compilation_data.cg_parse_name_iname = Hierarchy::make_iname_in(PARSE_NAME_FN_HL, PR);
+    }
+    return cg->compilation_data.cg_parse_name_iname;
+}
+
+inter_name *UnderstandGeneralTokens::compile_parse_name_property(inference_subject *subj) {
+    inter_name *symb = NULL;
+    command_grammar *cg = PARSING_DATA_FOR_SUBJ(subj)->understand_as_this_object;
+    if (CommandGrammars::is_empty(cg) == FALSE) {
+        symb = UnderstandGeneralTokens::get_gv_parse_name(cg);
+    } else {
+        if (Visibility::any_property_visible_to_subject(subj, FALSE)) {
+            parse_name_notice *notice = CREATE(parse_name_notice);
+            compilation_unit *C = CompilationUnits::find(subj->infs_created_at);
+            package_request *PR = Hierarchy::package(C, PARSE_NAMES_HAP);
+            notice->pnn_iname = Hierarchy::make_iname_in(PARSE_NAME_DASH_FN_HL, PR);
+            notice->parse_subject = subj;
+            symb = notice->pnn_iname;
+        }
+    }
+    return symb;
+}
+
+void UnderstandGeneralTokens::write_parse_name_routines(void) {
+    parse_name_notice *notice;
+    LOOP_OVER(notice, parse_name_notice) {
+        gpr_kit gprk = UnderstandValueTokens::new_kit();
+        packaging_state save = Emit::unused_packaging_state();
+        if (UnderstandGeneralTokens::compile_parse_name_head(&save, &gprk,
+            notice->parse_subject, NULL, notice->pnn_iname)) {
+            UnderstandGeneralTokens::compile_parse_name_tail(&gprk);
+            Routines::end(save);
+        }
+    }
+}
+
+

§5. The following routine produces one of three outcomes: either (i) the +head of an I6 declaration of a free-standing routine to be used as a +parse_name property, or (ii) the head of an I6 inline declaration of a +parse_name property as a with clause for an Object directive, or +

+ + +

In cases (i) and (ii), the head is immediately followed by code which +looks at the names of visible properties. Recall that a visible property +is one which can be used to describe an object: for instance, if colour +is a visible property of a car, then it can be called "green car" if +and only if the current value of the colour of the car is "green", and +so forth. In all such cases, we need to parse the text to look for the +name of the current value. +

+ +

But if a property can be used as part of the name, then it follows that +two objects with the same grammar (and name words) cease to be +indistinguishable when their values for this property differ. For instance, +given two otherwise identical cars which can only be called "car", we +can distinguish them with the names "red car" and "green car" if one +is red and the other green. The parser needs to know this. It calls the +parse_name routine with an I6 global called parser_action set to +##TheSame in such a case, and we can return 0 to make no decision or +-2 to say that they are different. +

+ +

Note that the parser checks this only if two or more objects share the same +parse_name routine: which will in I7 happen only if they each inherit it +from the I6 class of a common kind. Because parse_name is not additive in +I6, this can only occur if the objects, and any intervening classes for +intervening kinds, define no parse_name of their own. +

+ +

We will test distinguishability only for kinds which have permissions for +visible properties: kinds because no other parse_name values can ever +be duplicated in instance objects, and visible properties because these +are the only ways to tell apart instances which have no grammar of their +own. (If either had grammar of its own, it would also have its own +parse_name routine.) For all other kinds, we return a make-no-decision +value in response to a ##TheSame request: this ensures that the I6 +parser looks at the name properties of the objects instead, and in +the absence of either I7-level grammar lines or visible properties, that +will be the correct decision. +

+ +
+int UnderstandGeneralTokens::compile_parse_name_head(packaging_state *save,
+    gpr_kit *gprk, inference_subject *subj,
+    command_grammar *cg, inter_name *rname) {
+    int test_distinguishability = FALSE, sometimes_has_visible_properties = FALSE;
+    inter_name *N = NULL;
+
+    if (subj == NULL) internal_error("compiling parse_name head for null subj");
+
+    if (cg) {
+        sometimes_has_visible_properties =
+            Visibility::any_property_visible_to_subject(subj, TRUE);
+        N = UnderstandGeneralTokens::get_gv_parse_name(cg);
+    } else {
+        if (Visibility::any_property_visible_to_subject(subj, FALSE)
+            == FALSE) return FALSE;
+    }
+
+    if (KindSubjects::to_kind(subj)) test_distinguishability = TRUE;
+
+    inter_name *compile_to = rname;
+    if (compile_to == NULL) compile_to = N;
+    if (compile_to == NULL) internal_error("no parse name routine name given");
+
+    *save = Routines::begin(compile_to);
+
+    UnderstandValueTokens::add_parse_name_vars(gprk);
+
+    UnderstandGeneralTokens::top_of_head(gprk, N, subj,
+        test_distinguishability, sometimes_has_visible_properties, rname);
+    return TRUE;
+}
+
+

§6. The following multi-pass approach checks the possible patterns: +

+ + +

The longer match is taken: but note that a match of visible property names +alone is rejected unless at least one property has been declared sufficient +to identify the object all by itself. Longer grammar means grammar lines +containing 2 or more words, since all single-fixed-word grammar lines for +CGs destined to be parse_names is stripped out and converted into the +name property. +

+ +

There are clearly other possibilities and the above system is something of +a pragmatic compromise (in that to check other cases would be slower and +more complex). I suspect we will return to this. +

+ +
+void UnderstandGeneralTokens::top_of_head(gpr_kit *gprk, inter_name *cg_iname, inference_subject *subj,
+    int test_distinguishability, int sometimes_has_visible_properties, inter_name *given_name) {
+
+    Produce::inv_primitive(Emit::tree(), IFDEBUG_BIP);
+    Produce::down(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), IF_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), GE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TRACE_HL));
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 3);
+                Produce::up(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_text(Emit::tree(), I"Parse_name called\n");
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+
+    if ((cg_iname) && (sometimes_has_visible_properties == FALSE)) {
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+            Produce::down(Emit::tree());
+                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ACTION_HL));
+                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(THESAME_HL));
+            Produce::up(Emit::tree());
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 0);
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    }
+    Save word number6.1;
+
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->pass_s);
+        Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), WHILE_BIP);
+    Produce::down(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), LE_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+            Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 3);
+        Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Reset word number6.2;
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+                Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 0);
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->n_s);
+                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 0);
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), WHILE_BIP);
+            Produce::down(Emit::tree());
+                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+
+                     On pass 1 only, advance wn past name property words
+                     (but do not do this for ##TheSame, when wn is undefined)
+                    Produce::inv_primitive(Emit::tree(), IF_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), AND_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), NE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ACTION_HL));
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(THESAME_HL));
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+                                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                        Produce::code(Emit::tree());
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), WHILE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::inv_call_iname(Emit::tree(), Hierarchy::find(WORDINPROPERTY_HL));
+                                Produce::down(Emit::tree());
+                                    Produce::inv_call_iname(Emit::tree(), Hierarchy::find(NEXTWORDSTOPPED_HL));
+                                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                                    Produce::val_iname(Emit::tree(), K_value, RTParsing::name_iname());
+                                Produce::up(Emit::tree());
+                                Produce::code(Emit::tree());
+                                Produce::down(Emit::tree());
+                                    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                    Produce::down(Emit::tree());
+                                        Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+                                        Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+                                    Produce::up(Emit::tree());
+                                Produce::up(Emit::tree());
+                            Produce::up(Emit::tree());
+
+                            Produce::inv_primitive(Emit::tree(), POSTDECREMENT_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+
+                    Produce::inv_primitive(Emit::tree(), IF_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), OR_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+                                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+                                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 2);
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                        Produce::code(Emit::tree());
+                        Produce::down(Emit::tree());
+                        UnderstandGeneralTokens::consider_visible_properties(gprk, subj, test_distinguishability);
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+
+                    Produce::inv_primitive(Emit::tree(), IF_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), AND_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), NE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ACTION_HL));
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(THESAME_HL));
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+                                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                        Produce::code(Emit::tree());
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), WHILE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::inv_call_iname(Emit::tree(), Hierarchy::find(WORDINPROPERTY_HL));
+                                Produce::down(Emit::tree());
+                                    Produce::inv_call_iname(Emit::tree(), Hierarchy::find(NEXTWORDSTOPPED_HL));
+                                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                                    Produce::val_iname(Emit::tree(), K_value, RTParsing::name_iname());
+                                Produce::up(Emit::tree());
+                                Produce::code(Emit::tree());
+                                Produce::down(Emit::tree());
+                                    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                    Produce::down(Emit::tree());
+                                        Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+                                        Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+                                    Produce::up(Emit::tree());
+                                Produce::up(Emit::tree());
+                            Produce::up(Emit::tree());
+
+                            Produce::inv_primitive(Emit::tree(), POSTDECREMENT_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+}
+
+

§6.1. Save word number6.1 = +

+ +
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->original_wn_s);
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+    Produce::up(Emit::tree());
+
+ +

§6.2. Reset word number6.2 = +

+ +
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+        Produce::val_symbol(Emit::tree(), K_value, gprk->original_wn_s);
+    Produce::up(Emit::tree());
+
+ +

§7. The head and tail routines can only be understood by knowing that the +following code is used to reset the grammar-line parser after each failure +of a CGL to parse. +

+ +
+void UnderstandGeneralTokens::after_gl_failed(gpr_kit *gprk, inter_symbol *label, int pluralised) {
+    if (pluralised) {
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ACTION_HL));
+            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PLURALFOUND_HL));
+        Produce::up(Emit::tree());
+    }
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+        Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), CONTINUE_BIP);
+
+    Produce::place_label(Emit::tree(), label);
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+        Produce::val_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+    Produce::up(Emit::tree());
+}
+
+

§8. The interesting point about the tail of the parse_name routine is that +it ends on the ] "close routine" character, in mid-source line. This is +because the routine may be being used inside an Object directive, and +would therefore need to be followed by a comma, or in free-standing I6 code, +in which case it would need to be followed by a semi-colon. +

+ +
+void UnderstandGeneralTokens::compile_parse_name_tail(gpr_kit *gprk) {
+                    Produce::inv_primitive(Emit::tree(), BREAK_BIP);
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+
+            Produce::inv_primitive(Emit::tree(), WHILE_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_call_iname(Emit::tree(), Hierarchy::find(WORDINPROPERTY_HL));
+                Produce::down(Emit::tree());
+                    Produce::inv_call_iname(Emit::tree(), Hierarchy::find(NEXTWORDSTOPPED_HL));
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                    Produce::val_iname(Emit::tree(), K_value, RTParsing::name_iname());
+                Produce::up(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), POSTINCREMENT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::ref_symbol(Emit::tree(), K_value, gprk->n_s);
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+
+            Produce::inv_primitive(Emit::tree(), IF_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), OR_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val_symbol(Emit::tree(), K_value, gprk->f_s);
+                    Produce::inv_primitive(Emit::tree(), GT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+                        Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 0);
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::ref_symbol(Emit::tree(), K_value, gprk->n_s);
+                        Produce::inv_primitive(Emit::tree(), MINUS_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PLUS_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+                                Produce::val_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+                            Produce::up(Emit::tree());
+                            Produce::val_symbol(Emit::tree(), K_value, gprk->original_wn_s);
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+
+            Produce::inv_primitive(Emit::tree(), IF_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+                Produce::up(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::ref_symbol(Emit::tree(), K_value, gprk->pass1_n_s);
+                        Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), IF_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val_symbol(Emit::tree(), K_value, gprk->pass_s);
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 2);
+                Produce::up(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::ref_symbol(Emit::tree(), K_value, gprk->pass2_n_s);
+                        Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), POSTINCREMENT_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->pass_s);
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+
+    Produce::inv_primitive(Emit::tree(), IFDEBUG_BIP);
+    Produce::down(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), IF_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), GE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TRACE_HL));
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 3);
+                Produce::up(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_text(Emit::tree(), I"Pass 1: ");
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINTNUMBER_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_symbol(Emit::tree(), K_value, gprk->pass1_n_s);
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_text(Emit::tree(), I" Pass 2: ");
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINTNUMBER_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_symbol(Emit::tree(), K_value, gprk->pass2_n_s);
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_text(Emit::tree(), I" Pass 3: ");
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINTNUMBER_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_text(Emit::tree(), I"\n");
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), GT_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, gprk->pass1_n_s);
+            Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+        Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->n_s);
+                Produce::val_symbol(Emit::tree(), K_value, gprk->pass1_n_s);
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), GT_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, gprk->pass2_n_s);
+            Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+        Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->n_s);
+                Produce::val_symbol(Emit::tree(), K_value, gprk->pass2_n_s);
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+        Produce::inv_primitive(Emit::tree(), PLUS_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, gprk->original_wn_s);
+            Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+            Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 0);
+        Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+            Produce::down(Emit::tree());
+                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, (inter_ti) -1);
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+    Produce::inv_call_iname(Emit::tree(), Hierarchy::find(DETECTPLURALWORD_HL));
+    Produce::down(Emit::tree());
+        Produce::val_symbol(Emit::tree(), K_value, gprk->original_wn_s);
+        Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_symbol(Emit::tree(), K_value, gprk->n_s);
+    Produce::up(Emit::tree());
+}
+
+

§9. We generate code suitable for inclusion in a parse_name routine which +either tests distinguishability then parses, or else just parses, the +visible properties of a given subject (which may be a kind or instance). +Sometimes we allow visibility to be inherited from a permission given +to a kind, sometimes we require that the permission be given to this +specific object. +

+ +
+void UnderstandGeneralTokens::consider_visible_properties(gpr_kit *gprk, inference_subject *subj,
+    int test_distinguishability) {
+    int phase = 2;
+    if (test_distinguishability) phase = 1;
+    for (; phase<=2; phase++) {
+        property *pr;
+        UnderstandGeneralTokens::start_considering_visible_properties(gprk, phase);
+        LOOP_OVER(pr, property) {
+            if ((Properties::is_either_or(pr)) && (RTProperties::stored_in_negation(pr))) continue;
+            property_permission *pp =
+                PropertyPermissions::find(subj, pr, TRUE);
+            if ((pp) && (Visibility::get_level(pp) > 0))
+                UnderstandGeneralTokens::consider_visible_property(gprk, subj, pr, pp, phase);
+        }
+        UnderstandGeneralTokens::finish_considering_visible_properties(gprk, phase);
+    }
+}
+
+

§10. Common handling for distinguishing and parsing. The top-level considering routines parcel up work and hand it over to +the distinguishing routines if phase is 1, and the parsing routines +if phase is 2. Note that if there are no sometimes-visible-properties +then the correct behaviour is to call none of the routines below this +level, and to compile nothing to the file. +

+ +
+int visible_properties_code_written = FALSE;  persistent state used only here
+
+void UnderstandGeneralTokens::start_considering_visible_properties(gpr_kit *gprk, int phase) {
+    visible_properties_code_written = FALSE;
+}
+
+void UnderstandGeneralTokens::consider_visible_property(gpr_kit *gprk, inference_subject *subj,
+    property *pr, property_permission *pp, int phase) {
+    int conditional_vis = FALSE;
+    parse_node *spec;
+
+    if (visible_properties_code_written == FALSE) {
+        visible_properties_code_written = TRUE;
+        if (phase == 1)
+            UnderstandGeneralTokens::begin_distinguishing_visible_properties(gprk);
+        else
+            UnderstandGeneralTokens::begin_parsing_visible_properties(gprk);
+    }
+
+    spec = Visibility::get_condition(pp);
+
+    if (spec) {
+        conditional_vis = TRUE;
+        if (phase == 1)
+            UnderstandGeneralTokens::test_distinguish_visible_property(gprk, spec);
+        else
+            UnderstandGeneralTokens::test_parse_visible_property(gprk, spec);
+    }
+
+    if (phase == 1)
+        UnderstandGeneralTokens::distinguish_visible_property(gprk, pr);
+    else
+        UnderstandGeneralTokens::parse_visible_property(gprk, subj, pr, Visibility::get_level(pp));
+
+    if (conditional_vis) { Produce::up(Emit::tree()); Produce::up(Emit::tree()); }
+}
+
+void UnderstandGeneralTokens::finish_considering_visible_properties(gpr_kit *gprk, int phase) {
+    if (visible_properties_code_written) {
+        if (phase == 1)
+            UnderstandGeneralTokens::finish_distinguishing_visible_properties(gprk);
+        else
+            UnderstandGeneralTokens::finish_parsing_visible_properties(gprk);
+    }
+}
+
+

§11. Distinguishing visible properties. We distinguish two objects P1 and P2 based on the following criteria: +

+ + +
+void UnderstandGeneralTokens::begin_distinguishing_visible_properties(gpr_kit *gprk) {
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ACTION_HL));
+            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(THESAME_HL));
+        Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), IFDEBUG_BIP);
+            Produce::down(Emit::tree());
+                Produce::code(Emit::tree());
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), IF_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), GE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TRACE_HL));
+                            Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 4);
+                        Produce::up(Emit::tree());
+                        Produce::code(Emit::tree());
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_text(Emit::tree(), I"p1, p2 = ");
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PRINTNUMBER_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ONE_HL));
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_text(Emit::tree(), I", ");
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PRINTNUMBER_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TWO_HL));
+                            Produce::up(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PRINT_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_text(Emit::tree(), I"\n");
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->ss_s);
+                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+            Produce::up(Emit::tree());
+}
+
+void UnderstandGeneralTokens::test_distinguish_visible_property(gpr_kit *gprk, parse_node *spec) {
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ONE_HL));
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+        Specifications::Compiler::emit_as_val(K_truth_state, spec);
+    Produce::up(Emit::tree());
+
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TWO_HL));
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->g_s);
+        Specifications::Compiler::emit_as_val(K_truth_state, spec);
+    Produce::up(Emit::tree());
+
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), NE_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, gprk->f_s);
+            Produce::val_symbol(Emit::tree(), K_value, gprk->g_s);
+        Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Return minus two11.1;
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_symbol(Emit::tree(), K_value, gprk->f_s);
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+}
+
+void UnderstandGeneralTokens::distinguish_visible_property(gpr_kit *gprk, property *prn) {
+    TEMPORARY_TEXT(C)
+    WRITE_TO(C, "Distinguishing property %n", RTProperties::iname(prn));
+    Emit::code_comment(C);
+    DISCARD_TEXT(C)
+
+    if (Properties::is_either_or(prn)) {
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), AND_BIP);
+            Produce::down(Emit::tree());
+                RTPropertyValues::emit_iname_has_property(K_value, Hierarchy::find(PARSER_ONE_HL), prn);
+                Produce::inv_primitive(Emit::tree(), NOT_BIP);
+                Produce::down(Emit::tree());
+                    RTPropertyValues::emit_iname_has_property(K_value, Hierarchy::find(PARSER_TWO_HL), prn);
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Return minus two11.1;
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), AND_BIP);
+            Produce::down(Emit::tree());
+                RTPropertyValues::emit_iname_has_property(K_value, Hierarchy::find(PARSER_TWO_HL), prn);
+                Produce::inv_primitive(Emit::tree(), NOT_BIP);
+                Produce::down(Emit::tree());
+                    RTPropertyValues::emit_iname_has_property(K_value, Hierarchy::find(PARSER_ONE_HL), prn);
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Return minus two11.1;
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    } else {
+        kind *K = ValueProperties::kind(prn);
+        inter_name *distinguisher = Kinds::Behaviour::get_distinguisher_as_iname(K);
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            if (distinguisher) {
+                Produce::inv_call_iname(Emit::tree(), distinguisher);
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ONE_HL));
+                        Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TWO_HL));
+                        Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            } else {
+                Produce::inv_primitive(Emit::tree(), NE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_ONE_HL));
+                        Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                    Produce::up(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSER_TWO_HL));
+                        Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            }
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Return minus two11.1;
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    }
+}
+
+

§11.1. Return minus two11.1 = +

+ +
+    Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+    Produce::down(Emit::tree());
+        Produce::val(Emit::tree(), K_number, LITERAL_IVAL, (inter_ti) -2);
+    Produce::up(Emit::tree());
+
+ +

§12.

+ +
+void UnderstandGeneralTokens::finish_distinguishing_visible_properties(gpr_kit *gprk) {
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                Produce::val_symbol(Emit::tree(), K_value, gprk->ss_s);
+            Produce::up(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+            Produce::down(Emit::tree());
+                Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 0);
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+}
+
+

§13. Parsing visible properties. Here, unlike in distinguishing visible properties, it is unambiguous that +self refers to the object being parsed: there is therefore no need to +alter the value of self to make any visibility condition work correctly. +

+ +
+void UnderstandGeneralTokens::begin_parsing_visible_properties(gpr_kit *gprk) {
+    Emit::code_comment(I"Match any number of visible property values");
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->g_s);
+        Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), WHILE_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_symbol(Emit::tree(), K_value, gprk->g_s);
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), STORE_BIP);
+            Produce::down(Emit::tree());
+                Produce::ref_symbol(Emit::tree(), K_value, gprk->g_s);
+                Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 0);
+            Produce::up(Emit::tree());
+}
+
+void UnderstandGeneralTokens::test_parse_visible_property(gpr_kit *gprk, parse_node *spec) {
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        Specifications::Compiler::emit_as_val(K_truth_state, spec);
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+}
+
+int unique_pvp_counter = 0;
+void UnderstandGeneralTokens::parse_visible_property(gpr_kit *gprk,
+    inference_subject *subj, property *prn, int visibility_level) {
+    TEMPORARY_TEXT(C)
+    WRITE_TO(C, "Parsing property %n", RTProperties::iname(prn));
+    Emit::code_comment(C);
+    DISCARD_TEXT(C)
+
+    if (Properties::is_either_or(prn)) {
+        TEMPORARY_TEXT(L)
+        WRITE_TO(L, ".pvp_pass_L_%d", unique_pvp_counter++);
+        inter_symbol *pass_label = Produce::reserve_label(Emit::tree(), L);
+        DISCARD_TEXT(L)
+
+        UnderstandGeneralTokens::parse_visible_either_or(
+            gprk, prn, visibility_level, pass_label);
+        property *prnbar = EitherOrProperties::get_negation(prn);
+        if (prnbar)
+            UnderstandGeneralTokens::parse_visible_either_or(
+                gprk, prnbar, visibility_level, pass_label);
+
+        Produce::place_label(Emit::tree(), pass_label);
+    } else {
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+            Produce::val_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_symbol(Emit::tree(), K_value, gprk->spn_s);
+            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSED_NUMBER_HL));
+        Produce::up(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_symbol(Emit::tree(), K_value, gprk->ss_s);
+            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(ETYPE_HL));
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            kind *K = ValueProperties::kind(prn);
+            inter_name *recog_gpr = Kinds::Behaviour::get_recognition_only_GPR_as_iname(K);
+            if (recog_gpr) {
+                Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                Produce::down(Emit::tree());
+                    Produce::inv_call_iname(Emit::tree(), recog_gpr);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                            Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_PREPOSITION_HL));
+                Produce::up(Emit::tree());
+            } else if (Kinds::Behaviour::offers_I6_GPR(K)) {
+                inter_name *i6_gpr_name = Kinds::Behaviour::get_explicit_I6_GPR_iname(K);
+                if (i6_gpr_name) {
+                    Produce::inv_primitive(Emit::tree(), AND_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_call_iname(Emit::tree(), i6_gpr_name);
+                            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_NUMBER_HL));
+                        Produce::up(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                                Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                            Produce::up(Emit::tree());
+                            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSED_NUMBER_HL));
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                } else if (Kinds::Behaviour::is_an_enumeration(K)) {
+                    Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_call_iname(Emit::tree(), RTKinds::get_instance_GPR_iname(K));
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                                Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_NUMBER_HL));
+                    Produce::up(Emit::tree());
+                } else {
+                    Produce::inv_primitive(Emit::tree(), AND_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_call_iname(Emit::tree(), RTKinds::get_kind_GPR_iname(K));
+                            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_NUMBER_HL));
+                        Produce::up(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), PROPERTYVALUE_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SELF_HL));
+                                Produce::val_iname(Emit::tree(), K_value, RTProperties::iname(prn));
+                            Produce::up(Emit::tree());
+                            Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(PARSED_NUMBER_HL));
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                }
+            } else internal_error("Unable to recognise kind of value in parsing");
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+                Produce::up(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::ref_symbol(Emit::tree(), K_value, gprk->g_s);
+                    Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+                Produce::up(Emit::tree());
+                if (visibility_level == 2) {
+                    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+                        Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+                    Produce::up(Emit::tree());
+                }
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(PARSED_NUMBER_HL));
+            Produce::val_symbol(Emit::tree(), K_value, gprk->spn_s);
+        Produce::up(Emit::tree());
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(ETYPE_HL));
+            Produce::val_symbol(Emit::tree(), K_value, gprk->ss_s);
+        Produce::up(Emit::tree());
+    }
+}
+
+void UnderstandGeneralTokens::parse_visible_either_or(gpr_kit *gprk, property *prn, int visibility_level,
+    inter_symbol *pass_l) {
+    command_grammar *cg = EitherOrProperties::get_parsing_grammar(prn);
+    UnderstandGeneralTokens::pvp_test_begins_dash(gprk);
+    Produce::inv_primitive(Emit::tree(), IF_BIP);
+    Produce::down(Emit::tree());
+        wording W = prn->name;
+        int j = 0; LOOP_THROUGH_WORDING(i, W) j++;
+        int ands = 0;
+        if (j > 0) { Produce::inv_primitive(Emit::tree(), AND_BIP); Produce::down(Emit::tree()); ands++; }
+        RTPropertyValues::emit_iname_has_property(K_value, Hierarchy::find(SELF_HL), prn);
+        int k = 0;
+        LOOP_THROUGH_WORDING(i, W) {
+            if (k < j-1) { Produce::inv_primitive(Emit::tree(), AND_BIP); Produce::down(Emit::tree()); ands++; }
+            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+            Produce::down(Emit::tree());
+                Produce::inv_call_iname(Emit::tree(), Hierarchy::find(NEXTWORDSTOPPED_HL));
+                TEMPORARY_TEXT(N)
+                WRITE_TO(N, "%N", i);
+                Produce::val_dword(Emit::tree(), N);
+                DISCARD_TEXT(N)
+            Produce::up(Emit::tree());
+            k++;
+        }
+
+        for (int a=0; a<ands; a++) Produce::up(Emit::tree());
+        Produce::code(Emit::tree());
+        Produce::down(Emit::tree());
+            UnderstandGeneralTokens::pvp_test_passes_dash(gprk, visibility_level, pass_l);
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+    if (cg) {
+        if (cg->compilation_data.cg_prn_iname == NULL) internal_error("no PRN iname");
+        UnderstandGeneralTokens::pvp_test_begins_dash(gprk);
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), AND_BIP);
+            Produce::down(Emit::tree());
+                RTPropertyValues::emit_iname_has_property(K_value, Hierarchy::find(SELF_HL), prn);
+                Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                Produce::down(Emit::tree());
+                    Produce::inv_call_iname(Emit::tree(), cg->compilation_data.cg_prn_iname);
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_PREPOSITION_HL));
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                UnderstandGeneralTokens::pvp_test_passes_dash(gprk, visibility_level, pass_l);
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    }
+}
+
+void UnderstandGeneralTokens::pvp_test_begins_dash(gpr_kit *gprk) {
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+        Produce::val_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+    Produce::up(Emit::tree());
+}
+
+void UnderstandGeneralTokens::pvp_test_passes_dash(gpr_kit *gprk, int visibility_level, inter_symbol *pass_l) {
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+    Produce::up(Emit::tree());
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk->g_s);
+        Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+    Produce::up(Emit::tree());
+    if (visibility_level == 2) {
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_symbol(Emit::tree(), K_value, gprk->f_s);
+            Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+        Produce::up(Emit::tree());
+    }
+    if (pass_l) {
+        Produce::inv_primitive(Emit::tree(), JUMP_BIP);
+        Produce::down(Emit::tree());
+            Produce::lab(Emit::tree(), pass_l);
+        Produce::up(Emit::tree());
+    }
+}
+
+void UnderstandGeneralTokens::finish_parsing_visible_properties(gpr_kit *gprk) {
+        Produce::up(Emit::tree());
+    Produce::up(Emit::tree());
+    Emit::code_comment(I"try_from_wn is now advanced past any visible property values");
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+        Produce::val_symbol(Emit::tree(), K_value, gprk->try_from_wn_s);
+    Produce::up(Emit::tree());
+}
+
+ + +
+ + + diff --git a/docs/runtime-module/5-nft.html b/docs/runtime-module/5-nft.html new file mode 100644 index 000000000..dac548975 --- /dev/null +++ b/docs/runtime-module/5-nft.html @@ -0,0 +1,361 @@ + + + + Noun Filter Tokens + + + + + + + + + + + + + + + + + + +
+ + +

Filters are used to require nouns to have specific kinds or attributes, or to have specific scoping rules: they correspond to Inform 6's |noun=Routine| and |scope=Routine| tokens. Though these are quite different concepts in I6, their common handling seems natural in I7.

+ +
+ +

§1. Definitions.

+ +
+typedef struct noun_filter_token {
+    struct parse_node *the_filter;
+    struct parse_node *nft_created_at;
+    int global_scope_flag;
+    int any_things_flag;
+    int parse_using_gpr;
+    int nft_compiled;
+    struct inter_name *nft_iname;
+    CLASS_DEFINITION
+} noun_filter_token;
+
+ +

§2. There are only three things we can do with these: create them, compile +their names (used as I6 tokens), and compile their routines. +

+ +
+noun_filter_token *UnderstandFilterTokens::nft_new(parse_node *spec, int global_scope, int any_things) {
+    noun_filter_token *nft = CREATE(noun_filter_token);
+    nft->the_filter = spec;
+    nft->global_scope_flag = global_scope;
+    nft->any_things_flag = any_things;
+    nft->nft_created_at = current_sentence;
+    nft->parse_using_gpr = FALSE;
+    nft->nft_compiled = FALSE;
+
+    if (global_scope) {
+        package_request *PR = Hierarchy::local_package(SCOPE_FILTERS_HAP);
+        nft->nft_iname = Hierarchy::make_iname_in(SCOPE_FILTER_FN_HL, PR);
+    } else {
+        package_request *PR = Hierarchy::local_package(NOUN_FILTERS_HAP);
+        nft->nft_iname = Hierarchy::make_iname_in(NOUN_FILTER_FN_HL, PR);
+    }
+    return nft;
+}
+
+inter_name *UnderstandFilterTokens::nft_compile_routine_iname(noun_filter_token *nft) {
+    return nft->nft_iname;
+}
+
+void UnderstandFilterTokens::nft_compile_routine(noun_filter_token *nft) {
+    parse_node *noun_var = Lvalues::new_actual_NONLOCAL_VARIABLE(Inter_noun_VAR);
+    kind *R = Specifications::to_kind(nft->the_filter);
+    kind *K = NonlocalVariables::kind(Inter_noun_VAR);
+    NonlocalVariables::set_kind(Inter_noun_VAR, R);
+    if (Kinds::Behaviour::is_object(R) == FALSE) nft->parse_using_gpr = TRUE;
+
+    packaging_state save = Routines::begin(nft->nft_iname);
+    if (nft->parse_using_gpr) {
+        inter_symbol *v_s = LocalVariables::add_internal_local_c_as_symbol(I"v", "value parsed");
+        inter_symbol *n_s = LocalVariables::add_internal_local_c_as_symbol(I"n", "saved value of noun");
+
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_symbol(Emit::tree(), K_value, v_s);
+            inter_name *gpr_to_ask = Kinds::Behaviour::get_explicit_I6_GPR_iname(R);
+            if (gpr_to_ask == NULL) gpr_to_ask = RTKinds::get_kind_GPR_iname(R);
+            Produce::inv_call_iname(Emit::tree(), gpr_to_ask);
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), IF_BIP);
+        Produce::down(Emit::tree());
+            Produce::inv_primitive(Emit::tree(), EQ_BIP);
+            Produce::down(Emit::tree());
+                Produce::val_symbol(Emit::tree(), K_value, v_s);
+                Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(GPR_NUMBER_HL));
+            Produce::up(Emit::tree());
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::ref_symbol(Emit::tree(), K_value, n_s);
+                    Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                Produce::up(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                    Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(PARSED_NUMBER_HL));
+                Produce::up(Emit::tree());
+
+                Produce::inv_primitive(Emit::tree(), IF_BIP);
+                Produce::down(Emit::tree());
+                    Produce::inv_primitive(Emit::tree(), NOT_BIP);
+                    Produce::down(Emit::tree());
+                        Calculus::Deferrals::emit_test_if_var_matches_description(noun_var, nft->the_filter);
+                    Produce::up(Emit::tree());
+                    Produce::code(Emit::tree());
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::ref_symbol(Emit::tree(), K_value, v_s);
+                            Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(GPR_FAIL_HL));
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+
+                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                    Produce::val_symbol(Emit::tree(), K_value, n_s);
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_symbol(Emit::tree(), K_value, v_s);
+        Produce::up(Emit::tree());
+    } else if (nft->global_scope_flag) {
+        inter_symbol *obj_s = LocalVariables::add_internal_local_c_as_symbol(I"obj", "object loop variable");
+        inter_symbol *o2_s = LocalVariables::add_internal_local_c_as_symbol(I"o2", "saved value of noun");
+
+        Produce::inv_primitive(Emit::tree(), SWITCH_BIP);
+        Produce::down(Emit::tree());
+            Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(SCOPE_STAGE_HL));
+            Produce::code(Emit::tree());
+            Produce::down(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), CASE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 1);
+                    Produce::code(Emit::tree());
+                    Produce::down(Emit::tree());
+                        if (nft->any_things_flag) Produce::rtrue(Emit::tree());
+                        else Produce::rfalse(Emit::tree());
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), CASE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 2);
+                    Produce::code(Emit::tree());
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::ref_symbol(Emit::tree(), K_value, obj_s);
+                            Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                        Produce::up(Emit::tree());
+
+                        Produce::inv_primitive(Emit::tree(), OBJECTLOOP_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                            Produce::val_iname(Emit::tree(), K_value, RTKinds::I6_classname(K_object));
+                            Calculus::Deferrals::emit_test_if_var_matches_description(noun_var, nft->the_filter);
+
+                            Produce::code(Emit::tree());
+                            Produce::down(Emit::tree());
+                                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                Produce::down(Emit::tree());
+                                    Produce::ref_symbol(Emit::tree(), K_value, o2_s);
+                                    Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                                Produce::up(Emit::tree());
+                                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                Produce::down(Emit::tree());
+                                    Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                                    Produce::val_symbol(Emit::tree(), K_value, obj_s);
+                                Produce::up(Emit::tree());
+
+                                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                Produce::down(Emit::tree());
+                                    Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(SUPPRESS_SCOPE_LOOPS_HL));
+                                    Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+                                Produce::up(Emit::tree());
+
+                                Produce::inv_call_iname(Emit::tree(), Hierarchy::find(PLACEINSCOPE_HL));
+                                Produce::down(Emit::tree());
+                                    Produce::val_symbol(Emit::tree(), K_value, o2_s);
+                                    Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 1);
+                                Produce::up(Emit::tree());
+
+                                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                Produce::down(Emit::tree());
+                                    Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(SUPPRESS_SCOPE_LOOPS_HL));
+                                    Produce::val(Emit::tree(), K_truth_state, LITERAL_IVAL, 0);
+                                Produce::up(Emit::tree());
+
+                                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                                Produce::down(Emit::tree());
+                                    Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                                    Produce::val_symbol(Emit::tree(), K_value, o2_s);
+                                Produce::up(Emit::tree());
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+
+                        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+                            Produce::val_symbol(Emit::tree(), K_value, obj_s);
+                        Produce::up(Emit::tree());
+
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), CASE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val(Emit::tree(), K_number, LITERAL_IVAL, 3);
+                    Produce::code(Emit::tree());
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::ref_iname(Emit::tree(), K_object, Hierarchy::find(NEXTBEST_ETYPE_HL));
+                            Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(NOTINCONTEXTPE_HL));
+                        Produce::up(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::val(Emit::tree(), K_number, LITERAL_IVAL, (inter_ti) (-1));
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                Produce::up(Emit::tree());
+            Produce::up(Emit::tree());
+        Produce::up(Emit::tree());
+    } else {
+        inter_symbol *x_s = LocalVariables::add_internal_local_c_as_symbol(I"x", "saved value of noun");
+        Produce::inv_primitive(Emit::tree(), STORE_BIP);
+        Produce::down(Emit::tree());
+            Produce::ref_symbol(Emit::tree(), K_value, x_s);
+            Produce::val_iname(Emit::tree(), K_object, Hierarchy::find(NOUN_HL));
+        Produce::up(Emit::tree());
+
+        Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+        Produce::down(Emit::tree());
+            if (Specifications::to_proposition(nft->the_filter)) {
+                Propositions::Checker::type_check(Specifications::to_proposition(nft->the_filter), Propositions::Checker::tc_no_problem_reporting());
+                Calculus::Deferrals::emit_test_of_proposition(
+                    noun_var, Specifications::to_proposition(nft->the_filter));
+            } else
+                Calculus::Deferrals::emit_test_if_var_matches_description(noun_var, nft->the_filter);
+        Produce::up(Emit::tree());
+    }
+    Routines::end(save);
+    NonlocalVariables::set_kind(Inter_noun_VAR, K);
+}
+
+

§3. Access via ID. For now, though, these are perhaps strangely accessed by ID number. (Because +the parse_node structure can't conveniently be annotated with pointers, +that's why.) +

+ +
+void UnderstandFilterTokens::compile_id(noun_filter_token *nft) {
+    if (nft) {
+        if (nft->parse_using_gpr) Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_TT_HL));
+        else if (nft->global_scope_flag) Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(SCOPE_TT_HL));
+        else Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(ROUTINEFILTER_TT_HL));
+        Produce::val_iname(Emit::tree(), K_value, nft->nft_iname);
+    }
+}
+
+void UnderstandFilterTokens::emit_id(noun_filter_token *nft) {
+    if (nft) {
+        inter_ti annot = 0;
+        if (nft->parse_using_gpr == FALSE) {
+            if (nft->global_scope_flag) annot = SCOPE_FILTER_IANN;
+            else annot = NOUN_FILTER_IANN;
+        }
+        inter_name *iname = UnderstandFilterTokens::nft_compile_routine_iname(nft);
+        if (annot != 0)
+            if (Produce::read_annotation(iname, annot) != 1)
+                Produce::annotate_i(iname, annot, 1);
+        Emit::array_iname_entry(iname);
+    }
+}
+
+

§4. Compiling everything. Having referred to these filter routines, we need to compile them. +

+ +
+void UnderstandFilterTokens::compile(void) {
+    noun_filter_token *nft;
+    LOOP_OVER(nft, noun_filter_token)
+        if (nft->nft_compiled == FALSE) {
+            current_sentence = nft->nft_created_at;
+            UnderstandFilterTokens::nft_compile_routine(nft);
+            nft->nft_compiled = TRUE;
+        }
+}
+
+ + +
+ + + diff --git a/docs/runtime-module/5-tpv.html b/docs/runtime-module/5-tpv.html new file mode 100644 index 000000000..17ba49c2f --- /dev/null +++ b/docs/runtime-module/5-tpv.html @@ -0,0 +1,393 @@ + + + + Tokens Parsing Values + + + + + + + + + + + + + + + + + + +
+ + +

In the argot of Inform 6, GPR stands for General Parsing Routine, and I7 makes heavy use of GPR tokens to achieve its ends. This section is where the necessary I6 routines are compiled.

+ +

§1.

+ +
+typedef struct gpr_kit {
+    inter_symbol *cur_addr_s;
+    inter_symbol *cur_len_s;
+    inter_symbol *cur_word_s;
+    inter_symbol *f_s;
+    inter_symbol *g_s;
+    inter_symbol *group_wn_s;
+    inter_symbol *instance_s;
+    inter_symbol *matched_number_s;
+    inter_symbol *mid_word_s;
+    inter_symbol *n_s;
+    inter_symbol *original_wn_s;
+    inter_symbol *pass_s;
+    inter_symbol *pass1_n_s;
+    inter_symbol *pass2_n_s;
+    inter_symbol *range_from_s;
+    inter_symbol *range_words_s;
+    inter_symbol *rv_s;
+    local_variable *rv_lv;
+    inter_symbol *sgn_s;
+    inter_symbol *spn_s;
+    inter_symbol *ss_s;
+    inter_symbol *tot_s;
+    inter_symbol *try_from_wn_s;
+    inter_symbol *v_s;
+    inter_symbol *w_s;
+    inter_symbol *wpos_s;
+    inter_symbol *x_s;
+} gpr_kit;
+
+gpr_kit UnderstandValueTokens::new_kit(void) {
+    gpr_kit gprk;
+    gprk.cur_addr_s = NULL;
+    gprk.cur_len_s = NULL;
+    gprk.cur_word_s = NULL;
+    gprk.f_s = NULL;
+    gprk.g_s = NULL;
+    gprk.group_wn_s = NULL;
+    gprk.instance_s = NULL;
+    gprk.matched_number_s = NULL;
+    gprk.mid_word_s = NULL;
+    gprk.n_s = NULL;
+    gprk.original_wn_s = NULL;
+    gprk.pass_s = NULL;
+    gprk.pass1_n_s = NULL;
+    gprk.pass2_n_s = NULL;
+    gprk.range_from_s = NULL;
+    gprk.range_words_s = NULL;
+    gprk.rv_s = NULL;
+    gprk.rv_lv = NULL;
+    gprk.sgn_s = NULL;
+    gprk.spn_s = NULL;
+    gprk.ss_s = NULL;
+    gprk.tot_s = NULL;
+    gprk.try_from_wn_s = NULL;
+    gprk.v_s = NULL;
+    gprk.w_s = NULL;
+    gprk.wpos_s = NULL;
+    gprk.x_s = NULL;
+    return gprk;
+}
+
+void UnderstandValueTokens::add_instance_call(gpr_kit *gprk) {
+    gprk->instance_s = LocalVariables::add_named_call_as_symbol(I"instance");
+}
+
+void UnderstandValueTokens::add_range_calls(gpr_kit *gprk) {
+    gprk->range_from_s = LocalVariables::add_internal_local_c_as_symbol(I"range_from", "call parameter: word number of snippet start");
+    gprk->range_words_s = LocalVariables::add_internal_local_c_as_symbol(I"range_words", "call parameter: snippet length");
+}
+
+void UnderstandValueTokens::add_original(gpr_kit *gprk) {
+    gprk->original_wn_s = LocalVariables::add_internal_local_as_symbol(I"original_wn");
+}
+
+void UnderstandValueTokens::add_standard_set(gpr_kit *gprk) {
+    gprk->group_wn_s = LocalVariables::add_internal_local_as_symbol(I"group_wn");
+    gprk->v_s = LocalVariables::add_internal_local_as_symbol(I"v");
+    gprk->w_s = LocalVariables::add_internal_local_as_symbol(I"w");
+    gprk->rv_s = LocalVariables::add_internal_local_as_symbol_noting(I"rv", &(gprk->rv_lv));
+}
+
+void UnderstandValueTokens::add_lp_vars(gpr_kit *gprk) {
+    gprk->wpos_s = LocalVariables::add_internal_local_as_symbol(I"wpos");
+    gprk->mid_word_s = LocalVariables::add_internal_local_as_symbol(I"mid_word");
+    gprk->matched_number_s = LocalVariables::add_internal_local_as_symbol(I"matched_number");
+    gprk->cur_word_s = LocalVariables::add_internal_local_as_symbol(I"cur_word");
+    gprk->cur_len_s = LocalVariables::add_internal_local_as_symbol(I"cur_len");
+    gprk->cur_addr_s = LocalVariables::add_internal_local_as_symbol(I"cur_addr");
+    gprk->sgn_s = LocalVariables::add_internal_local_as_symbol(I"sgn");
+    gprk->tot_s = LocalVariables::add_internal_local_as_symbol(I"tot");
+    gprk->f_s = LocalVariables::add_internal_local_as_symbol(I"f");
+    gprk->x_s = LocalVariables::add_internal_local_as_symbol(I"x");
+}
+
+void UnderstandValueTokens::add_parse_name_vars(gpr_kit *gprk) {
+    gprk->original_wn_s = LocalVariables::add_internal_local_c_as_symbol(I"original_wn", "first word of text parsed");
+    gprk->group_wn_s = LocalVariables::add_internal_local_c_as_symbol(I"group_wn", "first word matched against A/B/C/... disjunction");
+    gprk->try_from_wn_s = LocalVariables::add_internal_local_c_as_symbol(I"try_from_wn", "position to try matching from");
+    gprk->n_s = LocalVariables::add_internal_local_c_as_symbol(I"n", "number of words matched");
+    gprk->f_s = LocalVariables::add_internal_local_c_as_symbol(I"f", "flag: sufficiently good match found to justify success");
+    gprk->w_s = LocalVariables::add_internal_local_c_as_symbol(I"w", "for use by individual grammar lines");
+    gprk->rv_s = LocalVariables::add_internal_local_as_symbol_noting(I"rv", &(gprk->rv_lv));
+    gprk->g_s = LocalVariables::add_internal_local_c_as_symbol(I"g", "temporary: success flag for parsing visibles");
+    gprk->ss_s = LocalVariables::add_internal_local_c_as_symbol(I"ss", "temporary: saves 'self' in distinguishing visibles");
+    gprk->spn_s = LocalVariables::add_internal_local_c_as_symbol(I"spn", "temporary: saves 'parsed_number' in parsing visibles");
+    gprk->pass_s = LocalVariables::add_internal_local_c_as_symbol(I"pass", "pass counter (1 to 3)");
+    gprk->pass1_n_s = LocalVariables::add_internal_local_c_as_symbol(I"pass1_n", "value of n recorded during pass 1");
+    gprk->pass2_n_s = LocalVariables::add_internal_local_c_as_symbol(I"pass2_n", "value of n recorded during pass 2");
+}
+
+void UnderstandValueTokens::number(void) {
+    inter_name *iname = Hierarchy::find(DECIMAL_TOKEN_INNER_HL);
+    packaging_state save = Routines::begin(iname);
+    gpr_kit gprk = UnderstandValueTokens::new_kit();
+    UnderstandValueTokens::add_original(&gprk);
+    command_grammar *cg = CommandGrammars::get_parsing_grammar(K_number);
+    if (cg) RTCommandGrammars::compile_iv(&gprk, cg);
+    Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_FAIL_HL));
+    Produce::up(Emit::tree());
+    Routines::end(save);
+    Hierarchy::make_available(Emit::tree(), iname);
+}
+
+void UnderstandValueTokens::time(void) {
+    inter_name *iname = Hierarchy::find(TIME_TOKEN_INNER_HL);
+    packaging_state save = Routines::begin(iname);
+    gpr_kit gprk = UnderstandValueTokens::new_kit();
+    UnderstandValueTokens::add_original(&gprk);
+    kind *K = TimesOfDay::kind();
+    if (K) {
+        command_grammar *cg = CommandGrammars::get_parsing_grammar(K);
+        if (cg) RTCommandGrammars::compile_iv(&gprk, cg);
+    }
+    Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_FAIL_HL));
+    Produce::up(Emit::tree());
+    Routines::end(save);
+    Hierarchy::make_available(Emit::tree(), iname);
+}
+
+void UnderstandValueTokens::truth_state(void) {
+    inter_name *iname = Hierarchy::find(TRUTH_STATE_TOKEN_INNER_HL);
+    packaging_state save = Routines::begin(iname);
+    gpr_kit gprk = UnderstandValueTokens::new_kit();
+    UnderstandValueTokens::add_original(&gprk);
+    command_grammar *cg = CommandGrammars::get_parsing_grammar(K_truth_state);
+    if (cg) RTCommandGrammars::compile_iv(&gprk, cg);
+    Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_FAIL_HL));
+    Produce::up(Emit::tree());
+    Routines::end(save);
+    Hierarchy::make_available(Emit::tree(), iname);
+}
+
+void UnderstandValueTokens::compile_type_gprs(void) {
+    int next_label = 1, longest;
+    command_grammar *cg;
+    kind *K;
+    LOOP_OVER_BASE_KINDS(K) {
+        if ((Kinds::Behaviour::is_an_enumeration(K)) ||
+            (Kinds::Behaviour::is_quasinumerical(K))) {
+            instance *q; literal_pattern *lp;
+            if (Kinds::Behaviour::needs_I6_GPR(K) == FALSE) continue;
+            inter_name *iname = RTKinds::get_kind_GPR_iname(K);
+            packaging_state save = Routines::begin(iname);
+            int need_lf_vars = FALSE;
+            LITERAL_FORMS_LOOP(lp, K) {
+                need_lf_vars = TRUE;
+                break;
+            }
+            gpr_kit gprk = UnderstandValueTokens::new_kit();
+            UnderstandValueTokens::add_original(&gprk);
+            UnderstandValueTokens::add_standard_set(&gprk);
+            if (need_lf_vars) UnderstandValueTokens::add_lp_vars(&gprk);
+            Compile body of kind GPR1.1;
+            Routines::end(save);
+
+            if (Kinds::Behaviour::is_an_enumeration(K)) {
+                inter_name *iname = RTKinds::get_instance_GPR_iname(K);
+                packaging_state save = Routines::begin(iname);
+                gpr_kit gprk = UnderstandValueTokens::new_kit();
+                UnderstandValueTokens::add_instance_call(&gprk);
+                UnderstandValueTokens::add_original(&gprk);
+                UnderstandValueTokens::add_standard_set(&gprk);
+                GV_IS_VALUE_instance_mode = TRUE;
+                Compile body of kind GPR1.1;
+                GV_IS_VALUE_instance_mode = FALSE;
+                Routines::end(save);
+            }
+        }
+    }
+}
+
+ +

§1.1. Compile body of kind GPR1.1 = +

+ +
+    Save word number1.1.1;
+    LITERAL_FORMS_LOOP(lp, K) {
+        RTLiteralPatterns::gpr(&gprk, lp);
+        Reset word number1.1.2;
+    }
+
+    cg = CommandGrammars::get_parsing_grammar(K);
+    if (cg != NULL) {
+        RTCommandGrammars::compile_iv(&gprk, cg);
+        Reset word number1.1.2;
+    }
+    longest = 0;
+    LOOP_OVER_INSTANCES(q, K) {
+        wording NW = Instances::get_name_in_play(q, FALSE);
+        int L = Wordings::length(NW) - 1;
+        if (L > longest) longest = L;
+    }
+    for (; longest >= 0; longest--) {
+        LOOP_OVER_INSTANCES(q, K) {
+            wording NW = Instances::get_name_in_play(q, FALSE);
+            if (Wordings::length(NW) - 1 == longest) {
+                if (GV_IS_VALUE_instance_mode) {
+                    Produce::inv_primitive(Emit::tree(), IF_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), EQ_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::val_symbol(Emit::tree(), K_value, gprk.instance_s);
+                            Produce::val_iname(Emit::tree(), K_value, RTInstances::iname(q));
+                        Produce::up(Emit::tree());
+                        Produce::code(Emit::tree());
+                        Produce::down(Emit::tree());
+                }
+                Reset word number1.1.2;
+
+                TEMPORARY_TEXT(L)
+                WRITE_TO(L, ".Failed_%d", next_label++);
+                inter_symbol *flab = Produce::reserve_label(Emit::tree(), L);
+                DISCARD_TEXT(L)
+
+                LOOP_THROUGH_WORDING(k, NW) {
+                    Produce::inv_primitive(Emit::tree(), IF_BIP);
+                    Produce::down(Emit::tree());
+                        Produce::inv_primitive(Emit::tree(), NE_BIP);
+                        Produce::down(Emit::tree());
+                            Produce::inv_call_iname(Emit::tree(), Hierarchy::find(NEXTWORDSTOPPED_HL));
+                            TEMPORARY_TEXT(W)
+                            WRITE_TO(W, "%N", k);
+                            Produce::val_dword(Emit::tree(), W);
+                            DISCARD_TEXT(W)
+                        Produce::up(Emit::tree());
+                        Produce::code(Emit::tree());
+                        Produce::down(Emit::tree());
+                            Produce::inv_primitive(Emit::tree(), JUMP_BIP);
+                            Produce::down(Emit::tree());
+                                Produce::lab(Emit::tree(), flab);
+                            Produce::up(Emit::tree());
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                }
+                Produce::inv_primitive(Emit::tree(), STORE_BIP);
+                Produce::down(Emit::tree());
+                    Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(PARSED_NUMBER_HL));
+                    Produce::val_iname(Emit::tree(), K_value, RTInstances::iname(q));
+                Produce::up(Emit::tree());
+                Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+                Produce::down(Emit::tree());
+                    Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_NUMBER_HL));
+                Produce::up(Emit::tree());
+
+                if (GV_IS_VALUE_instance_mode) {
+                        Produce::up(Emit::tree());
+                    Produce::up(Emit::tree());
+                }
+                Produce::place_label(Emit::tree(), flab);
+            }
+        }
+    }
+    Produce::inv_primitive(Emit::tree(), RETURN_BIP);
+    Produce::down(Emit::tree());
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(GPR_FAIL_HL));
+    Produce::up(Emit::tree());
+
+ +

§1.1.1. Save word number1.1.1 = +

+ +
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_symbol(Emit::tree(), K_value, gprk.original_wn_s);
+        Produce::val_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+    Produce::up(Emit::tree());
+
+ +

§1.1.2. Reset word number1.1.2 = +

+ +
+    Produce::inv_primitive(Emit::tree(), STORE_BIP);
+    Produce::down(Emit::tree());
+        Produce::ref_iname(Emit::tree(), K_value, Hierarchy::find(WN_HL));
+        Produce::val_symbol(Emit::tree(), K_value, gprk.original_wn_s);
+    Produce::up(Emit::tree());
+
+ + + +
+ + +