From 89f9b0e45ddf2662dcf19232e6c38c09c6b4883a Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Tue, 16 Feb 2021 00:54:32 +0000 Subject: [PATCH] Refactored inferences --- README.md | 2 +- build.txt | 4 +- docs/assertions-module/2-ptmn.html | 2 +- docs/assertions-module/4-imp.html | 27 +- docs/assertions-module/6-er.html | 8 +- docs/assertions-module/6-terr.html | 2 +- docs/core-module/1-cp.html | 4 + docs/core-module/1-htc.html | 8 +- docs/core-module/2-si.html | 4 +- docs/if-module/3-bck.html | 50 +- docs/if-module/3-dvc.html | 2 +- docs/if-module/3-em.html | 2 +- docs/if-module/3-mcr.html | 6 +- docs/if-module/3-prs.html | 2 +- docs/if-module/3-rgn.html | 10 +- docs/if-module/3-sm.html | 161 +++-- docs/if-module/3-sm2.html | 2 +- docs/if-module/3-sr.html | 12 +- docs/if-module/3-tm.html | 61 +- docs/if-module/3-tm2.html | 4 +- docs/if-module/3-tnt.html | 22 +- docs/if-module/3-tp.html | 6 +- docs/if-module/5-gp.html | 2 +- docs/index-module/2-ipw.html | 6 +- docs/index-module/2-ki.html | 2 +- docs/knowledge-module/1-ap.html | 10 +- docs/knowledge-module/1-km.html | 11 +- docs/knowledge-module/2-iaa.html | 4 +- docs/knowledge-module/2-ins.html | 8 +- docs/knowledge-module/2-nv.html | 8 +- docs/knowledge-module/3-cp.html | 2 +- docs/knowledge-module/3-ep.html | 10 +- docs/knowledge-module/3-epv.html | 17 +- docs/knowledge-module/3-ia.html | 16 +- docs/knowledge-module/3-ma.html | 2 +- docs/knowledge-module/3-prp.html | 26 +- docs/knowledge-module/3-ps.html | 18 +- docs/knowledge-module/3-spr2.html | 2 +- docs/knowledge-module/3-vp.html | 24 +- docs/knowledge-module/4-is.html | 66 +- docs/knowledge-module/4-is2.html | 2 +- docs/knowledge-module/4-ks.html | 4 +- docs/knowledge-module/4-rs.html | 34 +- docs/knowledge-module/4-vs.html | 10 +- docs/knowledge-module/5-cmw2.html | 119 ---- docs/knowledge-module/5-inf.html | 628 ++++++++---------- docs/knowledge-module/5-pi.html | 246 +++++++ docs/knowledge-module/5-pp.html | 6 +- docs/knowledge-module/5-ri.html | 95 +++ .../{5-cmw.html => 5-tmw.html} | 215 +++--- docs/knowledge-module/P-wtmd.html | 20 +- docs/knowledge-module/index.html | 28 +- docs/runtime-module/2-emt.html | 2 +- docs/runtime-module/2-hrr.html | 12 +- docs/runtime-module/4-adj.html | 2 +- docs/runtime-module/4-cl.html | 2 +- docs/runtime-module/4-ct.html | 2 +- docs/runtime-module/4-efart.html | 2 +- docs/runtime-module/4-es.html | 2 +- docs/runtime-module/4-fc.html | 2 +- docs/runtime-module/4-i6i.html | 2 +- .../5-ic.html => runtime-module/4-ic.html} | 216 +++--- docs/runtime-module/4-ins.html | 4 +- docs/runtime-module/4-itc.html | 2 +- docs/runtime-module/4-iti.html | 2 +- docs/runtime-module/4-jl.html | 2 +- docs/runtime-module/4-lpart.html | 2 +- docs/runtime-module/4-lt.html | 2 +- docs/runtime-module/4-ni.html | 2 +- docs/runtime-module/4-pc.html | 9 +- docs/runtime-module/4-plg.html | 6 +- docs/runtime-module/4-rart.html | 14 +- docs/runtime-module/4-rsfk.html | 6 +- docs/runtime-module/4-rsft.html | 2 +- docs/runtime-module/4-rsp.html | 2 +- docs/runtime-module/4-rtn.html | 2 +- docs/runtime-module/4-tl.html | 2 +- docs/runtime-module/4-ts.html | 2 +- docs/runtime-module/4-ts2.html | 2 +- docs/runtime-module/4-tv.html | 2 +- docs/runtime-module/4-uoart.html | 2 +- docs/runtime-module/4-vart.html | 2 +- docs/runtime-module/4-vrb.html | 2 +- docs/runtime-module/index.html | 5 + inform7/Figures/memory-diagnostics.txt | 77 +-- inform7/Figures/timings-diagnostics.txt | 25 +- .../Chapter 2/Passes through Major Nodes.w | 2 +- .../Chapter 4/Implications.w | 27 +- .../Chapter 6/Explicit Relations.w | 8 +- .../The Equality Relation Revisited.w | 2 +- .../Chapter 1/Class Predeclarations.w | 4 + .../core-module/Chapter 1/How To Compile.w | 8 +- .../Chapter 2/Supplementary Issues.w | 4 +- inform7/if-module/Chapter 3/Backdrops.w | 38 +- inform7/if-module/Chapter 3/Devices.w | 2 +- inform7/if-module/Chapter 3/EPS Map.w | 2 +- .../Chapter 3/Map Connection Relations.w | 6 +- inform7/if-module/Chapter 3/Persons.w | 2 +- inform7/if-module/Chapter 3/Regions.w | 10 +- inform7/if-module/Chapter 3/Spatial Map.w | 2 +- inform7/if-module/Chapter 3/Spatial Model.w | 145 ++-- .../if-module/Chapter 3/Spatial Relations.w | 12 +- inform7/if-module/Chapter 3/Temporal Map.w | 4 +- inform7/if-module/Chapter 3/The Map.w | 53 +- .../if-module/Chapter 3/The Naming Thicket.w | 22 +- inform7/if-module/Chapter 3/The Player.w | 4 +- .../if-module/Chapter 5/Grammar Properties.w | 2 +- .../Chapter 2/Index Physical World.w | 6 +- inform7/index-module/Chapter 2/Kinds Index.w | 2 +- .../Chapter 1/Knowledge Module.w | 11 +- .../Chapter 2/Instances as Adjectives.w | 2 +- .../knowledge-module/Chapter 2/Instances.w | 2 +- .../Chapter 2/Nonlocal Variables.w | 6 +- .../Chapter 3/Either-Or Properties.w | 4 +- .../Chapter 3/Emit Property Values.w | 17 +- .../Chapter 3/Indefinite Appearance.w | 14 +- .../Chapter 3/Measurement Adjectives.w | 2 +- .../knowledge-module/Chapter 3/Properties.w | 12 +- .../Chapter 3/Setting Property Relation.w | 2 +- .../Chapter 4/Inference Subjects.w | 28 +- .../Chapter 4/Relation Subjects.w | 34 +- .../Chapter 4/Variable Subjects.w | 8 +- .../Chapter 5/Compile Model World.w | 39 -- .../knowledge-module/Chapter 5/Inferences.w | 537 +++++++-------- .../Chapter 5/Property Inferences.w | 165 +++++ .../Chapter 5/Relation Inferences.w | 15 + ...mplete Model World.w => The Model World.w} | 165 ++--- inform7/knowledge-module/Contents.w | 8 +- .../Preliminaries/What This Module Does.w | 16 +- .../Chapter 4}/Instance Counting.w | 4 +- .../runtime-module/Chapter 4/Plugin Calls.w | 7 +- .../Chapter 4/Relations at Run Time.w | 8 +- inform7/runtime-module/Contents.w | 1 + 133 files changed, 2151 insertions(+), 1787 deletions(-) delete mode 100644 docs/knowledge-module/5-cmw2.html create mode 100644 docs/knowledge-module/5-pi.html create mode 100644 docs/knowledge-module/5-ri.html rename docs/knowledge-module/{5-cmw.html => 5-tmw.html} (56%) rename docs/{knowledge-module/5-ic.html => runtime-module/4-ic.html} (66%) delete mode 100644 inform7/knowledge-module/Chapter 5/Compile Model World.w create mode 100644 inform7/knowledge-module/Chapter 5/Property Inferences.w create mode 100644 inform7/knowledge-module/Chapter 5/Relation Inferences.w rename inform7/knowledge-module/Chapter 5/{Complete Model World.w => The Model World.w} (50%) rename inform7/{knowledge-module/Chapter 5 => runtime-module/Chapter 4}/Instance Counting.w (99%) diff --git a/README.md b/README.md index 6c4a6ac01..2f66e0a9b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -v10.1.0-alpha.1+6R25 'Krypton' (15 February 2021) +v10.1.0-alpha.1+6R26 'Krypton' (16 February 2021) ## About Inform 7 diff --git a/build.txt b/build.txt index e8f28eb10..94417d35a 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: alpha.1 -Build Date: 15 February 2021 -Build Number: 6R25 +Build Date: 16 February 2021 +Build Number: 6R26 diff --git a/docs/assertions-module/2-ptmn.html b/docs/assertions-module/2-ptmn.html index bc3276297..179db72ba 100644 --- a/docs/assertions-module/2-ptmn.html +++ b/docs/assertions-module/2-ptmn.html @@ -169,7 +169,7 @@ any additional sentences generated.
     current_sentence = last;
     global_pass_state.assembly_position = current_sentence;
-    Plugins::Call::complete_model(1);
+    World::deduce_object_instance_kinds();
     SyntaxTree::traverse_nodep_from(last, MajorNodes::visit, &last);
 
diff --git a/docs/assertions-module/4-imp.html b/docs/assertions-module/4-imp.html index 4a7e1c308..f7defe4dd 100644 --- a/docs/assertions-module/4-imp.html +++ b/docs/assertions-module/4-imp.html @@ -85,10 +85,9 @@ description only, whereas B could be any subtree of an assertion.
 typedef struct implication {
-    struct pcalc_prop *if_spec;  which objects are affected
+    struct pcalc_prop *if_proposition;  which objects are affected
     struct parse_node *then_pn;  what assertion is implied about them
     int implied_likelihood;  with what certainty level
-    struct implication *next_implication;  in list of implications
     CLASS_DEFINITION
 } implication;
 
@@ -143,15 +142,13 @@ is to store them and sit on them. Check that the conclusion involves only a single either/or property3.2.3; implication *imp = CREATE(implication); - imp->if_spec = premiss; + imp->if_proposition = premiss; imp->then_pn = py; imp->implied_likelihood = prevailing_mood; - - imp->next_implication = InferenceSubjects::get_implications(premiss_kind); - InferenceSubjects::set_implications(premiss_kind, imp); + ADD_TO_LINKED_LIST(imp, implication, InferenceSubjects::get_implications(premiss_kind)); LOGIF(IMPLICATIONS, "Forming implication for $j: $D implies\n $T", - premiss_kind, imp->if_spec, imp->then_pn); + premiss_kind, imp->if_proposition, imp->then_pn);

§3.2.1. Find the premiss kind and specification3.2.1 = @@ -259,9 +256,9 @@ basis of the inferences so far drawn about it. if (k) Assertions::Implications::set_possessed_flags(k); inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); - if ((Properties::is_either_or(prn)) && (World::Inferences::get_certainty(inf) != UNKNOWN_CE)) + KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *prn = PropertyInferences::get_property(inf); + if ((Properties::is_either_or(prn)) && (Inferences::get_certainty(inf) != UNKNOWN_CE)) See what we can get out of this inference5.1; } } @@ -275,7 +272,7 @@ of not being open, and vice versa.

-    int truth_state = TRUE, certainty = World::Inferences::get_certainty(inf);
+    int truth_state = TRUE, certainty = Inferences::get_certainty(inf);
     if (certainty < 0) { certainty = -certainty; truth_state = FALSE; }
 
     possession_marker *pom = Properties::get_possession_marker(prn);
@@ -316,12 +313,12 @@ no better a certainty level.
     inference_subject *k = InferenceSubjects::narrowest_broader_subject(domain);
     if ((k) && (Assertions::Implications::check_implications_of(k, candidate))) return TRUE;
 
-    if (InferenceSubjects::get_implications(domain))
+    if (LinkedLists::len(InferenceSubjects::get_implications(domain)) > 0)
         LOGIF(IMPLICATIONS, "Considering implications about $j as they apply to $j:\n",
             domain, candidate);
 
     implication *imp;
-    for (imp = InferenceSubjects::get_implications(domain); imp; imp = imp->next_implication)
+    LOOP_OVER_LINKED_LIST(imp, implication, InferenceSubjects::get_implications(domain))
         Consider this individual implication as it applies to the candidate6.1;
 
     return FALSE;
@@ -337,7 +334,7 @@ no better a certainty level.
     if (imp->implied_likelihood < 0) conclusion_state = (conclusion_state)?FALSE:TRUE;
 
     LOGIF(IMPLICATIONS, "$D => $T (certainty %d; changed state %d)\n",
-        imp->if_spec, imp->then_pn, imp->implied_likelihood, conclusion_state);
+        imp->if_proposition, imp->then_pn, imp->implied_likelihood, conclusion_state);
 
     property *conclusion_prop = AdjectiveAmbiguity::has_either_or_property_meaning(
         AdjectivalPredicates::to_adjective(pred), NULL);
@@ -346,7 +343,7 @@ no better a certainty level.
     possession_marker *pom = Properties::get_possession_marker(conclusion_prop);
     Check that the conclusion is not redundant or irrelevant6.1.2;
 
-    int candidate_qualifies = Assert::test_at_compile_time(imp->if_spec, candidate);
+    int candidate_qualifies = Assert::test_at_compile_time(imp->if_proposition, candidate);
 
     if (candidate_qualifies) {
         LOGIF(IMPLICATIONS, "PASS: changing property $Y of $j\n", conclusion_prop, candidate);
diff --git a/docs/assertions-module/6-er.html b/docs/assertions-module/6-er.html
index 9ff32e048..a22103186 100644
--- a/docs/assertions-module/6-er.html
+++ b/docs/assertions-module/6-er.html
@@ -254,14 +254,14 @@ to behave as if \(B(y, x)\) had also been asserted whenever \(B(x, y)\) has, if
 
     Reject non-assertable relations7.1;
     if (Relations::Explicit::stored_dynamically(bp)) {
-        World::Inferences::draw_relation_spec(bp, spec0, spec1);
+        Inferences::draw_relation_spec(bp, spec0, spec1);
         return TRUE;
     } else {
         if ((infs0 == NULL) || (infs1 == NULL)) Reject relationship with nothing7.2;
         if (Relations::Explicit::allow_arbitrary_assertions(bp)) {
-            World::Inferences::draw_relation(bp, infs0, infs1);
+            Inferences::draw_relation(bp, infs0, infs1);
             if ((Relations::Explicit::get_form_of_relation(bp) == Relation_Sym_VtoV) && (infs0 != infs1))
-                World::Inferences::draw_relation(bp, infs1, infs0);
+                Inferences::draw_relation(bp, infs1, infs0);
             return TRUE;
         }
         if (Relations::Explicit::is_explicit_with_runtime_storage(bp)) {
@@ -321,7 +321,7 @@ inferences for \(y\) and \(z\).
         inference_subject *swap=infs0; infs0=infs1; infs1=swap;
     }
     property *prn = Relations::Explicit::get_i6_storage_property(bp);
-    World::Inferences::draw_property(infs0, prn, InferenceSubjects::as_constant(infs1));
+    PropertyInferences::draw(infs0, prn, InferenceSubjects::as_constant(infs1));
 }
 

§9. We need do nothing special: these relations can be compiled from their schemas. diff --git a/docs/assertions-module/6-terr.html b/docs/assertions-module/6-terr.html index 69e685576..0efe2a70c 100644 --- a/docs/assertions-module/6-terr.html +++ b/docs/assertions-module/6-terr.html @@ -212,7 +212,7 @@ setting a global variable. "a variable can only be given its value straightforwardly or " "qualified by 'usually'", "not with 'always', 'seldom' or 'never'."); - else World::Inferences::draw_property( + else PropertyInferences::draw( NonlocalVariables::to_subject(q), P_variable_initial_value, spec1); return TRUE; } diff --git a/docs/core-module/1-cp.html b/docs/core-module/1-cp.html index ef3a1f2cd..4431ca684 100644 --- a/docs/core-module/1-cp.html +++ b/docs/core-module/1-cp.html @@ -159,12 +159,14 @@ We begin with core itself. enum comparative_bp_data_CLASS enum counting_data_CLASS enum inference_CLASS +enum inference_family_CLASS enum inference_subject_CLASS enum inference_subject_family_CLASS enum measurement_definition_CLASS enum named_rulebook_outcome_CLASS enum placement_affecting_CLASS enum property_CLASS +enum property_inference_data_CLASS enum property_permission_CLASS enum property_of_value_storage_CLASS enum property_setting_bp_data_CLASS @@ -185,6 +187,7 @@ We begin with core itself. DECLARE_CLASS(comparative_bp_data) DECLARE_CLASS(counting_data) DECLARE_CLASS(inference) +DECLARE_CLASS(inference_family) DECLARE_CLASS(inference_subject) DECLARE_CLASS(inference_subject_family) DECLARE_CLASS(measurement_definition) @@ -193,6 +196,7 @@ We begin with core itself. DECLARE_CLASS(property_of_value_storage) DECLARE_CLASS(property_permission) DECLARE_CLASS(property) +DECLARE_CLASS(property_inference_data) DECLARE_CLASS(property_setting_bp_data) DECLARE_CLASS(rule) DECLARE_CLASS(rulebook) diff --git a/docs/core-module/1-htc.html b/docs/core-module/1-htc.html index 871994745..6b8daa0d7 100644 --- a/docs/core-module/1-htc.html +++ b/docs/core-module/1-htc.html @@ -245,7 +245,8 @@ so on. Those absolute basics are made here. BENCH(NounIdentifiers::name_all) BENCH(OrderingInstances::objects_in_definition_sequence) Task::advance_stage_to(MODEL_COMPLETE_CSEQ, I"Completing the model world", -1); - BENCH(World::complete) + BENCH(World::stages_II_and_III) + BENCH(World::stage_IV)

§2.6. Tables and grammar2.6 = @@ -262,7 +263,7 @@ so on. Those absolute basics are made here. BENCH(Tables::check_tables_for_kind_clashes) BENCH(RTTables::compile_print_table_names) BENCH(PL::Parsing::traverse) - BENCH(World::complete_additions) + BENCH(World::stage_V)

§2.7. Phrases and rules2.7 = @@ -303,7 +304,8 @@ so on. Those absolute basics are made here. BENCH(RTRelations::compile_defined_relation_constants) BENCH(RTKinds::compile_data_type_support_routines) BENCH(RTKinds::I7_Kind_Name_routine) - BENCH(World::Compile::compile) + BENCH(Plugins::Call::compile_model_tables) + BENCH(InferenceSubjects::emit_all) BENCH_IF(backdrops_plugin, PL::Backdrops::write_found_in_routines) BENCH_IF(map_plugin, PL::Map::write_door_dir_routines) BENCH_IF(map_plugin, PL::Map::write_door_to_routines) diff --git a/docs/core-module/2-si.html b/docs/core-module/2-si.html index a9f885fce..60757a8ae 100644 --- a/docs/core-module/2-si.html +++ b/docs/core-module/2-si.html @@ -310,10 +310,10 @@ making no sense. char *message, char *explanation) { ACT_ON_SIGIL Problems::quote_subject(1, infs); - Problems::quote_source(2, World::Inferences::where_inferred(inf)); + Problems::quote_source(2, Inferences::where_inferred(inf)); Problems::quote_text(3, message); Problems::quote_text(4, explanation); - Problems::quote_property(5, World::Inferences::get_property(inf)); + Problems::quote_property(5, PropertyInferences::get_property(inf)); Problems::issue_problem_begin(Task::syntax_tree(), explanation); Problems::issue_problem_segment( "You wrote %2: but the property %5 for the %1 %3%S.%L, %4"); diff --git a/docs/if-module/3-bck.html b/docs/if-module/3-bck.html index 773278ce3..eb8fe2cb1 100644 --- a/docs/if-module/3-bck.html +++ b/docs/if-module/3-bck.html @@ -82,10 +82,10 @@ inside something generates FO inferences to avoid piling up bogus inconsistencies.

-
define FOUND_IN_INF 56  for backdrop things in many places
-define FOUND_EVERYWHERE_INF 57  ditto
-
+inference_family *FOUND_IN_INF = NULL;  56; for backdrop things in many places
+inference_family *FOUND_EVERYWHERE_INF = NULL;  57; ditto
+
 kind *K_backdrop = NULL;
 property *P_scenery = NULL;  an I7 either/or property marking something as scenery
 property *P_absent = NULL;  an I6-only property for backdrops out of play
@@ -105,6 +105,10 @@ inferences to avoid piling up bogus inconsistencies.
 
 
 void PL::Backdrops::start(void) {
+    FOUND_IN_INF = Inferences::new_family(I"FOUND_IN_INF", CI_DIFFER_IN_INFS1);
+    FOUND_EVERYWHERE_INF = Inferences::new_family(I"FOUND_EVERYWHERE_INF", CI_DIFFER_IN_INFS1);
+
+    PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Backdrops::create_inference_families);
     PLUGIN_REGISTER(PLUGIN_NEW_BASE_KIND_NOTIFY, PL::Backdrops::backdrops_new_base_kind_notify);
     PLUGIN_REGISTER(PLUGIN_NEW_PROPERTY_NOTIFY, PL::Backdrops::backdrops_new_property_notify);
     PLUGIN_REGISTER(PLUGIN_COMPLETE_MODEL, PL::Backdrops::backdrops_complete_model);
@@ -112,6 +116,10 @@ inferences to avoid piling up bogus inconsistencies.
     PLUGIN_REGISTER(PLUGIN_ESTIMATE_PROPERTY_USAGE, PL::Backdrops::backdrops_estimate_property_usage);
     PLUGIN_REGISTER(PLUGIN_INTERVENE_IN_ASSERTION, PL::Backdrops::backdrops_intervene_in_assertion);
 }
+
+int PL::Backdrops::create_inference_families(void) {
+    return FALSE;
+}
 

§4. Kinds. This a kind name to do with backdrops which Inform provides special support for; it recognises the English name when defined by the Standard Rules. (So @@ -162,7 +170,7 @@ Standard Rules. (So there is no need to translate this to other languages.) } int PL::Backdrops::object_is_scenery(instance *I) { - if (World::Inferences::get_EO_state(Instances::as_subject(I), P_scenery) > 0) + if (Inferences::get_EO_state(Instances::as_subject(I), P_scenery) > 0) return TRUE; return FALSE; } @@ -180,10 +188,6 @@ Standard Rules. (So there is no need to translate this to other languages.)

 int PL::Backdrops::backdrops_log_inference_type(int it) {
-    switch(it) {
-        case FOUND_IN_INF: LOG("FOUND_IN_INF"); return TRUE;
-        case FOUND_EVERYWHERE_INF: LOG("FOUND_EVERYWHERE_INF"); return TRUE;
-    }
     return FALSE;
 }
 
@@ -210,9 +214,9 @@ and text like (relation == R_regional_containment))) { inference_subject *bd = Instances::as_subject(I1); inference_subject *loc = Instances::as_subject(I0); - World::Inferences::draw(PART_OF_INF, bd, IMPOSSIBLE_CE, loc, NULL); - World::Inferences::draw(IS_ROOM_INF, bd, IMPOSSIBLE_CE, NULL, NULL); - World::Inferences::draw(FOUND_IN_INF, bd, CERTAIN_CE, loc, loc); + Inferences::draw(PART_OF_INF, bd, IMPOSSIBLE_CE, loc, NULL); + Inferences::draw(IS_ROOM_INF, bd, IMPOSSIBLE_CE, NULL, NULL); + Inferences::draw(FOUND_IN_INF, bd, CERTAIN_CE, loc, loc); return TRUE; } @@ -225,12 +229,12 @@ and text like
define LOOP_OVER_BACKDROPS_IN(B, P, I)
     LOOP_OVER_INSTANCES(B, K_object)
         if (PL::Backdrops::object_is_a_backdrop(B))
-            POSITIVE_KNOWLEDGE_LOOP(I, Instances::as_subject(B), FOUND_IN_INF)
-                if (World::Inferences::get_reference_as_object(I) == P)
+            POSITIVE_KNOWLEDGE_LOOP(I, Instances::as_subject(B), FOUND_IN_INF)
+                if (Inferences::get_reference_as_object(I) == P)
 define LOOP_OVER_BACKDROPS_EVERYWHERE(B, I)
     LOOP_OVER_INSTANCES(B, K_object)
         if (PL::Backdrops::object_is_a_backdrop(B))
-            POSITIVE_KNOWLEDGE_LOOP(I, Instances::as_subject(B), FOUND_EVERYWHERE_INF)
+            POSITIVE_KNOWLEDGE_LOOP(I, Instances::as_subject(B), FOUND_EVERYWHERE_INF)
 

§13. Since backdrops are contained using different mechanisms, the following (which does nothing if Backdrops isn't plugged in) adds backdrop contents to @@ -327,7 +331,7 @@ been asserted true: "is a vehicle which is everywhere.' is not."); return; } - World::Inferences::draw(FOUND_EVERYWHERE_INF, + Inferences::draw(FOUND_EVERYWHERE_INF, Instances::as_subject(I), prevailing_mood, NULL, NULL); }

@@ -336,7 +340,7 @@ been asserted true:
 int PL::Backdrops::backdrops_complete_model(int stage) {
-    if (stage == 2) {
+    if (stage == WORLD_STAGE_II) {
         P_absent = Properties::EitherOr::new_nameless(L"absent");
         Properties::EitherOr::implement_as_attribute(P_absent, TRUE);
         instance *I;
@@ -362,7 +366,7 @@ been asserted true:
 
 
     inference *inf;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_EVERYWHERE_INF) {
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_EVERYWHERE_INF) {
         FOUNDIN = Hierarchy::find(FOUND_EVERYWHERE_HL);
         break;
     }
@@ -373,8 +377,8 @@ been asserted true:
 
 
     inference *inf;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) {
-        instance *loc = World::Inferences::get_reference_as_object(inf);
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) {
+        instance *loc = Inferences::get_reference_as_object(inf);
         if ((K_region) && (Instances::of_kind(loc, K_region))) region_count++;
         else room_count++;
     }
@@ -388,8 +392,8 @@ been asserted true:
     FOUNDIN = Hierarchy::make_iname_in(INLINE_PROPERTY_HL, PR);
     packaging_state save = Emit::named_array_begin(FOUNDIN, K_value);
     inference *inf;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF)
-        Emit::array_iname_entry(RTInstances::iname(World::Inferences::get_reference_as_object(inf)));
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF)
+        Emit::array_iname_entry(RTInstances::iname(Inferences::get_reference_as_object(inf)));
     Emit::array_end(save);
     Produce::annotate_i(FOUNDIN, INLINE_ARRAY_IANN, 1);
 
@@ -446,8 +450,8 @@ code, derived from the old I6 library, requires packaging_state save = Routines::begin(notice->found_in_routine_iname); inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) { - instance *loc = World::Inferences::get_reference_as_object(inf); + POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) { + instance *loc = Inferences::get_reference_as_object(inf); Produce::inv_primitive(Emit::tree(), IF_BIP); Produce::down(Emit::tree()); if ((K_region) && (Instances::of_kind(loc, K_region))) { diff --git a/docs/if-module/3-dvc.html b/docs/if-module/3-dvc.html index 056a7c11a..09cb72169 100644 --- a/docs/if-module/3-dvc.html +++ b/docs/if-module/3-dvc.html @@ -110,7 +110,7 @@ age of Inter we want to avoid that sort of tomfoolery.
 int PL::Devices::IF_complete_model(int stage) {
-    if (stage == 3) {
+    if (stage == WORLD_STAGE_III) {
         P_switchable = Properties::EitherOr::new_nameless(L"switchable");
         Properties::EitherOr::implement_as_attribute(P_switchable, TRUE);
         instance *I;
diff --git a/docs/if-module/3-em.html b/docs/if-module/3-em.html
index 6ace2d50b..a7be33723 100644
--- a/docs/if-module/3-em.html
+++ b/docs/if-module/3-em.html
@@ -1400,7 +1400,7 @@ on — come from here.
 
 
     if (P_printed_name) {
-        parse_node *V = World::Inferences::get_prop_state_at(
+        parse_node *V = Inferences::get_prop_state_at(
             Instances::as_subject(I), P_printed_name, NULL);
         if ((Rvalues::is_CONSTANT_of_kind(V, K_text)) &&
             (Wordings::nonempty(Node::get_text(V)))) {
diff --git a/docs/if-module/3-mcr.html b/docs/if-module/3-mcr.html
index 2b7c74100..6ab4b341f 100644
--- a/docs/if-module/3-mcr.html
+++ b/docs/if-module/3-mcr.html
@@ -355,10 +355,10 @@ such.
     inference_subject *infs_from = infs0;
     inference_subject *infs_to = infs1;
 
-    World::Inferences::draw(IS_ROOM_INF, infs_from, prevailing_mood, NULL, NULL);
+    Inferences::draw(IS_ROOM_INF, infs_from, prevailing_mood, NULL, NULL);
     if ((prevailing_mood >= 0) && (infs_to))
-        World::Inferences::draw(IS_ROOM_INF, infs_to, LIKELY_CE, NULL, NULL);
-    World::Inferences::draw(DIRECTION_INF, infs_from, prevailing_mood,
+        Inferences::draw(IS_ROOM_INF, infs_to, LIKELY_CE, NULL, NULL);
+    Inferences::draw(DIRECTION_INF, infs_from, prevailing_mood,
         infs_to, o_dir?(Instances::as_subject(o_dir)):NULL);
 
     return TRUE;
diff --git a/docs/if-module/3-prs.html b/docs/if-module/3-prs.html
index 2c3a24a8f..a9a8da411 100644
--- a/docs/if-module/3-prs.html
+++ b/docs/if-module/3-prs.html
@@ -94,7 +94,7 @@ sort of tomfoolery.
 
 
 int PL::Persons::IF_complete_model(int stage) {
-    if ((stage == 3) && (K_person)) {
+    if ((stage == WORLD_STAGE_III) && (K_person)) {
         P_animate = Properties::EitherOr::new_nameless(L"animate");
         Properties::EitherOr::implement_as_attribute(P_animate, TRUE);
         P_before = Properties::Valued::new_nameless(I"before", K_value);
diff --git a/docs/if-module/3-rgn.html b/docs/if-module/3-rgn.html
index eb4f77cf8..e5c2b0c4b 100644
--- a/docs/if-module/3-rgn.html
+++ b/docs/if-module/3-rgn.html
@@ -371,7 +371,7 @@ to participate in nonspatial relations.)
 
     inference_subject *inner = Instances::as_subject(I1);
     inference_subject *outer = Instances::as_subject(I0);
-    World::Inferences::draw(PARENTAGE_INF, inner, CERTAIN_CE, outer, NULL);
+    Inferences::draw(PARENTAGE_INF, inner, CERTAIN_CE, outer, NULL);
 
  • This code is used in §16.

§16.3. Anything in or part of a region is necessarily a room, if it isn't known @@ -385,7 +385,7 @@ to be a region already: inference_subject *rm = Instances::as_subject(I1); parse_node *spec = Rvalues::from_instance(I0); Propositions::Abstract::assert_kind_of_instance(I1, K_room); - World::Inferences::draw_property(rm, P_map_region, spec); + PropertyInferences::draw(rm, P_map_region, spec);

  • This code is used in §16.

§17. Note that because we use regular PARENTAGE_INF inferences to remember @@ -406,8 +406,8 @@ region is either the next broadest region containing it, or else int PL::Regions::regions_complete_model(int stage) { - if (stage == 2) Assert map-region properties of rooms and regions18.1; - if (stage == 3) Assert regional-found-in properties of regions18.2; + if (stage == WORLD_STAGE_II) Assert map-region properties of rooms and regions18.1; + if (stage == WORLD_STAGE_III) Assert regional-found-in properties of regions18.2; return FALSE; }

@@ -427,7 +427,7 @@ region is either the next broadest region containing it, or else if ((Instances::of_kind(I, K_room)) || (Instances::of_kind(I, K_region))) { parse_node *where = NULL; - parse_node *val = World::Inferences::get_prop_state_at( + parse_node *val = Inferences::get_prop_state_at( Instances::as_subject(I), P_map_region, &where); if (val) { instance *reg = diff --git a/docs/if-module/3-sm.html b/docs/if-module/3-sm.html index c473e6cc1..3abeb0830 100644 --- a/docs/if-module/3-sm.html +++ b/docs/if-module/3-sm.html @@ -126,12 +126,13 @@ carries, wears, supports or incorporates it. indications of spatial structure:

-
define IS_ROOM_INF 50  is O a room?
-define CONTAINS_THINGS_INF 51  does O contain things?
-define PARENTAGE_INF 52  where is O located?
-define PARENTAGE_HERE_INF 53  located vaguely as "here"?
-define PARENTAGE_NOWHERE_INF 54  located vaguely as "nowhere"?
-define PART_OF_INF 55  is O a part of another object?
+
+inference_family *IS_ROOM_INF = NULL;  50 is O a room?
+inference_family *CONTAINS_THINGS_INF = NULL;  51 does O contain things?
+inference_family *PARENTAGE_INF = NULL;  52 where is O located?
+inference_family *PARENTAGE_HERE_INF = NULL;  53 located vaguely as "here"?
+inference_family *PARENTAGE_NOWHERE_INF = NULL;  54 located vaguely as "nowhere"?
+inference_family *PART_OF_INF = NULL;  55 is O a part of another object?
 

§4. The Spatial plugin also needs to know about a considerable number of special kinds and properties: @@ -174,6 +175,16 @@ timing issue to get around (see below).

 void PL::Spatial::start(void) {
+    IS_ROOM_INF = Inferences::new_family(I"IS_ROOM_INF", CI_DIFFER_IN_INFS1);
+    METHOD_ADD(IS_ROOM_INF, EXPLAIN_CONTRADICTION_INF_MTID, PL::Spatial::is_room_explain_contradiction);
+    CONTAINS_THINGS_INF = Inferences::new_family(I"CONTAINS_THINGS_INF", CI_DIFFER_IN_INFS1);
+    PARENTAGE_INF = Inferences::new_family(I"PARENTAGE_INF", CI_DIFFER_IN_INFS1);
+    METHOD_ADD(PARENTAGE_INF, EXPLAIN_CONTRADICTION_INF_MTID, PL::Spatial::parentage_explain_contradiction);
+    PARENTAGE_HERE_INF = Inferences::new_family(I"PARENTAGE_HERE_INF", CI_DIFFER_IN_INFS1);
+    PARENTAGE_NOWHERE_INF = Inferences::new_family(I"PARENTAGE_NOWHERE_INF", CI_DIFFER_IN_INFS1);
+    PART_OF_INF = Inferences::new_family(I"PART_OF_INF", CI_DIFFER_IN_INFS1);
+
+    PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Spatial::create_inference_families);
     PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCES, PL::Spatial::create_inference_subjects);
     PLUGIN_REGISTER(PLUGIN_NEW_BASE_KIND_NOTIFY, PL::Spatial::spatial_new_base_kind_notify);
     PLUGIN_REGISTER(PLUGIN_ACT_ON_SPECIAL_NPS, PL::Spatial::spatial_act_on_special_NPs);
@@ -191,6 +202,43 @@ timing issue to get around (see below).
     PLUGIN_REGISTER(PLUGIN_ADD_TO_WORLD_INDEX, PL::Spatial::spatial_add_to_World_index);
     PLUGIN_REGISTER(PLUGIN_INTERVENE_IN_ASSERTION, PL::Spatial::spatial_intervene_in_assertion);
 }
+
+int PL::Spatial::is_room_explain_contradiction(inference_family *f, inference *A,
+    inference *B, int similarity, inference_subject *subj) {
+    StandardProblems::two_sentences_problem(_p_(PM_WhenIsARoomNotARoom),
+        A->inferred_from,
+        "this looks like a contradiction",
+        "because apparently something would have to be both a room and not a "
+        "room at the same time.");
+    return TRUE;
+}
+
+int PL::Spatial::parentage_explain_contradiction(inference_family *f, inference *A,
+    inference *B, int similarity, inference_subject *subj) {
+    if (Inferences::get_reference_as_object(A) != Inferences::get_reference_as_object(B)) {
+        Problems::quote_source(1, Inferences::where_inferred(A));
+        Problems::quote_source(2, Inferences::where_inferred(B));
+        Problems::quote_subject(3, subj);
+        Problems::quote_object(4, Inferences::get_reference_as_object(A));
+        Problems::quote_object(5, Inferences::get_reference_as_object(B));
+        StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_SpatialContradiction));
+        Problems::issue_problem_segment(
+            "You wrote %1, but also %2: that seems to be saying that the same "
+            "object (%3) must be in two different places (%4 and %5). This "
+            "looks like a contradiction. %P"
+            "This sometimes happens as a result of a sentence like 'Every person "
+            "carries a bag', when Inform doesn't know 'bag' as the name of any "
+            "kind - so that it makes only a single thing called 'bag', and then "
+            "the sentence looks as if it says everyone is carrying the same bag.");
+        Problems::issue_problem_end();
+        return TRUE;
+    }
+    return FALSE;
+}
+
+int PL::Spatial::create_inference_families(void) {
+    return FALSE;
+}
 

§7. In talking about some of the fundamental spatial domains we potentially have a vicious circle, because @@ -263,35 +311,27 @@ multiple PARENTAGE_INF

 int PL::Spatial::spatial_log_inference_type(int it) {
-    switch(it) {
-        case CONTAINS_THINGS_INF: LOG("CONTAINS_THINGS_INF"); return TRUE;
-        case IS_ROOM_INF: LOG("IS_ROOM_INF"); return TRUE;
-        case PARENTAGE_HERE_INF: LOG("PARENTAGE_HERE_INF"); return TRUE;
-        case PARENTAGE_NOWHERE_INF: LOG("PARENTAGE_NOWHERE_INF"); return TRUE;
-        case PARENTAGE_INF: LOG("PARENTAGE_INF"); return TRUE;
-        case PART_OF_INF: LOG("PART_OF_INF"); return TRUE;
-    }
     return FALSE;
 }
 
 int PL::Spatial::spatial_inferences_contradict(inference *A, inference *B, int similarity) {
-    if ((World::Inferences::get_inference_type(A) == PARENTAGE_INF) &&
-        (World::Inferences::get_reference_as_object(A) !=
-            World::Inferences::get_reference_as_object(B)))
+    if ((Inferences::get_inference_type(A) == PARENTAGE_INF) &&
+        (Inferences::get_reference_as_object(A) !=
+            Inferences::get_reference_as_object(B)))
         return TRUE;
     return FALSE;
 }
 
 int PL::Spatial::spatial_explain_contradiction(inference *A, inference *B, int similarity,
     inference_subject *subj) {
-    if ((World::Inferences::get_inference_type(A) == PARENTAGE_INF) &&
-        (World::Inferences::get_reference_as_object(A) !=
-            World::Inferences::get_reference_as_object(B))) {
-        Problems::quote_source(1, World::Inferences::where_inferred(A));
-        Problems::quote_source(2, World::Inferences::where_inferred(B));
+	if ((Inferences::get_inference_type(A) == PARENTAGE_INF) &&
+        (Inferences::get_reference_as_object(A) !=
+            Inferences::get_reference_as_object(B))) {
+        Problems::quote_source(1, Inferences::where_inferred(A));
+        Problems::quote_source(2, Inferences::where_inferred(B));
         Problems::quote_subject(3, subj);
-        Problems::quote_object(4, World::Inferences::get_reference_as_object(A));
-        Problems::quote_object(5, World::Inferences::get_reference_as_object(B));
+        Problems::quote_object(4, Inferences::get_reference_as_object(A));
+        Problems::quote_object(5, Inferences::get_reference_as_object(B));
         StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_SpatialContradiction));
         Problems::issue_problem_segment(
             "You wrote %1, but also %2: that seems to be saying that the same "
@@ -304,6 +344,7 @@ multiple PARENTAGE_INF
         Problems::issue_problem_end();
         return TRUE;
     }
+*/
     return FALSE;
 }
 
@@ -354,7 +395,7 @@ if it turns out to be news, we infer kind *kw = Instances::to_kind(I); if ((!(Kinds::Behaviour::is_object_of_kind(kw, K_room))) && (Kinds::Behaviour::is_object_of_kind(k, K_room))) - World::Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, + Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, NULL, NULL); return FALSE; } @@ -470,9 +511,9 @@ appearance". instance *I = InstanceSubjects::to_object_instance(infs); if ((I) && (PL::Backdrops::object_is_scenery(I))) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); - if (((prn) && (World::Inferences::get_certainty(inf) > 0)) && + KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *prn = PropertyInferences::get_property(inf); + if (((prn) && (Inferences::get_certainty(inf) > 0)) && (prn == P_description)) { Produce a problem for doubly described scenery19.1; return TRUE; @@ -625,9 +666,9 @@ with certainty read void PL::Spatial::infer_presence_here(instance *I) { inference_subject *infs = Instances::as_subject(I); inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, infs, PARENTAGE_HERE_INF) { + POSITIVE_KNOWLEDGE_LOOP(inf, infs, PARENTAGE_HERE_INF) { StandardProblems::contradiction_problem(_p_(PM_DuplicateHere), - World::Inferences::where_inferred(inf), + Inferences::where_inferred(inf), current_sentence, I, "can only be said to be 'here' once", @@ -635,9 +676,9 @@ with certainty read "since 'here' can mean different things in different sentences."); } - World::Inferences::draw(PARENTAGE_HERE_INF, infs, CERTAIN_CE, + Inferences::draw(PARENTAGE_HERE_INF, infs, CERTAIN_CE, Anaphora::get_current_subject(), NULL); - World::Inferences::draw(IS_ROOM_INF, infs, IMPOSSIBLE_CE, NULL, NULL); + Inferences::draw(IS_ROOM_INF, infs, IMPOSSIBLE_CE, NULL, NULL); }

§27. Similarly: @@ -645,9 +686,9 @@ with certainty read

 void PL::Spatial::infer_presence_nowhere(instance *I) {
-    World::Inferences::draw(PARENTAGE_NOWHERE_INF,
+    Inferences::draw(PARENTAGE_NOWHERE_INF,
         Instances::as_subject(I), CERTAIN_CE, NULL, NULL);
-    World::Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), IMPOSSIBLE_CE,
+    Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), IMPOSSIBLE_CE,
         NULL, NULL);
 }
 
@@ -776,17 +817,17 @@ probably suggested by inferences.
     inference *inf;
-    KNOWLEDGE_LOOP(inf, Instances::as_subject(I), CONTAINS_THINGS_INF)
-        if (World::Inferences::get_certainty(inf) > geography_certainty) {
+    KNOWLEDGE_LOOP(inf, Instances::as_subject(I), CONTAINS_THINGS_INF)
+        if (Inferences::get_certainty(inf) > geography_certainty) {
             geography_choice = K_container;
-            geography_certainty = World::Inferences::get_certainty(inf);
+            geography_certainty = Inferences::get_certainty(inf);
             geography_inference = inf;
         }
-    KNOWLEDGE_LOOP(inf, Instances::as_subject(I), IS_ROOM_INF)
-        if ((World::Inferences::get_certainty(inf) > UNKNOWN_CE) ||
-            (World::Inferences::get_certainty(inf) > geography_certainty)) {
+    KNOWLEDGE_LOOP(inf, Instances::as_subject(I), IS_ROOM_INF)
+        if ((Inferences::get_certainty(inf) > UNKNOWN_CE) ||
+            (Inferences::get_certainty(inf) > geography_certainty)) {
             geography_choice = K_room;
-            geography_certainty = World::Inferences::get_certainty(inf);
+            geography_certainty = Inferences::get_certainty(inf);
             geography_inference = inf;
         }
 
@@ -845,7 +886,7 @@ when it's legitimately a door.
     StandardProblems::contradiction_problem(_p_(PM_PersonContaining),
         sentence_setting_kind,
-        World::Inferences::where_inferred(geography_inference), I,
+        Inferences::where_inferred(geography_inference), I,
         "cannot contain or support things like something inanimate",
         "which is what you are implying. Instead, people must carry or wear them: "
         "so 'The briefcase is in Daphne.' is disallowed, but 'The briefcase is "
@@ -861,7 +902,7 @@ Inform spatial model:
 
 
     StandardProblems::contradiction_problem(_p_(PM_CantContainAndSupport),
-        decider, World::Inferences::where_inferred(geography_inference), I,
+        decider, Inferences::where_inferred(geography_inference), I,
         "cannot both contain things and support things",
         "which is what you're implying here. If you need both, the easiest way is "
         "to make it either a supporter with a container attached or vice versa. "
@@ -876,7 +917,7 @@ Inform spatial model:
 
     StandardProblems::contradiction_problem(_p_(PM_BothRoomAndSupporter),
         decider,
-        World::Inferences::where_inferred(geography_inference), I,
+        Inferences::where_inferred(geography_inference), I,
         "would need to have two different and incompatible kinds to make both "
         "sentences true",
         "and this is a contradiction.");
@@ -907,7 +948,7 @@ provide access routines to read and write:
     if (to == NULL) internal_error("set progenitor of nothing");
     SPATIAL_DATA(of)->progenitor = to;
     SPATIAL_DATA(of)->progenitor_set_at =
-        (reason)?World::Inferences::where_inferred(reason):NULL;
+        (reason)?Inferences::where_inferred(reason):NULL;
 }
 

§31. This is used for error recovery only. @@ -949,7 +990,7 @@ the kind of here-objects. LOOP_OVER_INSTANCES(I, K_object) { SPATIAL_DATA(I)->here_flag = FALSE; inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_HERE_INF) + POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_HERE_INF) SPATIAL_DATA(I)->here_flag = TRUE; }

@@ -993,7 +1034,7 @@ object under investigation. Find the inference which will decide the progenitor32.3.1; if (parent_setting_inference) { instance *whereabouts = - World::Inferences::get_reference_as_object(parent_setting_inference); + Inferences::get_reference_as_object(parent_setting_inference); if (SPATIAL_DATA(I)->here_flag) Find the whereabouts of something here32.3.2; if (whereabouts) { PL::Spatial::set_progenitor(I, whereabouts, parent_setting_inference); @@ -1008,11 +1049,11 @@ object under investigation.
     inference *inf;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_NOWHERE_INF)
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_NOWHERE_INF)
         Make this the determining inference32.3.1.1;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_HERE_INF)
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_HERE_INF)
         Make this the determining inference32.3.1.1;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_INF)
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PARENTAGE_INF)
         Make this the determining inference32.3.1.1;
 
@@ -1022,8 +1063,8 @@ object under investigation.
     if (parent_setting_inference) {
         StandardProblems::contradiction_problem(_p_(PM_DuplicateParentage),
-            World::Inferences::where_inferred(parent_setting_inference),
-            World::Inferences::where_inferred(inf),
+            Inferences::where_inferred(parent_setting_inference),
+            Inferences::where_inferred(inf),
             I,
             "can only be given its position once",
             "in a single assertion sentence.");
@@ -1038,7 +1079,7 @@ object under investigation.
     if (PL::Spatial::object_is_a_room(whereabouts) == FALSE) whereabouts = NULL;
     if (whereabouts == NULL) {
         parse_node *here_sentence =
-            World::Inferences::where_inferred(parent_setting_inference);
+            Inferences::where_inferred(parent_setting_inference);
         Set the whereabouts to the last discussed room prior to this inference being drawn32.3.2.1;
         if (whereabouts == NULL) {
             current_sentence = here_sentence;
@@ -1069,7 +1110,7 @@ when it finishes this will be set to the most recently mentioned.
 
 
     inference *inf;
-    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PART_OF_INF) {
+    POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PART_OF_INF) {
         if ((PL::Spatial::object_is_a_room(I)) || (PL::Map::object_is_a_door(I))) {
             StandardProblems::object_problem(_p_(PM_RoomOrDoorAsPart),
                 I,
@@ -1408,8 +1449,8 @@ as a value for description    if (K_room) {
         inference *inf;
         int desc_seen = FALSE;
-        POSITIVE_KNOWLEDGE_LOOP(inf, KindSubjects::from_kind(K_room), PROPERTY_INF)
-            if (World::Inferences::get_property(inf) == P_description)
+        POSITIVE_KNOWLEDGE_LOOP(inf, KindSubjects::from_kind(K_room), property_inf)
+            if (PropertyInferences::get_property(inf) == P_description)
                 desc_seen = TRUE;
         if (desc_seen == FALSE) {
             TEMPORARY_TEXT(val)
@@ -1583,8 +1624,8 @@ empty.
         if (Instances::of_kind(P, K_person)) rel = "carried";
         if (SPATIAL_DATA(I)->part_flag) rel = "part";
         inference *inf;
-        POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PROPERTY_INF)
-            if (World::Inferences::get_property(inf) == P_worn)
+        POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), property_inf)
+            if (PropertyInferences::get_property(inf) == P_worn)
                 rel = "worn";
     }
     if (rel) WRITE("<i>%s</i> ", rel);
@@ -1649,8 +1690,8 @@ it already turns up under its owner.
             if (Instances::of_kind(P, K_person)) rel = "carried by";
             if (SPATIAL_DATA(O)->part_flag) rel = "part of";
             inference *inf;
-            POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(O), PROPERTY_INF)
-                if (World::Inferences::get_property(inf) == P_worn)
+            POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(O), property_inf)
+                if (PropertyInferences::get_property(inf) == P_worn)
                     rel = "worn by";
             WRITE("%s ", rel);
             IXInstances::index_name(OUT, P);
diff --git a/docs/if-module/3-sm2.html b/docs/if-module/3-sm2.html
index d44e76b29..2b56dc639 100644
--- a/docs/if-module/3-sm2.html
+++ b/docs/if-module/3-sm2.html
@@ -3150,7 +3150,7 @@ can make use of the following:
     if (Instances::of_kind(R, K_door)) {
         wording W = Instances::get_name(R, FALSE);
         LOG("%+W is a door.\n", W);
-        parse_node *S = World::Inferences::get_prop_state(
+        parse_node *S = Inferences::get_prop_state(
             Instances::as_subject(R), P_other_side);
         instance *X = Rvalues::to_object_instance(S);
         if (X) {
diff --git a/docs/if-module/3-sr.html b/docs/if-module/3-sr.html
index 4c48892eb..768d9f910 100644
--- a/docs/if-module/3-sr.html
+++ b/docs/if-module/3-sr.html
@@ -345,13 +345,13 @@ way which isn't symmetrical between the two, and this way round is cleanest.
 
     inference_subject *item = Instances::as_subject(I1);
     inference_subject *loc = Instances::as_subject(I0);
-    World::Inferences::draw(PART_OF_INF, item,
+    Inferences::draw(PART_OF_INF, item,
         (bp == R_incorporation)?CERTAIN_CE:IMPOSSIBLE_CE,
         loc, NULL);
     if (bp == R_containment)
-        World::Inferences::draw(CONTAINS_THINGS_INF, loc, CERTAIN_CE, item, NULL);
-    World::Inferences::draw(PARENTAGE_INF, item, CERTAIN_CE, loc, NULL);
-    World::Inferences::draw(IS_ROOM_INF, item, IMPOSSIBLE_CE, NULL, NULL);
+        Inferences::draw(CONTAINS_THINGS_INF, loc, CERTAIN_CE, item, NULL);
+    Inferences::draw(PARENTAGE_INF, item, CERTAIN_CE, loc, NULL);
+    Inferences::draw(IS_ROOM_INF, item, IMPOSSIBLE_CE, NULL, NULL);
 
  • This code is used in §4.

§4.5. If something is being worn, it needs to have the I7 either/or property @@ -366,12 +366,12 @@ special to make it work, so this doesn't seem worth the trouble.)

     inference_subject *item = Instances::as_subject(I1);
     if (P_wearable)
-        World::Inferences::draw_property(item, P_wearable, NULL);
+        PropertyInferences::draw(item, P_wearable, NULL);
     if (P_worn == NULL) {
         P_worn = Properties::EitherOr::new_nameless(L"worn");
         Properties::EitherOr::implement_as_attribute(P_worn, TRUE);
     }
-    World::Inferences::draw_property(item, P_worn, NULL);
+    PropertyInferences::draw(item, P_worn, NULL);
 
  • This code is used in §4.

§5. Compilation. We need do nothing special: these relations can be compiled from their schemas. diff --git a/docs/if-module/3-tm.html b/docs/if-module/3-tm.html index 8f15f0841..84fae690b 100644 --- a/docs/if-module/3-tm.html +++ b/docs/if-module/3-tm.html @@ -172,7 +172,8 @@ in connection with the "mapped D of" relations, it's altogether easier and makes for more legible code if we use a special inference type of our own:

-
define DIRECTION_INF 100  where do map connections from O lead?
+
+inference_family *DIRECTION_INF = NULL;  100; where do map connections from O lead?
 

§5. One useful constant:

@@ -205,6 +206,9 @@ makes for more legible code if we use a special inference type of our own:
 void PL::Map::start(void) {
+    DIRECTION_INF = Inferences::new_family(I"DIRECTION_INF", CI_DIFFER_IN_INFS1);
+
+    PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Map::create_inference_families);
     PLUGIN_REGISTER(PLUGIN_NEW_BASE_KIND_NOTIFY, PL::Map::map_new_base_kind_notify);
     PLUGIN_REGISTER(PLUGIN_NEW_SUBJECT_NOTIFY, PL::Map::map_new_subject_notify);
     PLUGIN_REGISTER(PLUGIN_SET_KIND_NOTIFY, PL::Map::map_set_kind_notify);
@@ -215,6 +219,7 @@ makes for more legible code if we use a special inference type of our own:
     PLUGIN_REGISTER(PLUGIN_ESTIMATE_PROPERTY_USAGE, PL::Map::map_estimate_property_usage);
     PLUGIN_REGISTER(PLUGIN_LOG_INFERENCE_TYPE, PL::Map::map_log_inference_type);
     PLUGIN_REGISTER(PLUGIN_INFERENCES_CONTRADICT, PL::Map::map_inferences_contradict);
+    PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Map::create_inference_families);
     PLUGIN_REGISTER(PLUGIN_COMPLETE_MODEL, PL::Map::map_complete_model);
     PLUGIN_REGISTER(PLUGIN_NEW_PROPERTY_NOTIFY, PL::Map::map_new_property_notify);
     PLUGIN_REGISTER(PLUGIN_PROPERTY_VALUE_NOTIFY, PL::Map::map_property_value_notify);
@@ -222,6 +227,10 @@ makes for more legible code if we use a special inference type of our own:
     PLUGIN_REGISTER(PLUGIN_ADD_TO_WORLD_INDEX, PL::Map::map_add_to_World_index);
     PLUGIN_REGISTER(PLUGIN_ANNOTATE_IN_WORLD_INDEX, PL::Map::map_annotate_in_World_index);
 }
+
+int PL::Map::create_inference_families(void) {
+    return FALSE;
+}
 

§8.

@@ -247,9 +256,6 @@ makes for more legible code if we use a special inference type of our own:
 int PL::Map::map_log_inference_type(int it) {
-    switch(it) {
-        case DIRECTION_INF: LOG("DIRECTION_INF"); return TRUE;
-    }
     return FALSE;
 }
 
@@ -261,11 +267,9 @@ direction — this of course is a contradiction.
 int PL::Map::map_inferences_contradict(inference *A, inference *B, int similarity) {
-    switch (World::Inferences::get_inference_type(A)) {
-        case DIRECTION_INF:
-            if (similarity == CI_DIFFER_IN_INFS1) return TRUE;
-            break;
-    }
+    if (Inferences::get_inference_type(A) == DIRECTION_INF)
+        if (similarity == CI_DIFFER_IN_INFS1)
+            return TRUE;
     return FALSE;
 }
 
@@ -472,9 +476,9 @@ quite crunchy algorithms, has the fastest possible access to the layout. } LOOP_OVER_INSTANCES(I, K_object) { inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) { + POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) { inference_subject *infs1, *infs2; - World::Inferences::get_references(inf, &infs1, &infs2); + Inferences::get_references(inf, &infs1, &infs2); instance *to = NULL, *dir = NULL; if (infs1) to = InstanceSubjects::to_object_instance(infs1); if (infs2) dir = InstanceSubjects::to_object_instance(infs2); @@ -482,7 +486,7 @@ quite crunchy algorithms, has the fastest possible access to the layout. int dn = MAP_DATA(dir)->direction_index; if ((dn >= 0) && (dn < MAX_DIRECTIONS)) { MAP_EXIT(I, dn) = to; - MAP_DATA(I)->exits_set_at[dn] = World::Inferences::where_inferred(inf); + MAP_DATA(I)->exits_set_at[dn] = Inferences::where_inferred(inf); } } } @@ -617,7 +621,7 @@ deduction is made: if (prn == P_other_side) { instance *I = Rvalues::to_object_instance(val); if (I) { - World::Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, + Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, NULL, NULL); } } @@ -636,7 +640,7 @@ one and Backdrops), and this is where they set it. if (P_found_in == NULL) P_found_in = Properties::Valued::new_nameless(I"found_in", K_value); - if (World::Inferences::get_prop_state( + if (Inferences::get_prop_state( Instances::as_subject(I), P_found_in)) internal_error("rival found_in interpretations"); Properties::Valued::assert(P_found_in, Instances::as_subject(I), @@ -651,7 +655,7 @@ and there seems little point in writing this any better.
 instance *PL::Map::get_value_of_opposite_property(instance *I) {
-    parse_node *val = World::Inferences::get_prop_state(
+    parse_node *val = Inferences::get_prop_state(
         Instances::as_subject(I), P_opposite);
     if (val) return Rvalues::to_object_instance(val);
     return NULL;
@@ -896,16 +900,16 @@ checks that various mapping impossibilities do not occur.
     instance *I;
     LOOP_OVER_INSTANCES(I, K_object) {
         inference *inf;
-        POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) {
+        POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) {
             inference_subject *infs1;
-            World::Inferences::get_references(inf, &infs1, NULL);
+            Inferences::get_references(inf, &infs1, NULL);
             instance *to = InstanceSubjects::to_object_instance(infs1);
             if ((PL::Spatial::object_is_a_room(I)) && (to) &&
                 (PL::Map::object_is_a_door(to) == FALSE) &&
                 (PL::Spatial::object_is_a_room(to) == FALSE))
                 StandardProblems::contradiction_problem(_p_(PM_BadMapCell),
                     Instances::get_creating_sentence(to),
-                    World::Inferences::where_inferred(inf), to,
+                    Inferences::where_inferred(inf), to,
                     "appears to be something which can be reached via a map "
                     "connection, but it seems to be neither a room nor a door",
                     "and these are the only possibilities allowed by Inform.");
@@ -932,33 +936,32 @@ checks that various mapping impossibilities do not occur.
             parse_node *where[3];
             where[0] = NULL; where[1] = NULL; where[2] = NULL;  to placate gcc
             inference *front_side_inf = NULL, *back_side_inf = NULL;
-            POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) {
+            POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) {
                 inference_subject *infs1, *infs2;
-                World::Inferences::get_references(inf, &infs1, &infs2);
+                Inferences::get_references(inf, &infs1, &infs2);
                 instance *to = InstanceSubjects::to_object_instance(infs1);
                 instance *dir = InstanceSubjects::to_object_instance(infs2);
                 if (to) {
                     if (connections_in == 0) {
                         MAP_DATA(I)->map_connection_a = to;
                         MAP_DATA(I)->map_direction_a = dir;
-                        where[0] = World::Inferences::where_inferred(inf);
+                        where[0] = Inferences::where_inferred(inf);
                         front_side_inf = inf;
                     }
                     if (connections_in == 1) {
                         MAP_DATA(I)->map_connection_b = to;
                         MAP_DATA(I)->map_direction_b = dir;
-                        where[1] = World::Inferences::where_inferred(inf);
+                        where[1] = Inferences::where_inferred(inf);
                         back_side_inf = inf;
                     }
                     if (connections_in == 2) {
-                        where[2] = World::Inferences::where_inferred(inf);
+                        where[2] = Inferences::where_inferred(inf);
                     }
                     connections_in++;
                 }
             }
             if ((front_side_inf) && (back_side_inf)) {
-                if (World::Inferences::get_timestamp(front_side_inf) >
-                    World::Inferences::get_timestamp(back_side_inf)) {
+                if (front_side_inf->allocation_id > back_side_inf->allocation_id) {
                     instance *X = MAP_DATA(I)->map_connection_a;
                     MAP_DATA(I)->map_connection_a = MAP_DATA(I)->map_connection_b;
                     MAP_DATA(I)->map_connection_b = X;
@@ -1018,9 +1021,9 @@ from which there's no way back.)
     LOOP_OVER_INSTANCES(I, K_object)
         if (PL::Spatial::object_is_a_room(I)) {
             inference *inf;
-            POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) {
+            POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) {
                 inference_subject *infs1;
-                World::Inferences::get_references(inf, &infs1, NULL);
+                Inferences::get_references(inf, &infs1, NULL);
                 instance *to = InstanceSubjects::to_object_instance(infs1);
                 if (PL::Map::object_is_a_door(to)) {
                     instance *exit1 = MAP_DATA(to)->map_connection_a;
@@ -1063,7 +1066,7 @@ from which there's no way back.)
         if ((PL::Map::object_is_a_door(I)) &&
             (MAP_DATA(I)->map_connection_a) &&
             (MAP_DATA(I)->map_connection_b) &&
-            (World::Inferences::get_prop_state(
+            (Inferences::get_prop_state(
                 Instances::as_subject(I), P_other_side)))
                 StandardProblems::object_problem(_p_(PM_BothWaysDoor),
                     I, "seems to be a door whose connections have been given in both "
@@ -1356,7 +1359,7 @@ why we don't need to compile 
         instance *X = A;
         if (A == Data::Objects::room_being_indexed()) X = B;
         if (X == NULL) {
-            parse_node *S = World::Inferences::get_prop_state(
+            parse_node *S = Inferences::get_prop_state(
                 Instances::as_subject(O), P_other_side);
             X = Rvalues::to_object_instance(S);
         }
diff --git a/docs/if-module/3-tm2.html b/docs/if-module/3-tm2.html
index db61c056b..d242cba2b 100644
--- a/docs/if-module/3-tm2.html
+++ b/docs/if-module/3-tm2.html
@@ -225,7 +225,7 @@ fact, end.
     Index::anchor_numbered(OUT, sc->allocation_id);
     WRITE("<b>The <i>%+W</i> scene</b>", PL::Scenes::get_name(sc));
     Index::link(OUT, Wordings::first_wn(Node::get_text(sc->scene_declared_at)));
-    if (World::Inferences::get_EO_state(
+    if (Inferences::get_EO_state(
         Instances::as_subject(sc->as_instance), P_recurring) > 0)
         WRITE("&nbsp;&nbsp;<i>recurring</i>");
     HTML_CLOSE("p");
@@ -417,7 +417,7 @@ on the initial call when dept
 
 
     inference_subject *subj = Instances::as_subject(sc->as_instance);
-    if (World::Inferences::get_EO_state(subj, P_recurring) > UNKNOWN_CE)
+    if (Inferences::get_EO_state(subj, P_recurring) > UNKNOWN_CE)
         PL::Scenes::Index::scene_icon_append(OUT, "Recurring");
 
  • This code is used in §2.
diff --git a/docs/if-module/3-tnt.html b/docs/if-module/3-tnt.html index 17b939d6d..36510d545 100644 --- a/docs/if-module/3-tnt.html +++ b/docs/if-module/3-tnt.html @@ -205,9 +205,9 @@ a room called the Counting House"). void PL::Naming::transfer_details(inference_subject *from, inference_subject *to) { instance *wto = InstanceSubjects::to_object_instance(to); if (wto) { - if (World::Inferences::get_EO_state(from, P_proper_named) > 0) + if (Inferences::get_EO_state(from, P_proper_named) > 0) PL::Naming::now_has_proper_name(to); - parse_node *art = World::Inferences::get_prop_state(from, P_article); + parse_node *art = Inferences::get_prop_state(from, P_article); if (art) Properties::Valued::assert(P_article, to, art, LIKELY_CE); } } @@ -224,7 +224,7 @@ we do here is provide its state on request.
 int PL::Naming::object_is_privately_named(instance *I) {
-    int certainty = World::Inferences::get_EO_state(Instances::as_subject(I), P_privately_named);
+    int certainty = Inferences::get_EO_state(Instances::as_subject(I), P_privately_named);
     if (certainty > 0) return TRUE;
     if (certainty < 0) return FALSE;
     return NOT_APPLICABLE;
@@ -236,7 +236,7 @@ to fill in the naming details for objects, so here goes.
 
 
 int PL::Naming::naming_complete_model(int stage) {
-    if (stage == 3) Add naming properties implicit from context10.1;
+    if (stage == WORLD_STAGE_III) Add naming properties implicit from context10.1;
     return FALSE;
 }
 
@@ -369,7 +369,7 @@ actually means it's rarely needed.) if (this_is_named_for_something_with_a_printed_name) { Compose the I6 cap-short-name as a routine dynamically using its owner's cap-short-name10.1.2.2.2 } else { - if ((World::Inferences::get_EO_state(subj, P_proper_named) > 0) + if ((Inferences::get_EO_state(subj, P_proper_named) > 0) && (begins_with_lower_case)) Compose the I6 cap-short-name as a piece of text10.1.2.2.1 else set_csn = FALSE; @@ -456,7 +456,7 @@ together in lists.
     if ((Kinds::Behaviour::is_object_of_kind(K, K_room) == FALSE) &&
         (Kinds::eq(K, K_thing) == FALSE) &&
-        (World::Inferences::get_prop_state_without_inheritance(
+        (Inferences::get_prop_state_without_inheritance(
             subj, P_printed_plural_name, NULL) == NULL)) {
         if (Wordings::nonempty(PW)) {
             text_stream *PROP = Str::new();
@@ -474,7 +474,7 @@ together in lists.
 

-    parse_node *spec = World::Inferences::get_prop_state(subj, P_grammatical_gender);
+    parse_node *spec = Inferences::get_prop_state(subj, P_grammatical_gender);
     if (spec) {
         int g = Annotations::read_int(spec, constant_enumeration_ANNOT);
         switch (g) {
@@ -506,9 +506,9 @@ after Y or vice versa.)
     inference_subject *check;
     for (check = subj; check; check = InferenceSubjects::narrowest_broader_subject(check)) {
         inference *inf;
-        POSITIVE_KNOWLEDGE_LOOP(inf, check, PROPERTY_INF)
-            if (World::Inferences::added_in_construction(inf) == FALSE)
-                if (World::Inferences::get_property(inf) == P_printed_name)
+        POSITIVE_KNOWLEDGE_LOOP(inf, check, property_inf)
+            if (Inferences::during_stage(inf) == 0)
+                if (PropertyInferences::get_property(inf) == P_printed_name)
                     return TRUE;
     }
     return FALSE;
@@ -658,7 +658,7 @@ this because we need access to it very quickly when parsing text substitutions.)
     if (L->adaptive_person >= 0) return L->adaptive_person;
     if ((L->adaptive_person == -1) && (P_adaptive_text_viewpoint)) {
         instance *I = L->nl_instance;
-        parse_node *val = World::Inferences::get_prop_state(
+        parse_node *val = Inferences::get_prop_state(
             Instances::as_subject(I), P_adaptive_text_viewpoint);
         if (Node::is(val, CONSTANT_NT)) {
             instance *V = Node::get_constant_instance(val);
diff --git a/docs/if-module/3-tp.html b/docs/if-module/3-tp.html
index d9e024439..22ab276c0 100644
--- a/docs/if-module/3-tp.html
+++ b/docs/if-module/3-tp.html
@@ -372,12 +372,12 @@ we assume he is freestanding in the earliest defined room.
 
 
 int PL::Player::player_complete_model(int stage) {
-    if ((stage == 3) && (I_yourself)) {
+    if ((stage == WORLD_STAGE_III) && (I_yourself)) {
         P_saved_short_name = Properties::Valued::new_nameless(I"saved_short_name", K_text);
         Properties::Valued::assert(P_saved_short_name, Instances::as_subject(I_yourself),
             Rvalues::from_unescaped_wording(Feeds::feed_text(I"yourself")), CERTAIN_CE);
     }
-    if (stage == 4) {
+    if (stage == WORLD_STAGE_IV) {
         Set the start room to the earliest room defined in the source text11.1;
         If the start room is still null, there's no room, so issue a problem11.2;
         Otherwise see if the player has explicitly been placed in the model world11.3;
@@ -441,7 +441,7 @@ will do. But otherwise:
             }
             inference *inf;
             POSITIVE_KNOWLEDGE_LOOP(inf,
-                Instances::as_subject(player_character_object), PART_OF_INF) {
+                Instances::as_subject(player_character_object), PART_OF_INF) {
                 StandardProblems::object_problem(_p_(PM_PlayerIsPart),
                     start_object,
                     "seems to have the player attached as a component part",
diff --git a/docs/if-module/5-gp.html b/docs/if-module/5-gp.html
index 78cc6ac40..fa0c370f5 100644
--- a/docs/if-module/5-gp.html
+++ b/docs/if-module/5-gp.html
@@ -217,7 +217,7 @@ for parsing:
 
 
 int PL::Parsing::Visibility::parsing_complete_model(int stage) {
-    if (stage == 5) {
+    if (stage == WORLD_STAGE_V) {
         instance *I;
         P_name = Properties::Valued::new_nameless(I"name", K_text);
         Hierarchy::make_available(Emit::tree(), PL::Parsing::Visibility::name_name());
diff --git a/docs/index-module/2-ipw.html b/docs/index-module/2-ipw.html
index 18b0b2f0f..5e8483c06 100644
--- a/docs/index-module/2-ipw.html
+++ b/docs/index-module/2-ipw.html
@@ -423,8 +423,8 @@ table of Kinds.
 
 
     HTML::open_indented_p(OUT, depth, "tight");
-    if (I) World::Inferences::index(OUT, Instances::as_subject(I), TRUE);
-    else World::Inferences::index(OUT, KindSubjects::from_kind(K), TRUE);
+    if (I) Inferences::index(OUT, Instances::as_subject(I), TRUE);
+    else Inferences::index(OUT, KindSubjects::from_kind(K), TRUE);
     if (K) {
         HTML_CLOSE("p");
         Data::Objects::index_instances(OUT, K, depth);
@@ -462,7 +462,7 @@ table of Kinds.
 

-    World::Inferences::index_specific(OUT, Instances::as_subject(I));
+    Inferences::index_specific(OUT, Instances::as_subject(I));
 
  • This code is used in §3.

§4.

diff --git a/docs/index-module/2-ki.html b/docs/index-module/2-ki.html index 380ee00c2..9831adef1 100644 --- a/docs/index-module/2-ki.html +++ b/docs/index-module/2-ki.html @@ -372,7 +372,7 @@ is made, so that the following sentence can't have an empty list in it. WRITE("%S", explanation); HTML_TAG("br"); } - World::Inferences::index(OUT, KindSubjects::from_kind(K), FALSE); + Inferences::index(OUT, KindSubjects::from_kind(K), FALSE);
  • This code is used in §1.

§1.12. Explain about covariance and contravariance1.12 = diff --git a/docs/knowledge-module/1-ap.html b/docs/knowledge-module/1-ap.html index c7722b82a..bbaaad220 100644 --- a/docs/knowledge-module/1-ap.html +++ b/docs/knowledge-module/1-ap.html @@ -358,19 +358,19 @@ interpret no indication of a kind as meaning "object". if ((lookahead->arity == 1) && (lookahead->terms[0].variable == v) && (lookahead->element == PREDICATE_ATOM)) { unary_predicate *up = RETRIEVE_POINTER_unary_predicate(lookahead->predicate); - if (up->family == calling_up_family) { + if (up->family == calling_up_family) { NW = up->calling_name; } - if (up->family == kind_up_family) { + if (up->family == kind_up_family) { K = up->assert_kind; } - if (up->family == is_a_kind_up_family) { + if (up->family == is_a_kind_up_family) { is_a_kind = TRUE; K = up->assert_kind; } - if (up->family == is_a_var_up_family) { + if (up->family == is_a_var_up_family) { is_a_var = TRUE; } - if (up->family == is_a_const_up_family) { + if (up->family == is_a_const_up_family) { is_a_const = TRUE; } } diff --git a/docs/knowledge-module/1-km.html b/docs/knowledge-module/1-km.html index e8cfcc6fa..8290e37b6 100644 --- a/docs/knowledge-module/1-km.html +++ b/docs/knowledge-module/1-km.html @@ -76,11 +76,11 @@ which use this module:

 COMPILE_WRITER(booking *, Rules::Bookings::log)
-COMPILE_WRITER(inference *, World::Inferences::log)
+COMPILE_WRITER(inference *, Inferences::log)
 COMPILE_WRITER(inference_subject *, InferenceSubjects::log)
 COMPILE_WRITER(property *, Properties::log)
 COMPILE_WRITER(rulebook *, Rulebooks::log)
-COMPILE_WRITER_I(int, World::Inferences::log_kind)
+COMPILE_WRITER(inference_family *, Inferences::log_kind)
 

§3.

@@ -98,6 +98,9 @@ which use this module:
 void KnowledgeModule::start(void) {
+    Inferences::start();
+    PropertyInferences::start();
+    RelationInferences::start();
     InstanceAdjectives::start();
     Properties::EitherOr::start();
     Properties::Measurement::start();
@@ -106,10 +109,10 @@ which use this module:
     Properties::ComparativeRelations::start();
     Properties::ProvisionRelation::start();
     REGISTER_WRITER('b', Rules::Bookings::log);
-    REGISTER_WRITER('I', World::Inferences::log);
+    REGISTER_WRITER('I', Inferences::log);
     REGISTER_WRITER('j', InferenceSubjects::log);
     REGISTER_WRITER('K', Rulebooks::log);
-    REGISTER_WRITER_I('n', World::Inferences::log_kind)
+    REGISTER_WRITER('n', Inferences::log_kind)
     REGISTER_WRITER('Y', Properties::log);
     Log::declare_aspect(ACTIVITY_CREATIONS_DA, L"activity creations", FALSE, FALSE);
     Log::declare_aspect(INFERENCES_DA, L"inferences", FALSE, TRUE);
diff --git a/docs/knowledge-module/2-iaa.html b/docs/knowledge-module/2-iaa.html
index 7b5ab3ef2..4e4e28cf5 100644
--- a/docs/knowledge-module/2-iaa.html
+++ b/docs/knowledge-module/2-iaa.html
@@ -105,7 +105,7 @@ age property, but we don't go there in Inform.
 }
 
 int InstanceAdjectives::is_enumerative(adjective_meaning *am) {
-    if ((am) && (am->family == enumerative_amf)) return TRUE;
+    if ((am) && (am->family == enumerative_amf)) return TRUE;
     return FALSE;
 }
 
@@ -187,7 +187,7 @@ to infer from, e.g., "the ball is not green": is it red, or blue? instance *I = RETRIEVE_POINTER_instance(am->family_specific_data); property *P = Properties::Conditions::get_coinciding_property(Instances::to_kind(I)); if (P == NULL) internal_error("enumerative adjective on non-property"); - World::Inferences::draw_property(infs_to_assert_on, P, Rvalues::from_instance(I)); + PropertyInferences::draw(infs_to_assert_on, P, Rvalues::from_instance(I)); return TRUE; }
diff --git a/docs/knowledge-module/2-ins.html b/docs/knowledge-module/2-ins.html index d628a356e..cf4954f0e 100644 --- a/docs/knowledge-module/2-ins.html +++ b/docs/knowledge-module/2-ins.html @@ -204,7 +204,7 @@ the same object may be thing number 17 but vehicle number 3 — and secondly because we won't know the exact kind of objects until much later on; for now the only thing we are sure of is that they are indeed objects. Enumeration for objects within kinds is certainly useful, but it's harder to do and will -be done later on: see Instance Counting. +be done later on: see Instance Counting (in runtime).

Add the new instance to its enumeration4.3 = @@ -245,7 +245,7 @@ be done later on: see Instance Counting

§6. Subject and source references.

-inference_subject *Instances::as_subject(instance *I) {
+inference_subject *Instances::as_subject(instance *I) {
     if (I == NULL) return NULL;
     return I->as_subject;
 }
@@ -341,13 +341,13 @@ specialised than which other ones, and by making a call, we can find out.
 

-kind *Instances::to_kind(instance *I) {
+kind *Instances::to_kind(instance *I) {
     if (I == NULL) return NULL;
     inference_subject *inherits_from = InferenceSubjects::narrowest_broader_subject(I->as_subject);
     return KindSubjects::to_kind(inherits_from);
 }
 
-int Instances::of_kind(instance *I, kind *match) {
+int Instances::of_kind(instance *I, kind *match) {
     if ((I == NULL) || (match == NULL)) return FALSE;
     return Kinds::conforms_to(Instances::to_kind(I), match);
 }
diff --git a/docs/knowledge-module/2-nv.html b/docs/knowledge-module/2-nv.html
index 341ca2a3f..dfbc86e27 100644
--- a/docs/knowledge-module/2-nv.html
+++ b/docs/knowledge-module/2-nv.html
@@ -135,7 +135,7 @@ closer to global variables than to literals such as     CLASS_DEFINITION
 } nonlocal_variable;
 
-
  • The structure nonlocal_variable is accessed in 2/ins, 3/prp, 3/ep, 3/vp, 3/spr, 4/vs, 5/inf, 5/cmw and here.
+
  • The structure nonlocal_variable is accessed in 2/ins, 3/prp, 3/ep, 3/vp, 3/spr, 4/vs, 5/inf, 5/pi, 5/tmw and here.

§2. We can create a new variable provided we give its name, kind and scope. When the scope isn't global, the variable is said to be "stacked", which is a reference to how it's stored at run-time. @@ -320,10 +320,10 @@ data variable (such as "story title") to be treated as text. wording NonlocalVariables::initial_value_as_plain_text(nonlocal_variable *nlv) { inference *inf; inference_subject *infs = NonlocalVariables::to_subject(nlv); - POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_variable_initial_value) + POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) + if (PropertyInferences::get_property(inf) == P_variable_initial_value) return Node::get_text( - World::Inferences::set_property_value_kind(inf, K_text)); + PropertyInferences::set_value_kind(inf, K_text)); return EMPTY_WORDING; }

diff --git a/docs/knowledge-module/3-cp.html b/docs/knowledge-module/3-cp.html index 7e23b348f..a48e3ec93 100644 --- a/docs/knowledge-module/3-cp.html +++ b/docs/knowledge-module/3-cp.html @@ -106,7 +106,7 @@ possible values these are.) kind *common_kind = NULL; int mixed_kind = FALSE, some_new = FALSE; wording CKW = EMPTY_WORDING, NKW = EMPTY_WORDING; - for (parse_node *option = set; option; option = (option->down)?(option->down->next):NULL) { + for (parse_node *option = set; option; option = (option->down)?(option->down->next):NULL) { wording PW = EMPTY_WORDING; if (Node::get_type(option) == AND_NT) PW = Node::get_text(option->down); diff --git a/docs/knowledge-module/3-ep.html b/docs/knowledge-module/3-ep.html index 39def2fc9..a8fafdc87 100644 --- a/docs/knowledge-module/3-ep.html +++ b/docs/knowledge-module/3-ep.html @@ -219,7 +219,7 @@ around), but not to break one. Properties::EitherOr::make_stored_in_negation(neg); } -property *Properties::EitherOr::get_negation(property *prn) { +property *Properties::EitherOr::get_negation(property *prn) { if ((prn == NULL) || (prn->either_or == FALSE)) internal_error("non-EO property"); return prn->negation; } @@ -227,7 +227,7 @@ around), but not to break one.

§7.

-int Properties::EitherOr::stored_in_negation(property *prn) {
+int Properties::EitherOr::stored_in_negation(property *prn) {
     if ((prn == NULL) || (prn->either_or == FALSE)) internal_error("non-EO property");
     return prn->stored_in_negation;
 }
@@ -338,7 +338,7 @@ adjectival meaning:
 }
 
 int Properties::EitherOr::is_either_or_adjective(adjective_meaning *am) {
-    if ((am) && (am->family == either_or_property_amf)) return TRUE;
+    if ((am) && (am->family == either_or_property_amf)) return TRUE;
     return FALSE;
 }
 
@@ -458,8 +458,8 @@ property.
 int Properties::EitherOr::assert_adj(adjective_meaning_family *f,
     adjective_meaning *am, inference_subject *infs_to_assert_on, int parity) {
     property *prn = RETRIEVE_POINTER_property(am->family_specific_data);
-    if (parity == FALSE) World::Inferences::draw_negated_property(infs_to_assert_on, prn, NULL);
-    else World::Inferences::draw_property(infs_to_assert_on, prn, NULL);
+    if (parity == FALSE) PropertyInferences::draw_negated(infs_to_assert_on, prn, NULL);
+    else PropertyInferences::draw(infs_to_assert_on, prn, NULL);
     return TRUE;
 }
 
diff --git a/docs/knowledge-module/3-epv.html b/docs/knowledge-module/3-epv.html index 734963892..e64f5045b 100644 --- a/docs/knowledge-module/3-epv.html +++ b/docs/knowledge-module/3-epv.html @@ -98,17 +98,6 @@ manage that here. Produce::annotate_i(iname, DECLARATION_ORDER_IANN, cs_sequence_counter++); Compile the actual object1.1; - if (K) { - World::Compile::set_rough_memory_usage(K, words_used); - int nw = 0; - for (inference_subject *infs = subj; - infs; infs = InferenceSubjects::narrowest_broader_subject(infs)) { - kind *K2 = KindSubjects::to_kind(infs); - if (K2) nw += World::Compile::get_rough_memory_usage(K2); - } - nw += 16; - LOGIF(OBJECT_COMPILATION, "Rough size estimate: %d words\n", nw); - } LOGIF(OBJECT_COMPILATION, "Compilation of $j complete\n", subj); }
@@ -172,9 +161,9 @@ the class hierarchy at I6 level exactly match the kind hierarchy at I7 level.
     inference *inf;
-    KNOWLEDGE_LOOP(inf, subj, PROPERTY_INF) {
-        property *prn = World::Inferences::get_property(inf);
-        current_sentence = World::Inferences::where_inferred(inf);
+    KNOWLEDGE_LOOP(inf, subj, property_inf) {
+        property *prn = PropertyInferences::get_property(inf);
+        current_sentence = Inferences::where_inferred(inf);
         LOGIF(OBJECT_COMPILATION, "Compiling property $Y\n", prn);
         words_used += Properties::Emit::emit_propertyvalue(subj, prn);
     }
diff --git a/docs/knowledge-module/3-ia.html b/docs/knowledge-module/3-ia.html
index 2f02fe266..0f642ef51 100644
--- a/docs/knowledge-module/3-ia.html
+++ b/docs/knowledge-module/3-ia.html
@@ -93,8 +93,8 @@ So as an interim measure the text is inferred into a pseudo-property called
 
 void Properties::Appearance::infer(inference_subject *infs, parse_node *spec) {
     inference *inf;
-    KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF)
-        if (World::Inferences::get_property(inf) == P_indefinite_appearance_text)
+    KNOWLEDGE_LOOP(inf, infs, property_inf)
+        if (PropertyInferences::get_property(inf) == P_indefinite_appearance_text)
             Issue a problem for a second appearance1.1;
 
     prevailing_mood = CERTAIN_CE;
@@ -113,7 +113,7 @@ ambiguously.
 
 
     StandardProblems::infs_contradiction_problem(_p_(PM_TwoAppearances),
-        World::Inferences::where_inferred(inf), current_sentence, infs,
+        Inferences::where_inferred(inf), current_sentence, infs,
         "seems to have two different descriptions",
         "perhaps because you intended the second description to apply to something "
         "mentioned in between, but declared it in such a way that it was never the "
@@ -136,12 +136,12 @@ available;
 
  • (c) But otherwise give up and issue a problem message.
  • -void Properties::Appearance::reallocate(inference_subject *infs) {
    +void Properties::Appearance::reallocate(inference_subject *infs) {
         inference *inf;
    -    KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
    -        if (World::Inferences::get_property(inf) == P_indefinite_appearance_text) {
    -            parse_node *txt = World::Inferences::get_property_value(inf);
    -            current_sentence = World::Inferences::where_inferred(inf);
    +    KNOWLEDGE_LOOP(inf, infs, property_inf) {
    +        if (PropertyInferences::get_property(inf) == P_indefinite_appearance_text) {
    +            parse_node *txt = PropertyInferences::get_value(inf);
    +            current_sentence = Inferences::where_inferred(inf);
                 if (Plugins::Call::default_appearance(infs, txt) == FALSE) {
                     if ((P_description) &&
                         (World::Permissions::find(infs, P_description, TRUE))) {
    diff --git a/docs/knowledge-module/3-ma.html b/docs/knowledge-module/3-ma.html
    index 4a97caa45..411c7e15e 100644
    --- a/docs/knowledge-module/3-ma.html
    +++ b/docs/knowledge-module/3-ma.html
    @@ -564,7 +564,7 @@ can't normally be unravelled at compile time.
             parse_node *val = NULL;
             if (<s-literal>(mdef->region_threshold_text)) val = <<rp>>;
             else internal_error("literal unreadable");
    -        World::Inferences::draw_property(infs_to_assert_on, mdef->prop, val);
    +        PropertyInferences::draw(infs_to_assert_on, mdef->prop, val);
             return TRUE;
         }
         return FALSE;
    diff --git a/docs/knowledge-module/3-prp.html b/docs/knowledge-module/3-prp.html
    index f25e0581e..1669a614d 100644
    --- a/docs/knowledge-module/3-prp.html
    +++ b/docs/knowledge-module/3-prp.html
    @@ -143,7 +143,7 @@ a value with the owner; it isn't that either/or properties are unloved.)
         CLASS_DEFINITION
     } property;
     
    -
    • The structure property is accessed in 2/nv, 3/ep, 3/vp, 3/cp, 3/spr, 4/vs, 5/inf, 5/cmw and here.
    +
    • The structure property is accessed in 2/nv, 3/ep, 3/vp, 3/cp, 3/spr, 4/vs, 5/inf, 5/pi, 5/tmw and here.

    §2. The only four properties which have special significance to core Inform (though plugins are interested in many others):

    @@ -538,10 +538,10 @@ of the other:

    -int Properties::is_either_or(property *prn) {
    +int Properties::is_either_or(property *prn) {
         return prn->either_or;
     }
    -int Properties::is_value_property(property *prn) {
    +int Properties::is_value_property(property *prn) {
         if (prn->either_or == FALSE) return TRUE;
         return FALSE;
     }
    @@ -563,7 +563,7 @@ sake:
     

    -int Properties::is_shown_in_index(property *prn) {
    +int Properties::is_shown_in_index(property *prn) {
         return prn->include_in_index;
     }
     void Properties::exclude_from_index(property *prn) {
    @@ -574,10 +574,10 @@ sake:
     

    -void Properties::set_indexed_already_flag(property *prn, int state) {
    +void Properties::set_indexed_already_flag(property *prn, int state) {
         prn->indexed_already = state;
     }
    -int Properties::get_indexed_already_flag(property *prn) {
    +int Properties::get_indexed_already_flag(property *prn) {
         return prn->indexed_already;
     }
     
    @@ -781,11 +781,11 @@ we find it, we compile it and return int Properties::compile_property_value_inner(value_holster *VH, inference_subject *infs, property *prn) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - if (World::Inferences::get_inference_type(inf) == PROPERTY_INF) { - current_sentence = World::Inferences::where_inferred(inf); - int sense = (World::Inferences::get_certainty(inf) > 0)?TRUE:FALSE; - property *inferred_property = World::Inferences::get_property(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) { + if (Inferences::get_inference_type(inf) == property_inf) { + current_sentence = Inferences::where_inferred(inf); + int sense = (Inferences::get_certainty(inf) > 0)?TRUE:FALSE; + property *inferred_property = PropertyInferences::get_property(inf); if (Properties::is_either_or(prn)) { if (inferred_property == prn) { Properties::EitherOr::compile_value(VH, inferred_property, sense); @@ -798,7 +798,7 @@ we find it, we compile it and return } else { if (inferred_property == prn) { if (sense) { - parse_node *val = World::Inferences::get_property_value(inf); + parse_node *val = PropertyInferences::get_value(inf); if (val == NULL) internal_error("malformed property inference"); Properties::Valued::compile_value(VH, inferred_property, val); return TRUE; @@ -815,7 +815,7 @@ we find it, we compile it and return §26. Emitting to Inter.

    -inter_name *Properties::iname(property *prn) {
    +inter_name *Properties::iname(property *prn) {
         if (prn == NULL) internal_error("tried to find iname for null property");
         if ((Properties::is_either_or(prn)) && (prn->stored_in_negation))
             return Properties::iname(Properties::EitherOr::get_negation(prn));
    diff --git a/docs/knowledge-module/3-ps.html b/docs/knowledge-module/3-ps.html
    index 6cbd29106..aabe443b4 100644
    --- a/docs/knowledge-module/3-ps.html
    +++ b/docs/knowledge-module/3-ps.html
    @@ -102,24 +102,24 @@ sentence will be properly parsed later on.
         pn = pn->down;
         if ((Node::get_type(pn) == VERB_NT)
             && (Node::get_special_meaning(pn) == NULL)
    -        && (pn->next)
    -        && (pn->next->next)
    -        && (Diagrams::is_possessive_RELATIONSHIP(pn->next->next))
    -        && (Node::get_type(pn->next->next->down) == CALLED_NT)
    -        && (pn->next->next->down->down)
    -        && (pn->next->next->down->down->next)) {
    -        parse_node *apparent_subject = pn->next;
    +        && (pn->next)
    +        && (pn->next->next)
    +        && (Diagrams::is_possessive_RELATIONSHIP(pn->next->next))
    +        && (Node::get_type(pn->next->next->down) == CALLED_NT)
    +        && (pn->next->next->down->down)
    +        && (pn->next->next->down->down->next)) {
    +        parse_node *apparent_subject = pn->next;
             wording SW = Node::get_text(apparent_subject);
             if (Node::get_type(apparent_subject) == WITH_NT)
                 if (apparent_subject->down) {
                     int s1 = Wordings::first_wn(Node::get_text(apparent_subject->down));
    -                parse_node *C = apparent_subject->down->next;
    +                parse_node *C = apparent_subject->down->next;
                     if (C)
                         SW = Wordings::new(s1, Wordings::last_wn(Node::get_text(C)));
                     else
                         SW = Wordings::new(s1, Wordings::last_wn(SW));
                 }
    -        wording PW = Node::get_text(pn->next->next->down->down->next);
    +        wording PW = Node::get_text(pn->next->next->down->down->next);
             if (<prohibited-property-owners>(SW) == FALSE)
                 <has-properties-called-sentence-object>(PW);
         }
    diff --git a/docs/knowledge-module/3-spr2.html b/docs/knowledge-module/3-spr2.html
    index e338aac9d..6fc825f3a 100644
    --- a/docs/knowledge-module/3-spr2.html
    +++ b/docs/knowledge-module/3-spr2.html
    @@ -363,7 +363,7 @@ be caught later on Inform's run.
             inference_subject *infs1, parse_node *spec1) {
         property_setting_bp_data *PSD =
             RETRIEVE_POINTER_property_setting_bp_data(bp->family_specific);
    -    World::Inferences::draw_property(infs0, PSD->set_property, spec1);
    +    PropertyInferences::draw(infs0, PSD->set_property, spec1);
         return TRUE;
     }
     
    diff --git a/docs/knowledge-module/3-vp.html b/docs/knowledge-module/3-vp.html index aa4f5a0e1..2224b1e09 100644 --- a/docs/knowledge-module/3-vp.html +++ b/docs/knowledge-module/3-vp.html @@ -135,7 +135,7 @@ to the end user.

    -property *Properties::Valued::new_nameless(text_stream *I6_form, kind *K) {
    +property *Properties::Valued::new_nameless(text_stream *I6_form, kind *K) {
         wording W = Feeds::feed_text(I6_form);
         if (K == NULL) internal_error("new nameless property without kind");
         package_request *R = Hierarchy::synoptic_package(PROPERTIES_HAP);
    @@ -152,7 +152,7 @@ to the end user.
         return prn;
     }
     
    -property *Properties::Valued::new_nameless_using(kind *K, package_request *R, inter_name *using) {
    +property *Properties::Valued::new_nameless_using(kind *K, package_request *R, inter_name *using) {
         if (K == NULL) internal_error("new nameless property without kind");
         property *prn = Properties::create(EMPTY_WORDING, R, using);
         Properties::exclude_from_index(prn);
    @@ -168,7 +168,7 @@ to the end user.
     

    §4. Initialising details.

    -void Properties::Valued::initialise(property *prn) {
    +void Properties::Valued::initialise(property *prn) {
         prn->property_value_kind = NULL;
         prn->setting_bp = NULL;
         prn->used_for_non_typesafe_relation = FALSE;
    @@ -176,7 +176,7 @@ to the end user.
         Properties::Conditions::initialise(prn);
     }
     
    -void Properties::Valued::make_setting_relation(property *prn, wording W) {
    +void Properties::Valued::make_setting_relation(property *prn, wording W) {
         binary_predicate *bp = Properties::SettingRelations::find_set_property_BP(W);
         if (bp == NULL) bp = Properties::SettingRelations::make_set_property_BP(W);
         Properties::SettingRelations::fix_property_bp(bp);
    @@ -188,12 +188,12 @@ to the end user.
     

    -kind *Properties::Valued::kind(property *prn) {
    +kind *Properties::Valued::kind(property *prn) {
         if ((prn == NULL) || (prn->either_or)) return NULL;  for better type-checking Problems
         return prn->property_value_kind;
     }
     
    -void Properties::Valued::set_kind(property *prn, kind *K) {
    +void Properties::Valued::set_kind(property *prn, kind *K) {
         if (K == NULL) internal_error("tried to set null kind");
         if ((prn == NULL) || (prn->either_or)) internal_error("non-value property");
         if ((Kinds::Behaviour::definite(K) == FALSE) && (prn->do_not_compile == FALSE)) {
    @@ -230,7 +230,7 @@ then say that a thing has a weight: that makes a property also called
     

    -void Properties::Valued::make_coincide_with_kind(property *prn, kind *K) {
    +void Properties::Valued::make_coincide_with_kind(property *prn, kind *K) {
         Properties::Valued::set_kind(prn, K);
         if (Kinds::eq(K, K_grammatical_gender)) P_grammatical_gender = prn;
         prn->also_a_type = TRUE;
    @@ -261,7 +261,7 @@ then say that a thing has a weight: that makes a property also called
         prn->stored_bp = bp;
     }
     
    -binary_predicate *Properties::Valued::get_stored_relation(property *prn) {
    +binary_predicate *Properties::Valued::get_stored_relation(property *prn) {
         if ((prn == NULL) || (prn->either_or)) internal_error("non-value property");
         return prn->stored_bp;
     }
    @@ -280,7 +280,7 @@ all to work; the following keep a flag to mark that.
         prn->used_for_non_typesafe_relation = TRUE;
     }
     
    -int Properties::Valued::is_used_for_non_typesafe_relation(property *prn) {
    +int Properties::Valued::is_used_for_non_typesafe_relation(property *prn) {
         if ((prn == NULL) || (prn->either_or)) internal_error("non-value property");
         return prn->used_for_non_typesafe_relation;
     }
    @@ -288,7 +288,7 @@ all to work; the following keep a flag to mark that.
     

    §10. Assertion.

    -void Properties::Valued::assert(property *prn, inference_subject *owner,
    +void Properties::Valued::assert(property *prn, inference_subject *owner,
         parse_node *val, int certainty) {
         pcalc_prop *prop = Propositions::Abstract::to_set_property(prn, val);
         Assert::true_about(prop, owner, certainty);
    @@ -301,7 +301,7 @@ storage methods at run-time if we wanted.)
     

    -void Properties::Valued::compile_value(value_holster *VH, property *prn, parse_node *val) {
    +void Properties::Valued::compile_value(value_holster *VH, property *prn, parse_node *val) {
         kind *K = Properties::Valued::kind(prn);
         if (K) Specifications::Compiler::compile_constant_to_kind_vh(VH, val, K);
         else {
    @@ -312,7 +312,7 @@ storage methods at run-time if we wanted.)
         }
     }
     
    -void Properties::Valued::compile_default_value(value_holster *VH, property *prn) {
    +void Properties::Valued::compile_default_value(value_holster *VH, property *prn) {
         if (Properties::Valued::is_used_for_non_typesafe_relation(prn)) {
             if (Holsters::data_acceptable(VH))
                 Holsters::holster_pair(VH, LITERAL_IVAL, 0);
    diff --git a/docs/knowledge-module/4-is.html b/docs/knowledge-module/4-is.html
    index 2eb1e69be..338d78101 100644
    --- a/docs/knowledge-module/4-is.html
    +++ b/docs/knowledge-module/4-is.html
    @@ -115,7 +115,7 @@ as method calls. There are (currently) five families.
         return f;
     }
     
    -
    • The structure inference_subject_family is private to this section.
    +
    • The structure inference_subject_family is accessed in 5/inf and here.

    §2. The "fundamentals" family will be defined here. As we will see, it is used only for a few broad concepts. It provides few method functions, because these subjects serve a mainly organisational role.1 @@ -215,8 +215,8 @@ one and only subject with no broader subject: struct general_pointer represents; family-specific data void *additional_data_for_plugins[MAX_PLUGINS]; and managed by those plugins - struct inference *inf_list; contingently true: inferences drawn about this subject - struct implication *imp_list; necessarily true: implications applying to this + struct linked_list *inf_list; contingently true: each inference drawn about this + struct linked_list *imp_list; necessarily true: each implication applying to this struct linked_list *permissions_list; of property_permission struct assemblies_data assemblies; what generalisations have been made about this? @@ -255,8 +255,8 @@ kind once the kind itself is created.) infs->infs_created_at = current_sentence; infs->represents = gp; infs->infs_family = family; - infs->inf_list = NULL; - infs->imp_list = NULL; + infs->inf_list = NEW_LINKED_LIST(inference); + infs->imp_list = NEW_LINKED_LIST(implication); infs->broader_than = from; infs->permissions_list = NEW_LINKED_LIST(property_permission); infs->infs_name_in_log = log_name; @@ -275,7 +275,7 @@ It has to do with the difference between "yourself" and "the player". infs->alias_variable = q; } -int InferenceSubjects::aliased_but_diverted(inference_subject *infs) { +int InferenceSubjects::aliased_but_diverted(inference_subject *infs) { if (infs->alias_variable) { inference_subject *vs = Instances::as_subject( @@ -296,7 +296,7 @@ This makes testing for containment simple:

    -int InferenceSubjects::is_within(inference_subject *smaller, inference_subject *larger) {
    +int InferenceSubjects::is_within(inference_subject *smaller, inference_subject *larger) {
         while (smaller) {
             if (smaller == larger) return TRUE;
             smaller = smaller->broader_than;
    @@ -314,7 +314,7 @@ operations scaling the subject tree, we use the following:
     

    -inference_subject *InferenceSubjects::narrowest_broader_subject(inference_subject *narrow) {
    +inference_subject *InferenceSubjects::narrowest_broader_subject(inference_subject *narrow) {
         if (narrow == NULL) return NULL;
         return narrow->broader_than;
     }
    @@ -326,7 +326,7 @@ before, then this remains true afterwards.
     

    -void InferenceSubjects::falls_within(inference_subject *narrow, inference_subject *broad) {
    +void InferenceSubjects::falls_within(inference_subject *narrow, inference_subject *broad) {
         if (InferenceSubjects::is_within(broad, narrow->broader_than) == FALSE)
             internal_error("subject breadth change leads to inconsistency");
         narrow->broader_than = broad;
    @@ -345,24 +345,15 @@ before, then this remains true afterwards.
         return &(infs->assemblies);
     }
     
    -inference *InferenceSubjects::get_inferences(inference_subject *infs) {
    +linked_list *InferenceSubjects::get_inferences(inference_subject *infs) {
         return (infs)?(infs->inf_list):NULL;
     }
     
    -void InferenceSubjects::set_inferences(inference_subject *infs, inference *inf) {
    -    if (infs == NULL) internal_error("null INFS");
    -    infs->inf_list = inf;
    -}
    -
    -implication *InferenceSubjects::get_implications(inference_subject *infs) {
    +linked_list *InferenceSubjects::get_implications(inference_subject *infs) {
         return infs->imp_list;
     }
     
    -void InferenceSubjects::set_implications(inference_subject *infs, implication *imp) {
    -    infs->imp_list = imp;
    -}
    -
    -linked_list *InferenceSubjects::get_permissions(inference_subject *infs) {
    +linked_list *InferenceSubjects::get_permissions(inference_subject *infs) {
         return infs->permissions_list;
     }
     
    @@ -372,7 +363,7 @@ kinds and instances.

    -inference_subject *InferenceSubjects::from_specification(parse_node *spec) {
    +inference_subject *InferenceSubjects::from_specification(parse_node *spec) {
         inference_subject *infs = NULL;
         if (Specifications::is_kind_like(spec)) {
             kind *K = Specifications::to_kind(spec);
    @@ -388,7 +379,7 @@ kinds and instances.
     

    -parse_node *InferenceSubjects::as_constant(inference_subject *infs) {
    +parse_node *InferenceSubjects::as_constant(inference_subject *infs) {
         kind *K = KindSubjects::to_kind(infs);
         if (K) return Specifications::from_kind(K);
     
    @@ -402,11 +393,11 @@ kinds and instances.
     

    -int InferenceSubjects::is_an_object(inference_subject *infs) {
    +int InferenceSubjects::is_an_object(inference_subject *infs) {
         if (InstanceSubjects::to_object_instance(infs)) return TRUE;
         return FALSE;
     }
    -int InferenceSubjects::is_a_kind_of_object(inference_subject *infs) {
    +int InferenceSubjects::is_a_kind_of_object(inference_subject *infs) {
         if (infs) {
             kind *K = KindSubjects::to_kind(infs);
             if ((K) && (Kinds::Behaviour::is_subkind_of_object(K))) return TRUE;
    @@ -417,7 +408,7 @@ kinds and instances.
     

    §16. Logging.

    -void InferenceSubjects::log(inference_subject *infs) {
    +void InferenceSubjects::log(inference_subject *infs) {
         if (infs == NULL) { LOG("<null infs>"); return; }
         if (infs->infs_name_in_log) { LOG("infs<%s>", infs->infs_name_in_log); return; }
     
    @@ -434,9 +425,10 @@ kinds and instances.
     }
     
     void InferenceSubjects::log_knowledge_about(inference_subject *infs) {
    -    inference *inf;
         LOG("Inferences drawn about $j:\n", infs); LOG_INDENT;
    -    for (inf = InferenceSubjects::get_inferences(infs); inf; inf = inf->next) LOG("$I\n", inf);
    +    inference *inf;
    +    LOOP_OVER_LINKED_LIST(inf, inference, InferenceSubjects::get_inferences(infs))
    +        LOG("$I\n", inf);
         LOG_OUTDENT;
     }
     
    @@ -447,7 +439,7 @@ DAG.

    -void InferenceSubjects::log_infs_hierarchy(void) {
    +void InferenceSubjects::log_infs_hierarchy(void) {
         LOG("Subjects hierarchy:\n");
         InferenceSubjects::log_subjects_hierarchically(NULL, 0);
     }
    @@ -474,7 +466,7 @@ word range into the wording.
     VOID_METHOD_TYPE(GET_NAME_TEXT_INFS_MTID, inference_subject_family *f,
         inference_subject *infs, wording *W)
     
    -wording InferenceSubjects::get_name_text(inference_subject *infs) {
    +wording InferenceSubjects::get_name_text(inference_subject *infs) {
         if (infs == NULL) internal_error("null INFS");
         wording W = EMPTY_WORDING;
         VOID_METHOD_CALL(infs->infs_family, GET_NAME_TEXT_INFS_MTID, infs, &W);
    @@ -499,7 +491,7 @@ level of certainty.
     INT_METHOD_TYPE(GET_DEFAULT_CERTAINTY_INFS_MTID, inference_subject_family *f,
         inference_subject *infs)
     
    -int InferenceSubjects::get_default_certainty(inference_subject *infs) {
    +int InferenceSubjects::get_default_certainty(inference_subject *infs) {
         int cert = CERTAIN_CE;
         INT_METHOD_CALL(cert, infs->infs_family, GET_DEFAULT_CERTAINTY_INFS_MTID, infs);
         return cert;
    @@ -517,7 +509,7 @@ to the permission, or NULL_GE
     VOID_METHOD_TYPE(NEW_PERMISSION_GRANTED_INFS_MTID, inference_subject_family *f,
         inference_subject *infs, general_pointer *G)
     
    -general_pointer InferenceSubjects::new_permission_granted(inference_subject *infs) {
    +general_pointer InferenceSubjects::new_permission_granted(inference_subject *infs) {
         if (infs == NULL) internal_error("null INFS");
         general_pointer G = NULL_GENERAL_POINTER;
         VOID_METHOD_CALL(infs->infs_family, NEW_PERMISSION_GRANTED_INFS_MTID, infs, &G);
    @@ -536,7 +528,7 @@ of "green" as an adjective.
     VOID_METHOD_TYPE(MAKE_ADJ_CONST_DOMAIN_INFS_MTID, inference_subject_family *f,
         inference_subject *infs, instance *nc, property *prn)
     
    -void InferenceSubjects::make_adj_const_domain(inference_subject *infs,
    +void InferenceSubjects::make_adj_const_domain(inference_subject *infs,
         instance *nc, property *prn) {
         if (infs == NULL) internal_error("null INFS");
         VOID_METHOD_CALL(infs->infs_family, MAKE_ADJ_CONST_DOMAIN_INFS_MTID, infs, nc, prn);
    @@ -552,7 +544,7 @@ to fill in anything missing about itself:
     
     VOID_METHOD_TYPE(COMPLETE_MODEL_INFS_MTID, inference_subject_family *f, inference_subject *infs)
     
    -void InferenceSubjects::complete_model(inference_subject *infs) {
    +void InferenceSubjects::complete_model(inference_subject *infs) {
         if (infs == NULL) internal_error("null INFS");
         VOID_METHOD_CALL(infs->infs_family, COMPLETE_MODEL_INFS_MTID, infs);
     }
    @@ -566,7 +558,7 @@ consistency, and to issue problem messages if something is wrong:
     
     VOID_METHOD_TYPE(CHECK_MODEL_INFS_MTID, inference_subject_family *f, inference_subject *infs)
     
    -void InferenceSubjects::check_model(inference_subject *infs) {
    +void InferenceSubjects::check_model(inference_subject *infs) {
         if (infs == NULL) internal_error("null INFS");
         VOID_METHOD_CALL(infs->infs_family, CHECK_MODEL_INFS_MTID, infs);
     }
    @@ -616,11 +608,11 @@ for an individual subject.
     
     INT_METHOD_TYPE(EMIT_ALL_INFS_MTID, inference_subject_family *f, int ignored)
     VOID_METHOD_TYPE(EMIT_ONE_INFS_MTID, inference_subject_family *f, inference_subject *infs)
    -void InferenceSubjects::emit_all(void) {
    +void InferenceSubjects::emit_all(void) {
         inference_subject *infs;
     
         LOOP_OVER(infs, inference_subject)
    -        World::Inferences::verify_prop_states(infs);
    +        Inferences::verify_prop_states(infs);
     
         inference_subject_family *family;
         LOOP_OVER(family, inference_subject_family) {
    diff --git a/docs/knowledge-module/4-is2.html b/docs/knowledge-module/4-is2.html
    index ffb0f8805..d7f4de949 100644
    --- a/docs/knowledge-module/4-is2.html
    +++ b/docs/knowledge-module/4-is2.html
    @@ -116,7 +116,7 @@ a go-between.
         return NULL;
     }
     
    -instance *InstanceSubjects::to_object_instance(inference_subject *infs) {
    +instance *InstanceSubjects::to_object_instance(inference_subject *infs) {
         instance *I = InstanceSubjects::to_instance(infs);
         if ((I) && (Kinds::Behaviour::is_object(Instances::to_kind(I)))) return I;
         return NULL;
    diff --git a/docs/knowledge-module/4-ks.html b/docs/knowledge-module/4-ks.html
    index ffac01173..603e66dad 100644
    --- a/docs/knowledge-module/4-ks.html
    +++ b/docs/knowledge-module/4-ks.html
    @@ -134,12 +134,12 @@ a little trickier than for other subject families:
     

    -inference_subject *KindSubjects::from_kind(kind *K) {
    +inference_subject *KindSubjects::from_kind(kind *K) {
         if (K == NULL) return NULL;
         return K->construct->base_as_infs;
     }
     
    -kind *KindSubjects::to_kind(inference_subject *infs) {
    +kind *KindSubjects::to_kind(inference_subject *infs) {
         if ((infs) && (infs->infs_family == kinds_family)) {
             kind *K = Kinds::base_construction(
                     RETRIEVE_POINTER_kind_constructor(infs->represents));
    diff --git a/docs/knowledge-module/4-rs.html b/docs/knowledge-module/4-rs.html
    index e78e27246..3be4220ff 100644
    --- a/docs/knowledge-module/4-rs.html
    +++ b/docs/knowledge-module/4-rs.html
    @@ -130,10 +130,9 @@ function togglePopup(material_id) {
             (bp->right_way_round)) {
             RTRelations::equivalence_relation_make_singleton_partitions(bp, domain_size);
             inference *i;
    -        POSITIVE_KNOWLEDGE_LOOP(i, World::Inferences::bp_as_subject(bp),
    -            ARBITRARY_RELATION_INF) {
    +        POSITIVE_KNOWLEDGE_LOOP(i, Inferences::bp_as_subject(bp), arbitrary_relation_inf) {
                 inference_subject *infs0, *infs1;
    -            World::Inferences::get_references(i, &infs0, &infs1);
    +            Inferences::get_references(i, &infs0, &infs1);
                 RTRelations::equivalence_relation_merge_classes(bp, domain_size,
                     infs0->allocation_id, infs1->allocation_id);
             }
    @@ -177,10 +176,10 @@ checking in.
             inference *inf1 = NULL;
             int leftc = 0;
             inference *inf;
    -        KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
    -            if ((World::Inferences::get_property(inf) == prn) &&
    -                (World::Inferences::get_certainty(inf) == CERTAIN_CE)) {
    -                parse_node *val = World::Inferences::get_property_value(inf);
    +        KNOWLEDGE_LOOP(inf, infs, property_inf) {
    +            if ((PropertyInferences::get_property(inf) == prn) &&
    +                (Inferences::get_certainty(inf) == CERTAIN_CE)) {
    +                parse_node *val = PropertyInferences::get_value(inf);
                     inference_subject *infs2 = InferenceSubjects::from_specification(val);
                     leftc++;
                     if (infs2) {
    @@ -191,8 +190,8 @@ checking in.
                     if (leftc == 1) inf1 = inf;
                     if (leftc == 2) {
                         StandardProblems::infs_contradiction_problem(_p_(BelievedImpossible),
    -                        World::Inferences::where_inferred(inf1),
    -                        World::Inferences::where_inferred(inf),
    +                        Inferences::where_inferred(inf1),
    +                        Inferences::where_inferred(inf),
                             infs, "can only relate to one other thing in this way",
                             "since the relation in question is one-to-one.");
                     }
    @@ -202,8 +201,8 @@ checking in.
         LOOP_OVER(infs, inference_subject) {
             if (right_counts[infs->allocation_id] >= 2) {
                 StandardProblems::infs_contradiction_problem(_p_(PM_Relation1to1Right),
    -                World::Inferences::where_inferred(right_first[infs->allocation_id]),
    -                World::Inferences::where_inferred(right_second[infs->allocation_id]),
    +                Inferences::where_inferred(right_first[infs->allocation_id]),
    +                Inferences::where_inferred(right_second[infs->allocation_id]),
                     infs, "can only relate to one other thing in this way",
                     "since the relation in question is one-to-one.");
             }
    @@ -233,11 +232,10 @@ checking in.
         LOOP_OVER(infs, inference_subject) right_counts[infs->allocation_id] = 0;
     
         inference *inf;
    -    POSITIVE_KNOWLEDGE_LOOP(inf, World::Inferences::bp_as_subject(bp),
    -        ARBITRARY_RELATION_INF) {
    +    POSITIVE_KNOWLEDGE_LOOP(inf, Inferences::bp_as_subject(bp), arbitrary_relation_inf) {
             parse_node *left_val = NULL;
             parse_node *right_val = NULL;
    -        World::Inferences::get_references_spec(inf, &left_val, &right_val);
    +        Inferences::get_references_spec(inf, &left_val, &right_val);
             inference_subject *left_infs = InferenceSubjects::from_specification(left_val);
             inference_subject *right_infs = InferenceSubjects::from_specification(right_val);
             int left_id = (left_infs)?(left_infs->allocation_id):(-1);
    @@ -261,8 +259,8 @@ checking in.
                 if (left_counts[infs->allocation_id] >= 2) {
                     StandardProblems::infs_contradiction_problem(
                         _p_(PM_RelationVtoOContradiction),
    -                    World::Inferences::where_inferred(left_first[infs->allocation_id]),
    -                    World::Inferences::where_inferred(left_second[infs->allocation_id]),
    +                    Inferences::where_inferred(left_first[infs->allocation_id]),
    +                    Inferences::where_inferred(left_second[infs->allocation_id]),
                         infs, "can only relate to one other thing in this way",
                         "since the relation in question is various-to-one.");
                 }
    @@ -272,8 +270,8 @@ checking in.
                 if (right_counts[infs->allocation_id] >= 2) {
                     StandardProblems::infs_contradiction_problem(
                         _p_(PM_RelationOtoVContradiction),
    -                    World::Inferences::where_inferred(right_first[infs->allocation_id]),
    -                    World::Inferences::where_inferred(right_second[infs->allocation_id]),
    +                    Inferences::where_inferred(right_first[infs->allocation_id]),
    +                    Inferences::where_inferred(right_second[infs->allocation_id]),
                         infs, "can only be related to by one other thing in this way",
                         "since the relation in question is one-to-various.");
                 }
    diff --git a/docs/knowledge-module/4-vs.html b/docs/knowledge-module/4-vs.html
    index eec2586ea..4f3c400bf 100644
    --- a/docs/knowledge-module/4-vs.html
    +++ b/docs/knowledge-module/4-vs.html
    @@ -129,22 +129,22 @@ about the same subject.
         if (nlv) {
             inference_subject *infs = NonlocalVariables::to_subject(nlv);
             inference *inf;
    -        POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF)
    -            if (World::Inferences::get_property(inf) == P_variable_initial_value)
    +        POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf)
    +            if (PropertyInferences::get_property(inf) == P_variable_initial_value)
                     return inf;
         }
         return NULL;
     }
     
    -parse_node *VariableSubjects::get_initial_value(nonlocal_variable *nlv) {
    +parse_node *VariableSubjects::get_initial_value(nonlocal_variable *nlv) {
         inference *inf = VariableSubjects::get_initial_value_inference(nlv);
    -    if (inf) return World::Inferences::get_property_value(inf);
    +    if (inf) return PropertyInferences::get_value(inf);
         return Specifications::new_UNKNOWN(EMPTY_WORDING);
     }
     
     parse_node *VariableSubjects::origin_of_initial_value(nonlocal_variable *nlv) {
         inference *inf = VariableSubjects::get_initial_value_inference(nlv);
    -    if (inf) return World::Inferences::where_inferred(inf);
    +    if (inf) return Inferences::where_inferred(inf);
         return NULL;
     }
     
    diff --git a/docs/knowledge-module/5-cmw2.html b/docs/knowledge-module/5-cmw2.html
    deleted file mode 100644
    index 3131a1978..000000000
    --- a/docs/knowledge-module/5-cmw2.html
    +++ /dev/null
    @@ -1,119 +0,0 @@
    -
    -
    -	
    -		Compile Model World
    -
    -		
    -		
    -		
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -		
    -	
    -	
    -		
    -		
    - - -

    To manage the compilation of the diverse run-time arrays and/or code needed to set up the initial state of the model world.

    - -

    §1. A modest temporary array is needed to tally up the memory cost of creating -objects of given kinds, for the sake of the index: -

    - -
    -int *rough_array_memory_used = NULL;  in words, not bytes; for kinds only
    -
    -void World::Compile::set_rough_memory_usage(kind *K, int words_used) {
    -    if (K == NULL) return;
    -    if (rough_array_memory_used == NULL)
    -        internal_error("rough_array_memory_used unallocated");
    -    rough_array_memory_used[Kinds::get_construct(K)->allocation_id] = words_used;
    -}
    -
    -int World::Compile::get_rough_memory_usage(kind *K) {
    -    if (K == NULL) return 0;
    -    if (rough_array_memory_used == NULL)
    -        internal_error("rough_array_memory_used unallocated");
    -    return rough_array_memory_used[Kinds::get_construct(K)->allocation_id];
    -}
    -
    -

    §2. The actual compilation is entirely delegated: we ask if the plugins want -to write anything, then put the same question to the subjects. -

    - -
    -void World::Compile::compile(void) {
    -    Plugins::Call::compile_model_tables();
    -    int nc = NUMBER_CREATED(kind_constructor), i;
    -    rough_array_memory_used = (int *)
    -        (Memory::calloc(nc, sizeof(int), COMPILATION_SIZE_MREASON));
    -    for (i=0; i<nc; i++) rough_array_memory_used[i] = 0;
    -    InferenceSubjects::emit_all();
    -    Memory::I7_array_free(rough_array_memory_used, COMPILATION_SIZE_MREASON, nc, sizeof(int));
    -    rough_array_memory_used = NULL;
    -}
    -
    - - -
    - - - diff --git a/docs/knowledge-module/5-inf.html b/docs/knowledge-module/5-inf.html index 1cb6776be..855e240a9 100644 --- a/docs/knowledge-module/5-inf.html +++ b/docs/knowledge-module/5-inf.html @@ -83,10 +83,10 @@ function togglePopup(material_id) {
    +

    To manage the individual pieces of information gathered, with varying degrees of certainty, from assertion sentences. This is mostly information about which objects have what properties.

    -
    +

    §1. Inform reads a natural language description of a world. As it runs through, it collects together the assertions made in this description (such as "On the @@ -113,14 +113,7 @@ about X or Y. by the fact in question, besides the INFS to which it is attached.

    -

    §2. There are only two main types of inference, though plugins can and do define -further types. -

    - -
    define ARBITRARY_RELATION_INF 1  fact about an "arbitrary" relation
    -define PROPERTY_INF 2  fact about a property
    -
    -

    §3. Not all information is positive, or certain. The likelihood of something +

    §2. Not all information is positive, or certain. The likelihood of something being true is measured on the five-point *_CE scale, though an inference is never allowed to have UNKNOWN_CE status — that would tell us nothing.

    @@ -130,18 +123,87 @@ certainty". Thus there are only three absolute certainty levels: unknown, likely and certain.

    -

    §4. This is the data structure used to store a single inference. Within the -stock of facts known about a given INFS, the individual inferences are -organised as linked lists; hence the next field. -

    +
    +typedef struct inference_family {
    +    struct method_set *methods;
    +    struct text_stream *log_name;
    +    int affinity_threshold;
    +    CLASS_DEFINITION
    +} inference_family;
    +
    +inference_family *Inferences::new_family(text_stream *name, int T) {
    +    inference_family *f = CREATE(inference_family);
    +    f->methods = Methods::new_set();
    +    f->affinity_threshold = T;
    +    f->log_name = Str::duplicate(name);
    +    return f;
    +}
    +
    +
    • The structure inference_family is accessed in 4/is and here.
    +

    §3.

    + +
    enum LOG_INF_MTID
    +
    +
    +VOID_METHOD_TYPE(LOG_INF_MTID, inference_family *f, inference *inf)
    +
    +void Inferences::log_family_details(inference *inf) {
    +    VOID_METHOD_CALL(inf->family, LOG_INF_MTID, inf);
    +}
    +
    +

    §4.

    + +
    enum JOIN_INF_MTID
    +
    +
    +VOID_METHOD_TYPE(JOIN_INF_MTID, inference_family *f, inference *inf, inference_subject *infs)
    +
    +void Inferences::join_family(inference *inf, inference_subject *infs) {
    +    VOID_METHOD_CALL(inf->family, JOIN_INF_MTID, inf, infs);
    +}
    +
    +

    §5.

    + +
    enum COMPARE_INF_MTID
    +
    +
    +INT_METHOD_TYPE(COMPARE_INF_MTID, inference_family *f, inference *inf1, inference *inf2)
    +
    +int Inferences::family_specific_cmp(inference *inf1, inference *inf2) {
    +    int rv = 0;
    +    INT_METHOD_CALL(rv, inf1->family, COMPARE_INF_MTID, inf1, inf2);
    +    return rv;
    +}
    +
    +

    §6.

    + +
    enum EXPLAIN_CONTRADICTION_INF_MTID
    +
    +
    +INT_METHOD_TYPE(EXPLAIN_CONTRADICTION_INF_MTID, inference_family *f,
    +    inference *A, inference *B, int similarity, inference_subject *subj)
    +
    +int Inferences::explain_contradiction(inference *A, inference *B,
    +    int similarity, inference_subject *subj) {
    +    int rv = 0;
    +    INT_METHOD_CALL(rv, A->family, EXPLAIN_CONTRADICTION_INF_MTID, A, B, similarity, subj);
    +    return rv;
    +}
    +
    +

    §7.

    + +
    +void Inferences::start(void) {
    +    Plugins::Call::create_inference_families();
    +}
    +
    +

    §8.

     typedef struct inference {
    -    int inference_type;  see above
    +    inference_family *family;  see above
         int certainty;  see above
    -    struct parse_node *inferred_from;  from what sentence was this drawn?
    -    int added_in_construction;  or was this drawn during the model completion stage?
    -    int inference_timestamp;
    +    general_pointer data;
     
         struct inference_subject *infs_ref1;  from 0 to 2 other INFSs are connected by this inference
         struct inference_subject *infs_ref2;
    @@ -149,74 +211,57 @@ organised as linked lists; hence the     struct parse_node *spec_ref1;  used by dynamic relations between non-subjects
         struct parse_node *spec_ref2;
     
    -    struct property *inferred_property;  property referred to, if any
    -    struct parse_node *inferred_property_value;  and its value, if any
    -
    -    struct inference *next;  next in list of inferences on same subject
    +    struct parse_node *inferred_from;  from what sentence was this drawn?
    +    int drawn_during_stage;  or was this drawn during the model completion stage?
         CLASS_DEFINITION
     } inference;
     
    -
    • The structure inference is accessed in 3/ps, 3/cp, 4/is and here.
    -

    §5. Creation. The following routine coins a newly minted inference which is not yet attached +

    • The structure inference is accessed in 1/ap, 2/iaa, 3/ep, 5/pi and here.
    +

    §9. Creation. The following routine coins a newly minted inference which is not yet attached to any subject: but it will not stay unattached for long. Note that if nothing has been said about likelihood, the sentence is assumed to be factually certain.

    -int inference_timer = 0;
    -
    -inference *World::Inferences::create_inference(int type, int certitude) {
    +inference *Inferences::create_inference(inference_family *f, general_pointer data,
    +    int certitude) {
         PROTECTED_MODEL_PROCEDURE;
    +    if (f == NULL) internal_error("inference orphaned");
         if (certitude == UNKNOWN_CE) certitude = CERTAIN_CE;
         inference *new_i;
         new_i = CREATE(inference);
    -    new_i->inference_timestamp = inference_timer++;
    -    new_i->inference_type = type;
    +    new_i->family = f;
    +    new_i->data = data;
         new_i->certainty = certitude;
         new_i->infs_ref1 = NULL; new_i->infs_ref2 = NULL;
         new_i->spec_ref1 = NULL; new_i->spec_ref2 = NULL;
    -    new_i->inferred_property = NULL;
    -    new_i->inferred_property_value = NULL;
         new_i->inferred_from = current_sentence;
    -    new_i->added_in_construction = Task::is_during_stage(MODEL_COMPLETE_CSEQ);
    -    new_i->next = NULL;
    +    new_i->drawn_during_stage = World::current_building_stage();
         return new_i;
     }
     
    -

    §6. Here are our two core inference types: +

    §10. Here are our two core inference types:

    -inference *World::Inferences::create_property_inference(inference_subject *infs,
    -    property *prn, parse_node *val) {
    +inference *Inferences::create_relation_inference(inference_subject *infs0, inference_subject *infs1) {
         PROTECTED_MODEL_PROCEDURE;
    -    inference *i = World::Inferences::create_inference(PROPERTY_INF, prevailing_mood);
    -    if (prevailing_mood == UNKNOWN_CE)
    -        i->certainty = InferenceSubjects::get_default_certainty(infs);
    -    i->inferred_property = prn;
    -    i->inferred_property_value = val;
    -    if (prn == NULL) internal_error("null property inference");
    +    inference *i = Inferences::create_inference(arbitrary_relation_inf, NULL_GENERAL_POINTER, prevailing_mood);
    +    i->infs_ref1 = Inferences::divert_infs(infs0);
    +    i->infs_ref2 = Inferences::divert_infs(infs1);
         return i;
     }
     
    -inference *World::Inferences::create_relation_inference(inference_subject *infs0, inference_subject *infs1) {
    +inference *Inferences::create_relation_inference_spec(parse_node *spec0, parse_node *spec1) {
         PROTECTED_MODEL_PROCEDURE;
    -    inference *i = World::Inferences::create_inference(ARBITRARY_RELATION_INF, prevailing_mood);
    -    i->infs_ref1 = World::Inferences::divert_infs(infs0);
    -    i->infs_ref2 = World::Inferences::divert_infs(infs1);
    -    return i;
    -}
    -
    -inference *World::Inferences::create_relation_inference_spec(parse_node *spec0, parse_node *spec1) {
    -    PROTECTED_MODEL_PROCEDURE;
    -    inference *i = World::Inferences::create_inference(ARBITRARY_RELATION_INF, prevailing_mood);
    +    inference *i = Inferences::create_inference(arbitrary_relation_inf, NULL_GENERAL_POINTER, prevailing_mood);
         i->spec_ref1 = spec0;
         i->spec_ref2 = spec1;
         if ((spec0 == NULL) || (spec1 == NULL)) internal_error("malformed specified relation");
         return i;
     }
     
    -

    §7. Drawing inferences. This is how the rest of Inform records fresh information about the world +

    §11. Drawing inferences. This is how the rest of Inform records fresh information about the world model. To "draw" an inference is to create it as a structure and then "join" it to the list of facts already known about its subject. (This might not actually accept it; it might be redundant, or contradictory.) @@ -226,134 +271,106 @@ might not actually accept it; it might be redundant, or contradictory.)

    -void World::Inferences::draw_property(inference_subject *infs,
    -    property *prn, parse_node *val) {
    -    inference *i = World::Inferences::create_property_inference(infs, prn, val);
    -    World::Inferences::join_inference(i, infs);
    -}
    -
    -void World::Inferences::draw_negated_property(inference_subject *infs,
    -    property *prn, parse_node *val) {
    -    inference *i = World::Inferences::create_property_inference(infs, prn, val);
    -    i->certainty = -i->certainty;
    -    World::Inferences::join_inference(i, infs);
    -}
    -
    -inference_subject *World::Inferences::bp_as_subject(binary_predicate *bp) {
    +inference_subject *Inferences::bp_as_subject(binary_predicate *bp) {
         return bp->knowledge_about_bp;
     }
     
    -void World::Inferences::draw_relation(binary_predicate *bp,
    +void Inferences::draw_relation(binary_predicate *bp,
         inference_subject *infs0, inference_subject *infs1) {
    -    inference *i = World::Inferences::create_relation_inference(infs0, infs1);
    -    World::Inferences::join_inference(i, World::Inferences::bp_as_subject(bp));
    +    inference *i = Inferences::create_relation_inference(infs0, infs1);
    +    Inferences::join_inference(i, Inferences::bp_as_subject(bp));
     }
     
    -void World::Inferences::draw_relation_spec(binary_predicate *bp,
    +void Inferences::draw_relation_spec(binary_predicate *bp,
         parse_node *spec0, parse_node *spec1) {
    -    inference *i = World::Inferences::create_relation_inference_spec(spec0, spec1);
    -    World::Inferences::join_inference(i, World::Inferences::bp_as_subject(bp));
    +    inference *i = Inferences::create_relation_inference_spec(spec0, spec1);
    +    Inferences::join_inference(i, Inferences::bp_as_subject(bp));
     }
     
    -

    §8. And an all-purpose routine provided for plugins to draw customised +

    §12. And an all-purpose routine provided for plugins to draw customised inferences of their own:

    -void World::Inferences::draw(int type, inference_subject *about,
    +void Inferences::draw(inference_family *f, inference_subject *about,
         int certitude, inference_subject *infs0, inference_subject *infs1) {
    -    inference *i = World::Inferences::create_inference(type, certitude);
    -    i->infs_ref1 = World::Inferences::divert_infs(infs0); i->infs_ref2 = World::Inferences::divert_infs(infs1);
    -    World::Inferences::join_inference(i, about);
    +    inference *i = Inferences::create_inference(f, NULL_GENERAL_POINTER, certitude);
    +    i->infs_ref1 = Inferences::divert_infs(infs0); i->infs_ref2 = Inferences::divert_infs(infs1);
    +    Inferences::join_inference(i, about);
     }
     
    -

    §9. Reading inference data. Once drawn, inferences are read-only, and the following access routines +

    §13. Reading inference data. Once drawn, inferences are read-only, and the following access routines allow them to be read.

    -int World::Inferences::get_timestamp(inference *i) {
    -    return i->inference_timestamp;
    +inference_family *Inferences::get_inference_type(inference *i) {
    +    return i->family;
     }
     
    -int World::Inferences::get_inference_type(inference *i) {
    -    return i->inference_type;
    -}
    -
    -parse_node *World::Inferences::where_inferred(inference *i) {
    +parse_node *Inferences::where_inferred(inference *i) {
         return i->inferred_from;
     }
     
    -int World::Inferences::get_certainty(inference *i) {
    +int Inferences::get_certainty(inference *i) {
         return i->certainty;
     }
     
    -void World::Inferences::set_certainty(inference *i, int ce) {
    +void Inferences::set_certainty(inference *i, int ce) {
         i->certainty = ce;
     }
     
    -int World::Inferences::added_in_construction(inference *i) {
    -    return i->added_in_construction;
    -}
    -
    -property *World::Inferences::get_property(inference *i) {
    -    return i->inferred_property;
    -}
    -
    -parse_node *World::Inferences::get_property_value(inference *i) {
    -    return i->inferred_property_value;
    -}
    -
    -parse_node *World::Inferences::set_property_value_kind(inference *i, kind *K) {
    -    Node::set_kind_of_value(i->inferred_property_value, K);
    -    return i->inferred_property_value;
    +int Inferences::during_stage(inference *i) {
    +    return i->drawn_during_stage;
     }
     
    -

    §10. Core Inform deals only in INFSs, but plugins often use inferences concerned +

    §14. Core Inform deals only in INFSs, but plugins often use inferences concerned only with objects (e.g., for the map), so we also provide a convenient abbreviated way to extract just reference 1 in object form.

    -void World::Inferences::get_references(inference *i,
    +void Inferences::get_references(inference *i,
         inference_subject **infs1, inference_subject **infs2) {
         if (infs1) *infs1 = i->infs_ref1; if (infs2) *infs2 = i->infs_ref2;
     }
     
    -void World::Inferences::get_references_spec(inference *i,
    +void Inferences::get_references_spec(inference *i,
         parse_node **spec1, parse_node **spec2) {
         *spec1 = i->spec_ref1; *spec2 = i->spec_ref2;
     }
     
    -instance *World::Inferences::get_reference_as_object(inference *i) {
    +instance *Inferences::get_reference_as_object(inference *i) {
         return InstanceSubjects::to_object_instance(i->infs_ref1);
     }
     
    -

    §11. Looping over inferences. The following macro prototypes show how to loop through all of the inferences +

    §15. Looping over inferences. The following macro prototypes show how to loop through all of the inferences known concerning a given inference subject, and of a given type. "Positive" knowledge means that the inferences must have a certainty of likely or better.

    define POSITIVE_KNOWLEDGE_LOOP(inf, infs, type)
    -    for (inf = (infs)?(InferenceSubjects::get_inferences(World::Inferences::divert_infs(infs))):NULL; inf; inf = inf->next)
    -        if ((inf->inference_type == type) && (inf->certainty > 0))
    +    LOOP_OVER_LINKED_LIST(inf, inference,
    +        (infs)?(InferenceSubjects::get_inferences(Inferences::divert_infs(infs))):NULL)
    +        if ((inf->family == type) && (inf->certainty > 0))
     define KNOWLEDGE_LOOP(inf, infs, type)
    -    for (inf = (infs)?(InferenceSubjects::get_inferences(World::Inferences::divert_infs(infs))):NULL; inf; inf = inf->next)
    -        if (inf->inference_type == type)
    +    LOOP_OVER_LINKED_LIST(inf, inference,
    +        (infs)?(InferenceSubjects::get_inferences(Inferences::divert_infs(infs))):NULL)
    +        if (inf->family == type)
     
    -

    §12. Finding property states.

    +

    §16. Finding property states.

    -int World::Inferences::get_EO_state(inference_subject *infs, property *prn) {
    +int Inferences::get_EO_state(inference_subject *infs, property *prn) {
         if ((prn == NULL) || (infs == NULL)) return UNKNOWN_CE;
         inference_subject *k;
         property *prnbar = NULL;
         if (Properties::is_either_or(prn)) prnbar = Properties::EitherOr::get_negation(prn);
         for (k = infs; k; k = InferenceSubjects::narrowest_broader_subject(k)) {
             inference *inf;
    -        KNOWLEDGE_LOOP(inf, k, PROPERTY_INF) {
    -            property *known = World::Inferences::get_property(inf);
    -            int c = World::Inferences::get_certainty(inf);
    +        KNOWLEDGE_LOOP(inf, k, property_inf) {
    +            property *known = PropertyInferences::get_property(inf);
    +            int c = Inferences::get_certainty(inf);
                 if (known) {
                     if ((prn == known) && (c != UNKNOWN_CE)) return c;
                     if ((prnbar == known) && (c != UNKNOWN_CE)) return -c;
    @@ -363,21 +380,21 @@ knowledge means that the inferences must have a certainty of likely or better.
         return UNKNOWN_CE;
     }
     
    -int World::Inferences::get_EO_state_without_inheritance(inference_subject *infs, property *prn, parse_node **where) {
    +int Inferences::get_EO_state_without_inheritance(inference_subject *infs, property *prn, parse_node **where) {
         if ((prn == NULL) || (infs == NULL)) return UNKNOWN_CE;
         property *prnbar = NULL;
         if (Properties::is_either_or(prn)) prnbar = Properties::EitherOr::get_negation(prn);
         inference *inf;
    -    KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
    -        property *known = World::Inferences::get_property(inf);
    -        int c = World::Inferences::get_certainty(inf);
    +    KNOWLEDGE_LOOP(inf, infs, property_inf) {
    +        property *known = PropertyInferences::get_property(inf);
    +        int c = Inferences::get_certainty(inf);
             if (known) {
                 if ((prn == known) && (c != UNKNOWN_CE)) {
    -                if (where) *where = World::Inferences::where_inferred(inf);
    +                if (where) *where = Inferences::where_inferred(inf);
                     return c;
                 }
                 if ((prnbar == known) && (c != UNKNOWN_CE)) {
    -                if (where) *where = World::Inferences::where_inferred(inf);
    +                if (where) *where = Inferences::where_inferred(inf);
                     return -c;
                 }
             }
    @@ -385,11 +402,11 @@ knowledge means that the inferences must have a certainty of likely or better.
         return UNKNOWN_CE;
     }
     
    -void World::Inferences::verify_prop_states(inference_subject *infs) {
    +void Inferences::verify_prop_states(inference_subject *infs) {
         inference *inf;
    -    POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
    -        property *prn = World::Inferences::get_property(inf);
    -        parse_node *val = World::Inferences::get_property_value(inf);
    +    POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) {
    +        property *prn = PropertyInferences::get_property(inf);
    +        parse_node *val = PropertyInferences::get_value(inf);
             kind *PK = Properties::Valued::kind(prn);
             kind *VK = Specifications::to_kind(val);
             if (Kinds::compatible(VK, PK) != ALWAYS_MATCH) {
    @@ -409,60 +426,60 @@ knowledge means that the inferences must have a certainty of likely or better.
         }
     }
     
    -parse_node *World::Inferences::get_prop_state(inference_subject *infs, property *prn) {
    +parse_node *Inferences::get_prop_state(inference_subject *infs, property *prn) {
         if ((prn == NULL) || (infs == NULL)) return NULL;
         inference_subject *k;
         for (k = infs; k; k = InferenceSubjects::narrowest_broader_subject(k)) {
             inference *inf;
    -        POSITIVE_KNOWLEDGE_LOOP(inf, k, PROPERTY_INF) {
    -            property *known = World::Inferences::get_property(inf);
    -            if (known == prn) return World::Inferences::get_property_value(inf);
    +        POSITIVE_KNOWLEDGE_LOOP(inf, k, property_inf) {
    +            property *known = PropertyInferences::get_property(inf);
    +            if (known == prn) return PropertyInferences::get_value(inf);
             }
         }
         return NULL;
     }
     
    -parse_node *World::Inferences::get_prop_state_at(inference_subject *infs, property *prn,
    +parse_node *Inferences::get_prop_state_at(inference_subject *infs, property *prn,
         parse_node **where) {
         if ((prn == NULL) || (infs == NULL)) return NULL;
         inference_subject *k;
         for (k = infs; k; k = InferenceSubjects::narrowest_broader_subject(k)) {
             inference *inf;
    -        POSITIVE_KNOWLEDGE_LOOP(inf, k, PROPERTY_INF) {
    -            property *known = World::Inferences::get_property(inf);
    +        POSITIVE_KNOWLEDGE_LOOP(inf, k, property_inf) {
    +            property *known = PropertyInferences::get_property(inf);
                 if (known == prn) {
    -                if (where) *where = World::Inferences::where_inferred(inf);
    -                return World::Inferences::get_property_value(inf);
    +                if (where) *where = Inferences::where_inferred(inf);
    +                return PropertyInferences::get_value(inf);
                 }
             }
         }
         return NULL;
     }
     
    -parse_node *World::Inferences::get_prop_state_without_inheritance(inference_subject *infs,
    +parse_node *Inferences::get_prop_state_without_inheritance(inference_subject *infs,
         property *prn, parse_node **where) {
         if ((prn == NULL) || (infs == NULL)) return NULL;
         inference *inf;
    -    POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
    -        property *known = World::Inferences::get_property(inf);
    +    POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) {
    +        property *known = PropertyInferences::get_property(inf);
             if (known == prn) {
    -            if (where) *where = World::Inferences::where_inferred(inf);
    -            return World::Inferences::get_property_value(inf);
    +            if (where) *where = Inferences::where_inferred(inf);
    +            return PropertyInferences::get_value(inf);
             }
         }
         return NULL;
     }
     
    -

    §13. Indexing properties of a subject. This is where the detailed description of a given kind — what properties it +

    §17. Indexing properties of a subject. This is where the detailed description of a given kind — what properties it has, and so on — is generated.

    -void World::Inferences::index(OUTPUT_STREAM, inference_subject *infs, int brief) {
    +void Inferences::index(OUTPUT_STREAM, inference_subject *infs, int brief) {
         inference *inf;
    -    KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF)
    -        if (World::Inferences::get_property(inf) == P_specification) {
    -            parse_node *spec = World::Inferences::get_property_value(inf);
    +    KNOWLEDGE_LOOP(inf, infs, property_inf)
    +        if (PropertyInferences::get_property(inf) == P_specification) {
    +            parse_node *spec = PropertyInferences::get_value(inf);
                 Index::dequote(OUT, Lexer::word_raw_text(Wordings::first_wn(Node::get_text(spec))));
                 HTML_TAG("br");
             }
    @@ -481,19 +498,19 @@ has, and so on — is generated.
                 case IMPOSSIBLE_CE: cert = "Never"; break;
                 case INITIALLY_CE:  cert = "Initially"; break;
             }
    -        World::Inferences::index_provided(OUT, infs, TRUE, c, cert, brief);
    +        Inferences::index_provided(OUT, infs, TRUE, c, cert, brief);
         }
    -    World::Inferences::index_provided(OUT, infs, FALSE, LIKELY_CE, "Can have", brief);
    +    Inferences::index_provided(OUT, infs, FALSE, LIKELY_CE, "Can have", brief);
     }
     
    -

    §14. The following lists off the properties of the kind, with the given +

    §18. The following lists off the properties of the kind, with the given state of being boolean, and the given certainty levels:

    -int World::Inferences::has_or_can_have(inference_subject *infs, property *prn) {
    +int Inferences::has_or_can_have(inference_subject *infs, property *prn) {
         if (Properties::is_either_or(prn)) {
    -        int has = World::Inferences::get_EO_state(infs, prn);
    +        int has = Inferences::get_EO_state(infs, prn);
             if ((has == UNKNOWN_CE) && (World::Permissions::find(infs, prn, TRUE))) {
                 if (Properties::EitherOr::stored_in_negation(prn))
                     return LIKELY_CE;
    @@ -506,7 +523,7 @@ state of being boolean, and the given certainty levels:
         return UNKNOWN_CE;
     }
     
    -void World::Inferences::index_provided(OUTPUT_STREAM, inference_subject *infs, int bool, int c, char *cert, int brief) {
    +void Inferences::index_provided(OUTPUT_STREAM, inference_subject *infs, int bool, int c, char *cert, int brief) {
         int f = TRUE;
         property *prn;
         LOOP_OVER(prn, property) {
    @@ -514,9 +531,9 @@ state of being boolean, and the given certainty levels:
             if (Properties::get_indexed_already_flag(prn)) continue;
             if (Properties::is_either_or(prn) != bool) continue;
     
    -        int state = World::Inferences::has_or_can_have(infs, prn);
    +        int state = Inferences::has_or_can_have(infs, prn);
             if (state != c) continue;
    -        int inherited_state = World::Inferences::has_or_can_have(
    +        int inherited_state = Inferences::has_or_can_have(
                 InferenceSubjects::narrowest_broader_subject(infs), prn);
             if ((state == inherited_state) && (brief)) continue;
     
    @@ -544,18 +561,18 @@ state of being boolean, and the given certainty levels:
         }
     }
     
    -

    §15. Indexing properties of a specific subject. This only tells about specific property settings for a given instance. +

    §19. Indexing properties of a specific subject. This only tells about specific property settings for a given instance.

    -void World::Inferences::index_specific(OUTPUT_STREAM, inference_subject *infs) {
    +void Inferences::index_specific(OUTPUT_STREAM, inference_subject *infs) {
         property *prn; int k = 0;
         LOOP_OVER(prn, property)
             if (Properties::is_shown_in_index(prn))
                 if (Properties::is_either_or(prn)) {
                     if (World::Permissions::find(infs, prn, TRUE)) {
                         parse_node *P = NULL;
    -                    int S = World::Inferences::get_EO_state_without_inheritance(infs, prn, &P);
    +                    int S = Inferences::get_EO_state_without_inheritance(infs, prn, &P);
                         property *prnbar = Properties::EitherOr::get_negation(prn);
                         if ((prnbar) && (S < 0)) continue;
                         if (S != UNKNOWN_CE) {
    @@ -574,7 +591,7 @@ state of being boolean, and the given certainty levels:
                 if (Properties::is_either_or(prn) == FALSE)
                     if (World::Permissions::find(infs, prn, TRUE)) {
                         parse_node *P = NULL;
    -                    parse_node *S = World::Inferences::get_prop_state_without_inheritance(infs, prn, &P);
    +                    parse_node *S = Inferences::get_prop_state_without_inheritance(infs, prn, &P);
                         if ((S) && (Wordings::nonempty(Node::get_text(S)))) {
                             HTML::open_indented_p(OUT, 1, "hanging");
                             WRITE("%+W: ", prn->name);
    @@ -587,14 +604,14 @@ state of being boolean, and the given certainty levels:
                     }
     }
     
    -

    §16. Comparing inferences. The following routine is a little like strcmp, the standard C routine +

    §20. Comparing inferences. The following routine is a little like strcmp, the standard C routine for comparing strings, in that it compares two inferences and returns a value useful for sorting algorithms: 0 if equal, positive if i1 < i2, negative if i2 < i1. This is a stable trichotomy; in particular,

    -    World::Inferences::compare_inferences(I, J) == -World::Inferences::compare_inferences(J, I)
    +    Inferences::compare_inferences(I, J) == -Inferences::compare_inferences(J, I)
     

    for all pairs of inference pointers I and J.

    @@ -622,7 +639,7 @@ same property but with different values. define CI_DIFFER_IN_COPY_ONLY 7 define CI_IDENTICAL 0
    -

    §17. Funny story: until 2019, this routine ran by using pointer subtraction when +

    §21. Funny story: until 2019, this routine ran by using pointer subtraction when comparing, for example, the INFS references in the inferences, on the principle that the ordering doesn't really matter so long as it is definite and stable during a run. But in the late 2010s, desktop operating systems such as MacOS @@ -640,66 +657,61 @@ was probably a good thing.

    -int World::Inferences::compare_inferences(inference *i1, inference *i2) {
    +int Inferences::compare_inferences(inference *i1, inference *i2) {
    +	PRINT("%S %S on %d %d\n", i1->family->log_name, i2->family->log_name, i1->allocation_id, i2->allocation_id);
    +    int c = Inferences::compare_inferencesi(i1, i2);
    +	PRINT("= %d\n", c);
    +    return c;
    +}
    +int Inferences::compare_inferencesi(inference *i1, inference *i2) {
         if (i1 == i2) return CI_IDENTICAL;
         if (i1 == NULL) return CI_DIFFER_IN_EXISTENCE;
         if (i2 == NULL) return -CI_DIFFER_IN_EXISTENCE;
    -    int c = i1->inference_type - i2->inference_type;
    +    int c = i1->family->allocation_id - i2->family->allocation_id;
         if (c > 0) return CI_DIFFER_IN_TYPE; if (c < 0) return -CI_DIFFER_IN_TYPE;
    -    property *pr1 = i1->inferred_property;
    -    property *pr2 = i2->inferred_property;
    -    if ((pr1) && (Properties::is_either_or(pr1)) &&
    -        (pr2) && (Properties::is_either_or(pr2)) &&
    -        ((pr1 == Properties::EitherOr::get_negation(pr2)) ||
    -         (pr2 == Properties::EitherOr::get_negation(pr1)))) pr2 = pr1;
    -    c = World::Inferences::measure_property(pr1) - World::Inferences::measure_property(pr2);
    -    if (c > 0) return CI_DIFFER_IN_PROPERTY; if (c < 0) return -CI_DIFFER_IN_PROPERTY;
    -    c = World::Inferences::measure_infs(i1->infs_ref2) - World::Inferences::measure_infs(i2->infs_ref2);
    +
    +    c = Inferences::family_specific_cmp(i1, i2); if (c != 0) return c;
    +
    +    c = Inferences::measure_infs(i1->infs_ref2) - Inferences::measure_infs(i2->infs_ref2);
         if (c > 0) return CI_DIFFER_IN_INFS2; if (c < 0) return -CI_DIFFER_IN_INFS2;
    -    c = World::Inferences::measure_infs(i1->infs_ref1) - World::Inferences::measure_infs(i2->infs_ref1);
    +    c = Inferences::measure_infs(i1->infs_ref1) - Inferences::measure_infs(i2->infs_ref1);
         if (c > 0) return CI_DIFFER_IN_INFS1; if (c < 0) return -CI_DIFFER_IN_INFS1;
    -    c = World::Inferences::measure_pn(i1->spec_ref2) - World::Inferences::measure_pn(i2->spec_ref2);
    +    c = Inferences::measure_pn(i1->spec_ref2) - Inferences::measure_pn(i2->spec_ref2);
         if (c > 0) return CI_DIFFER_IN_INFS2; if (c < 0) return -CI_DIFFER_IN_INFS2;
    -    c = World::Inferences::measure_pn(i1->spec_ref1) - World::Inferences::measure_pn(i2->spec_ref1);
    +    c = Inferences::measure_pn(i1->spec_ref1) - Inferences::measure_pn(i2->spec_ref1);
         if (c > 0) return CI_DIFFER_IN_INFS1; if (c < 0) return -CI_DIFFER_IN_INFS1;
    -    c = World::Inferences::measure_inf(i1) - World::Inferences::measure_inf(i2);
    -    parse_node *val1 = i1->inferred_property_value;
    -    parse_node *val2 = i2->inferred_property_value;
    -    if ((i1->inferred_property != i2->inferred_property) ||
    -        ((val1) && (val2) && (Rvalues::compare_CONSTANT(val1, val2) == FALSE))) {
    -        if (c > 0) return CI_DIFFER_IN_PROPERTY_VALUE;
    -        if (c < 0) return -CI_DIFFER_IN_PROPERTY_VALUE;
    -    }
    +    c = Inferences::measure_inf(i1) - Inferences::measure_inf(i2);
    +
         if (c > 0) return CI_DIFFER_IN_COPY_ONLY; if (c < 0) return -CI_DIFFER_IN_COPY_ONLY;
         return CI_IDENTICAL;
     }
     
    -int World::Inferences::measure_property(property *P) {
    +int Inferences::measure_property(property *P) {
         if (P) return 1 + P->allocation_id;
         return 0;
     }
    -int World::Inferences::measure_inf(inference *I) {
    +int Inferences::measure_inf(inference *I) {
         if (I) return 1 + I->allocation_id;
         return 0;
     }
    -int World::Inferences::measure_infs(inference_subject *IS) {
    +int Inferences::measure_infs(inference_subject *IS) {
         if (IS) return 1 + IS->allocation_id;
         return 0;
     }
    -int World::Inferences::measure_pn(parse_node *N) {
    +int Inferences::measure_pn(parse_node *N) {
         if (N) return 1 + N->allocation_id;
         return 0;
     }
     
     int infs_diversion = TRUE;
    -void World::Inferences::diversion_on(void) {
    +void Inferences::diversion_on(void) {
         infs_diversion = TRUE;
     }
    -void World::Inferences::diversion_off(void) {
    +void Inferences::diversion_off(void) {
         infs_diversion = FALSE;
     }
     
    -inference_subject *World::Inferences::divert_infs(inference_subject *infs) {
    +inference_subject *Inferences::divert_infs(inference_subject *infs) {
         #ifdef IF_MODULE
         if (infs_diversion)
             if ((I_yourself) && (player_VAR) &&
    @@ -712,7 +724,7 @@ was probably a good thing.
         return infs;
     }
     
    -

    §18. Joining an inference to what is known about an object. As the above will have made clear, it is not altogether easy to join a new +

    §22. Joining an inference to what is known about an object. As the above will have made clear, it is not altogether easy to join a new inference to the linked list of inferences which belong to a given subject: we can't simply put it at the end of the list. The following routine looks simple enough, but was a difficult one to get right. @@ -724,51 +736,51 @@ then the routine exits without completing the loop.

    -void World::Inferences::join_inference(inference *i, inference_subject *infs) {
    +void Inferences::join_inference(inference *i, inference_subject *infs) {
         PROTECTED_MODEL_PROCEDURE;
         if (i == NULL) internal_error("joining null inference");
         if (infs == NULL) internal_error("joining to null inference subject");
     
    -    infs = World::Inferences::divert_infs(infs);
    +    infs = Inferences::divert_infs(infs);
     
         int inserted = FALSE;
    -    inference *list, *prev;
    -    for (prev = NULL, list = InferenceSubjects::get_inferences(infs);
    -        (list) && (inserted == FALSE); prev = list, list = list->next) {
    +    linked_list *SL = InferenceSubjects::get_inferences(infs);
    +    inference *list, *prev = NULL;
    +    int pos = 0;
    +    LOOP_OVER_LINKED_LIST(list, inference, SL)
    +        if (inserted == FALSE) {
    +            int c = Inferences::compare_inferences(i, list);
    +            int d = c; if (d < 0) d = -d;
    +            int icl = i->certainty; if (icl < 0) icl = -icl;
    +            int lcl = list->certainty; if (lcl < 0) lcl = -lcl;
     
    -        int c = World::Inferences::compare_inferences(i, list);
    -        int d = c; if (d < 0) d = -d;
    -        int icl = i->certainty; if (icl < 0) icl = -icl;
    -        int lcl = list->certainty; if (lcl < 0) lcl = -lcl;
    +            int affinity_threshold;
    +            Determine the affinity threshold, which depends on the inference type22.2;
    +            if (d >= affinity_threshold) {
    +                These relate to the same basic fact and one must exclude the other22.3;
    +                return;
    +            }
     
    -        int affinity_threshold;
    -        Determine the affinity threshold, which depends on the inference type18.2;
    -        if (d >= affinity_threshold) {
    -            These relate to the same basic fact and one must exclude the other18.3;
    -            return;
    +            if (c<0) Insert the newly-drawn inference before this list position22.1;
    +            pos++; prev = list;
             }
    +    if (inserted == FALSE) Insert the newly-drawn inference before this list position22.1;
     
    -        if (c<0) Insert the newly-drawn inference before this list position18.1;
    -    }
    -    if (inserted == FALSE) Insert the newly-drawn inference before this list position18.1;
    -
    -    World::Inferences::report_inference(i, infs, "drawn");
    -    if (i->inference_type == PROPERTY_INF)
    -        Plugins::Call::property_value_notify(
    -            i->inferred_property, i->inferred_property_value);
    +    Inferences::report_inference(i, infs, "drawn");
    +    Inferences::join_family(i, infs);
     }
     
    -

    §18.1. Insert the newly-drawn inference before this list position18.1 = +

    §22.1. Insert the newly-drawn inference before this list position22.1 =

    -    if (prev == NULL) InferenceSubjects::set_inferences(infs, i); else prev->next = i;
    -    i->next = list; inserted = TRUE;
    +    LinkedLists::insert(SL, pos, i);
    +    inserted = TRUE;
     
    -
    • This code is used in §18 (twice).
    -

    §18.2. The first question we must answer is when our two inferences are talking +

    • This code is used in §22 (twice).
    +

    §22.2. The first question we must answer is when our two inferences are talking about what is basically the same fact. We do this by requiring that the -absolute value of the World::Inferences::compare_inferences score — which will always be +absolute value of the Inferences::compare_inferences score — which will always be one of the CI_* constants enumerated above — must exceed some threshold. (Recall that higher scores mean greater similarity; the perfect CI_IDENTICAL is not possible here.) @@ -779,7 +791,7 @@ always at least half-way down the list, so we can be certain that

    -    i->inference_type == list->inference_type
    +    i->family == list->family
     

    (and therefore it's unambiguous what we mean by the type of inference being looked at). For two property inferences to be talking about the same fact, @@ -794,55 +806,50 @@ never talk about the same fact unless they're essentially identical. belonging to plugins (at present, anyway).

    -

    Determine the affinity threshold, which depends on the inference type18.2 = +

    Determine the affinity threshold, which depends on the inference type22.2 =

    -    switch (list->inference_type) {
    -        case PROPERTY_INF: affinity_threshold = CI_DIFFER_IN_PROPERTY_VALUE; break;
    -        case ARBITRARY_RELATION_INF: affinity_threshold = CI_DIFFER_IN_COPY_ONLY; break;
    -        default: affinity_threshold = CI_DIFFER_IN_INFS1; break;
    -    }
    +    affinity_threshold = list->family->affinity_threshold;
     
    -
    • This code is used in §18.
    -

    §18.3. So, let's suppose our new inference i is sufficiently close to the our +

    • This code is used in §22.
    +

    §22.3. So, let's suppose our new inference i is sufficiently close to the our existing one, list. What then?

    -

    These relate to the same basic fact and one must exclude the other18.3 = +

    These relate to the same basic fact and one must exclude the other22.3 =

    -    if (icl != lcl) They have different certainties, so take the more certain to be true18.3.1
    +    if (icl != lcl) They have different certainties, so take the more certain to be true22.3.1
         else {
             int contradiction_flag = FALSE;
    -        They are equally certain, so determine whether or not they contradict each other18.3.2;
    +        They are equally certain, so determine whether or not they contradict each other22.3.2;
             if (contradiction_flag) {
    -            if (icl == CERTAIN_CE) Contradictions of certainty are forbidden, so issue a problem18.3.3;
    +            if (icl == CERTAIN_CE) Contradictions of certainty are forbidden, so issue a problem22.3.3;
                 if ((icl == LIKELY_CE) && (InferenceSubjects::get_default_certainty(infs) == LIKELY_CE))
    -                Later uncertain data beats earlier, for subjects which generalise about whole domains18.3.4;
    +                Later uncertain data beats earlier, for subjects which generalise about whole domains22.3.4;
             }
    -        World::Inferences::report_inference(i, infs, "redundant");
    +        Inferences::report_inference(i, infs, "redundant");
         }
     
    -
    • This code is used in §18.
    -

    §18.3.1. Where: +

    • This code is used in §22.
    +

    §22.3.1. Where:

    -

    They have different certainties, so take the more certain to be true18.3.1 = +

    They have different certainties, so take the more certain to be true22.3.1 =

         if (lcl > icl) {
    -        World::Inferences::report_inference(i, infs, "discarded (we already know better)");
    +        Inferences::report_inference(i, infs, "discarded (we already know better)");
         } else {
    -        i->next = list->next;
    -        if (prev == NULL) InferenceSubjects::set_inferences(infs, i); else prev->next = i;
    -        World::Inferences::report_inference(i, infs, "replaced existing less certain one");
    +        LinkedLists::set_entry(pos, SL, i);
    +        Inferences::report_inference(i, infs, "replaced existing less certain one");
         }
     
    - -

    §18.3.2. Note that certainties opposite in sign reverse the issue of whether a +

    +

    §22.3.2. Note that certainties opposite in sign reverse the issue of whether a contradiction has occurred. The following, after all, do not conflict:

    @@ -859,142 +866,76 @@ are always required to be positive in sense, i.e., with positive certainty, and so clashed are impossible.)

    -

    They are equally certain, so determine whether or not they contradict each other18.3.2 = +

    They are equally certain, so determine whether or not they contradict each other22.3.2 =

    -    switch (list->inference_type) {
    -        case PROPERTY_INF:
    -            if (d == CI_DIFFER_IN_PROPERTY_VALUE) contradiction_flag = TRUE;
    -            break;
    -        default:
    -            if (Plugins::Call::inferences_contradict(list, i, d)) contradiction_flag = TRUE;
    -            break;
    +    if (list->family == property_inf) {
    +        if (d == CI_DIFFER_IN_PROPERTY_VALUE) contradiction_flag = TRUE;
    +    } else {
    +        if (Plugins::Call::inferences_contradict(list, i, d)) contradiction_flag = TRUE;
         }
     
         if (list->certainty == -i->certainty) contradiction_flag = (contradiction_flag)?FALSE:TRUE;
     
    - -

    §18.3.3. Contradictions of certainty are forbidden, so issue a problem18.3.3 = +

    +

    §22.3.3. Contradictions of certainty are forbidden, so issue a problem22.3.3 =

    -    World::Inferences::report_inference(i, infs, "contradiction");
    -    World::Inferences::report_inference(list, infs, "with");
    -    if ((list->inference_type != PROPERTY_INF) &&
    -        (list->inference_type != ARBITRARY_RELATION_INF) &&
    +    Inferences::report_inference(i, infs, "contradiction");
    +    Inferences::report_inference(list, infs, "with");
    +	if ((list->family != property_inf) &&
    +        (list->family != arbitrary_relation_inf) &&
             (Plugins::Call::explain_contradiction(list, i, d, infs))) return;
    -    if (i->inference_type == PROPERTY_INF) {
    -        if (i->inferred_property == P_variable_initial_value)
    -        StandardProblems::two_sentences_problem(_p_(PM_VariableContradiction),
    -            list->inferred_from,
    -            "this looks like a contradiction",
    -            "because the initial value of this variable seems to be being set "
    -            "in each of these sentences, but with a different outcome.");
    -        else {
    -            if (Properties::is_value_property(i->inferred_property)) {
    -                binary_predicate *bp =
    -                    Properties::Valued::get_stored_relation(i->inferred_property);
    -                if (bp) {
    -                    if (Wordings::match(Node::get_text(current_sentence), Node::get_text(list->inferred_from))) {
    -                        Problems::quote_source(1, current_sentence);
    -                        Problems::quote_relation(3, bp);
    -                        Problems::quote_subject(4, infs);
    -                        Problems::quote_spec(5, i->inferred_property_value);
    -                        Problems::quote_spec(6, list->inferred_property_value);
    -                        StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_RelationContradiction2));
    -                        Problems::issue_problem_segment(
    -                            "I'm finding a contradiction at the sentence %1, "
    -                            "because it means I can't set up %3. "
    -                            "On the one hand, %4 should relate to %5, but on the other "
    -                            "hand to %6, and this is a relation which doesn't allow "
    -                            "such clashes.");
    -                        Problems::issue_problem_end();
    -                    } else {
    -                        Problems::quote_source(1, current_sentence);
    -                        Problems::quote_source(2, list->inferred_from);
    -                        Problems::quote_relation(3, bp);
    -                        Problems::quote_subject(4, infs);
    -                        Problems::quote_spec(5, i->inferred_property_value);
    -                        Problems::quote_spec(6, list->inferred_property_value);
    -                        StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_RelationContradiction));
    -                        Problems::issue_problem_segment(
    -                            "I'm finding a contradiction at the sentences %1 and %2, "
    -                            "because between them they set up rival versions of %3. "
    -                            "On the one hand, %4 should relate to %5, but on the other "
    -                            "hand to %6, and this is a relation which doesn't allow "
    -                            "such clashes.");
    -                        Problems::issue_problem_end();
    -                    }
    -                    return;
    -                }
    -            }
    -            StandardProblems::two_sentences_problem(_p_(PM_PropertyContradiction),
    -                list->inferred_from,
    -                "this looks like a contradiction",
    -                "because the same property seems to be being set in each of these sentences, "
    -                "but with a different outcome.");
    -        }
    -    } else
    -        #ifdef IF_MODULE
    -        if (i->inference_type == IS_ROOM_INF) {
    -        StandardProblems::two_sentences_problem(_p_(PM_WhenIsARoomNotARoom),
    -            list->inferred_from,
    -            "this looks like a contradiction",
    -            "because apparently something would have to be both a room and not a "
    -            "room at the same time.");
    -    } else
    -        #endif
    -        StandardProblems::two_sentences_problem(_p_(PM_Contradiction),
    -            list->inferred_from,
    -            "this looks like a contradiction",
    -            "which might be because I have misunderstood what was meant to be the subject "
    -            "of one or both of those sentences.");
    +*/
    +    if (Inferences::explain_contradiction(list, i, d, infs)) return;
    +    StandardProblems::two_sentences_problem(_p_(PM_Contradiction),
    +        list->inferred_from,
    +        "this looks like a contradiction",
    +        "which might be because I have misunderstood what was meant to be the subject "
    +        "of one or both of those sentences.");
         return;
     
    - -

    §18.3.4. When talking about kinds or kinds of value, we allow new merely likely +

    +

    §22.3.4. When talking about kinds or kinds of value, we allow new merely likely information to displace old; but not when talking about specific objects or values, when the initial information stands. (This is to make it easier for people to change the effect of extensions which create kinds and specify their likely properties.)

    -

    Later uncertain data beats earlier, for subjects which generalise about whole domains18.3.4 = +

    Later uncertain data beats earlier, for subjects which generalise about whole domains22.3.4 =

    -    i->next = list->next;
    -    if (prev == NULL) InferenceSubjects::set_inferences(infs, i); else prev->next = i;
    -    World::Inferences::report_inference(i, infs, "replaced existing also only likely one");
    +    LinkedLists::set_entry(pos, SL, i);
    +    Inferences::report_inference(i, infs, "replaced existing also only likely one");
         return;
     
    - -

    §19. Logging inferences. We keep the debugging log file more than usually well informed about what +

    +

    §23. Logging inferences. We keep the debugging log file more than usually well informed about what goes on with inferences, as there is obviously great potential for mystifying bugs if inferences are incorrectly ignored.

    -void World::Inferences::report_inference(inference *i, inference_subject *infs, char *what_happened) {
    +void Inferences::report_inference(inference *i, inference_subject *infs, char *what_happened) {
         LOGIF(INFERENCES, ":::: %s: $j - $I\n", what_happened, infs, i);
     }
     
    -

    §20. And more generally: +

    §24. And more generally:

    -void World::Inferences::log_kind(int it) {
    -    switch(it) {
    -        case ARBITRARY_RELATION_INF: LOG("ARBITRARY_RELATION_INF"); break;
    -        case PROPERTY_INF: LOG("PROPERTY_INF"); break;
    -        default: Plugins::Call::log_inference_type(it); break;
    -    }
    +void Inferences::log_kind(inference_family *f) {
    +    if (f == NULL) LOG("<null inference family>");
    +    else LOG("%S", f->log_name);
     }
     
    -void World::Inferences::log(inference *in) {
    +void Inferences::log(inference *in) {
         if (in == NULL) { LOG("<null-inference>"); return; }
    -    World::Inferences::log_kind(in->inference_type);
    +    Inferences::log_kind(in->family);
         LOG("-");
         switch(in->certainty) {
             case IMPOSSIBLE_CE: LOG("Impossible "); break;
    @@ -1004,8 +945,7 @@ bugs if inferences are incorrectly ignored.
             case CERTAIN_CE: LOG("Certain "); break;
             default: LOG("<unknown-certainty>"); break;
         }
    -    if (in->inferred_property) LOG("(%W)", in->inferred_property->name);
    -    if (in->inferred_property_value) LOG("-1:$P", in->inferred_property_value);
    +    Inferences::log_family_details(in);
         if (in->infs_ref1) LOG("-1:$j", in->infs_ref1);
         if (in->infs_ref2) LOG("-2:$j", in->infs_ref2);
         if (in->spec_ref1) LOG("-s1:$P", in->spec_ref1);
    @@ -1013,7 +953,7 @@ bugs if inferences are incorrectly ignored.
     }
     
    diff --git a/docs/knowledge-module/5-pi.html b/docs/knowledge-module/5-pi.html new file mode 100644 index 000000000..db4bac4cf --- /dev/null +++ b/docs/knowledge-module/5-pi.html @@ -0,0 +1,246 @@ + + + + Property Inferences + + + + + + + + + + + + + + + + + + +
    + + +

    Inferences that a property of something is true, or has a particular value.

    + +

    §1. We will make: +

    + +
    +inference_family *property_inf = NULL;
    +
    +

    §2.

    + +
    +void PropertyInferences::start(void) {
    +    property_inf = Inferences::new_family(I"property_inf", CI_DIFFER_IN_PROPERTY_VALUE);
    +    METHOD_ADD(property_inf, LOG_INF_MTID, PropertyInferences::log);
    +    METHOD_ADD(property_inf, COMPARE_INF_MTID, PropertyInferences::cmp);
    +    METHOD_ADD(property_inf, JOIN_INF_MTID, PropertyInferences::join);
    +    METHOD_ADD(property_inf, EXPLAIN_CONTRADICTION_INF_MTID, PropertyInferences::explain_contradiction);
    +}
    +
    +void PropertyInferences::join(inference_family *f, inference *inf, inference_subject *infs) {
    +    property_inference_data *data = RETRIEVE_POINTER_property_inference_data(inf->data);
    +    Plugins::Call::property_value_notify(
    +        data->inferred_property, data->inferred_property_value);
    +}
    +
    +int PropertyInferences::cmp(inference_family *f, inference *i1, inference *i2) {
    +    property_inference_data *data1 = RETRIEVE_POINTER_property_inference_data(i1->data);
    +    property_inference_data *data2 = RETRIEVE_POINTER_property_inference_data(i2->data);
    +    property *pr1 = data1->inferred_property;
    +    property *pr2 = data2->inferred_property;
    +    if ((pr1) && (Properties::is_either_or(pr1)) &&
    +        (pr2) && (Properties::is_either_or(pr2)) &&
    +        ((pr1 == Properties::EitherOr::get_negation(pr2)) ||
    +         (pr2 == Properties::EitherOr::get_negation(pr1)))) pr2 = pr1;
    +    int c = Inferences::measure_property(pr1) - Inferences::measure_property(pr2);
    +    if (c > 0) return CI_DIFFER_IN_PROPERTY; if (c < 0) return -CI_DIFFER_IN_PROPERTY;
    +
    +    c = Inferences::measure_inf(i1) - Inferences::measure_inf(i2);
    +
    +    parse_node *val1 = data1->inferred_property_value;
    +    parse_node *val2 = data2->inferred_property_value;
    +    if ((data1->inferred_property != data2->inferred_property) ||  in case they are an either-or pair
    +        ((val1) && (val2) && (Rvalues::compare_CONSTANT(val1, val2) == FALSE))) {
    +        if (c > 0) return CI_DIFFER_IN_PROPERTY_VALUE;
    +        if (c < 0) return -CI_DIFFER_IN_PROPERTY_VALUE;
    +    }
    +
    +    if (c > 0) return CI_DIFFER_IN_COPY_ONLY; if (c < 0) return -CI_DIFFER_IN_COPY_ONLY;
    +    return CI_IDENTICAL;
    +}
    +
    +int PropertyInferences::explain_contradiction(inference_family *f, inference *A,
    +    inference *B, int similarity, inference_subject *subj) {
    +    property_inference_data *A_data = RETRIEVE_POINTER_property_inference_data(A->data);
    +    property_inference_data *B_data = RETRIEVE_POINTER_property_inference_data(B->data);
    +    if (B_data->inferred_property == P_variable_initial_value) {
    +        StandardProblems::two_sentences_problem(_p_(PM_VariableContradiction),
    +            A->inferred_from,
    +            "this looks like a contradiction",
    +            "because the initial value of this variable seems to be being set "
    +            "in each of these sentences, but with a different outcome.");
    +    } else {
    +        if (Properties::is_value_property(B_data->inferred_property)) {
    +            binary_predicate *bp =
    +                Properties::Valued::get_stored_relation(B_data->inferred_property);
    +            if (bp) {
    +                if (Wordings::match(Node::get_text(current_sentence),
    +                    Node::get_text(A->inferred_from))) {
    +                    Problems::quote_source(1, current_sentence);
    +                    Problems::quote_relation(3, bp);
    +                    Problems::quote_subject(4, subj);
    +                    Problems::quote_spec(5, B_data->inferred_property_value);
    +                    Problems::quote_spec(6, A_data->inferred_property_value);
    +                    StandardProblems::handmade_problem(Task::syntax_tree(),
    +                        _p_(PM_RelationContradiction2));
    +                    Problems::issue_problem_segment(
    +                        "I'm finding a contradiction at the sentence %1, "
    +                        "because it means I can't set up %3. "
    +                        "On the one hand, %4 should relate to %5, but on the other "
    +                        "hand to %6, and this is a relation which doesn't allow "
    +                        "such clashes.");
    +                    Problems::issue_problem_end();
    +                } else {
    +                    Problems::quote_source(1, current_sentence);
    +                    Problems::quote_source(2, A->inferred_from);
    +                    Problems::quote_relation(3, bp);
    +                    Problems::quote_subject(4, subj);
    +                    Problems::quote_spec(5, B_data->inferred_property_value);
    +                    Problems::quote_spec(6, A_data->inferred_property_value);
    +                    StandardProblems::handmade_problem(Task::syntax_tree(),
    +                        _p_(PM_RelationContradiction));
    +                    Problems::issue_problem_segment(
    +                        "I'm finding a contradiction at the sentences %1 and %2, "
    +                        "because between them they set up rival versions of %3. "
    +                        "On the one hand, %4 should relate to %5, but on the other "
    +                        "hand to %6, and this is a relation which doesn't allow "
    +                        "such clashes.");
    +                    Problems::issue_problem_end();
    +                }
    +                return TRUE;
    +            }
    +        }
    +        StandardProblems::two_sentences_problem(_p_(PM_PropertyContradiction),
    +            A->inferred_from,
    +            "this looks like a contradiction",
    +            "because the same property seems to be being set in each of these sentences, "
    +            "but with a different outcome.");
    +    }
    +    return TRUE;
    +}
    +
    +void PropertyInferences::log(inference_family *f, inference *inf) {
    +    property_inference_data *data = RETRIEVE_POINTER_property_inference_data(inf->data);
    +    LOG("(%W)", data->inferred_property->name);
    +    if (data->inferred_property_value) LOG(":=$P", data->inferred_property_value);
    +}
    +
    +typedef struct property_inference_data {
    +    struct property *inferred_property;  property referred to, if any
    +    struct parse_node *inferred_property_value;  and its value, if any
    +    CLASS_DEFINITION
    +} property_inference_data;
    +
    +inference *PropertyInferences::new(inference_subject *infs,
    +    property *prn, parse_node *val) {
    +    PROTECTED_MODEL_PROCEDURE;
    +    if (prn == NULL) internal_error("null property inference");
    +
    +    property_inference_data *data = CREATE(property_inference_data);
    +    data->inferred_property = prn;
    +    data->inferred_property_value = val;
    +    int c = prevailing_mood;
    +    if (c == UNKNOWN_CE) c = InferenceSubjects::get_default_certainty(infs);
    +    inference *i = Inferences::create_inference(property_inf,
    +        STORE_POINTER_property_inference_data(data), c);
    +    return i;
    +}
    +
    +void PropertyInferences::draw(inference_subject *infs, property *prn, parse_node *val) {
    +    inference *i = PropertyInferences::new(infs, prn, val);
    +    Inferences::join_inference(i, infs);
    +}
    +
    +void PropertyInferences::draw_negated(inference_subject *infs, property *prn, parse_node *val) {
    +    inference *i = PropertyInferences::new(infs, prn, val);
    +    i->certainty = -i->certainty;
    +    Inferences::join_inference(i, infs);
    +}
    +
    +property *PropertyInferences::get_property(inference *i) {
    +    property_inference_data *data = RETRIEVE_POINTER_property_inference_data(i->data);
    +    return data->inferred_property;
    +}
    +
    +parse_node *PropertyInferences::get_value(inference *i) {
    +    property_inference_data *data = RETRIEVE_POINTER_property_inference_data(i->data);
    +    return data->inferred_property_value;
    +}
    +
    +parse_node *PropertyInferences::set_value_kind(inference *i, kind *K) {
    +    property_inference_data *data = RETRIEVE_POINTER_property_inference_data(i->data);
    +    Node::set_kind_of_value(data->inferred_property_value, K);
    +    return data->inferred_property_value;
    +}
    +
    +
    • The structure property_inference_data is private to this section.
    + + +
    + + + diff --git a/docs/knowledge-module/5-pp.html b/docs/knowledge-module/5-pp.html index a54c1c9bc..0041a971b 100644 --- a/docs/knowledge-module/5-pp.html +++ b/docs/knowledge-module/5-pp.html @@ -74,7 +74,7 @@ function togglePopup(material_id) {
    +

    To enforce the domain of properties: for instance, that a door can be open or closed but that an animal cannot, or that a person can have a carrying capacity but that a door cannot.


    @@ -128,7 +128,7 @@ whereas the unpredictable order might make testing Inform more annoying. LOOP_OVER_LINKED_LIST(pp, property_permission, InferenceSubjects::get_permissions(infs))
    -property_permission *World::Permissions::find(inference_subject *infs,
    +property_permission *World::Permissions::find(inference_subject *infs,
         property *prn, int allow_inheritance) {
         property *prnbar = NULL;
         if (Properties::is_either_or(prn)) prnbar = Properties::EitherOr::get_negation(prn);
    @@ -240,7 +240,7 @@ in the case of a broken jar.
     }
     
    diff --git a/docs/knowledge-module/5-ri.html b/docs/knowledge-module/5-ri.html new file mode 100644 index 000000000..3957e4881 --- /dev/null +++ b/docs/knowledge-module/5-ri.html @@ -0,0 +1,95 @@ + + + + Relation Inferences + + + + + + + + + + + + + + + + + + +
    + + +

    Inferences that a relation holds between two subjects or values.

    + +

    §1. We will make: +

    + +
    +inference_family *arbitrary_relation_inf = NULL;
    +
    +

    §2.

    + +
    +void RelationInferences::start(void) {
    +    arbitrary_relation_inf = Inferences::new_family(I"arbitrary_relation_inf", CI_DIFFER_IN_COPY_ONLY);
    +}
    +
    + + +
    + + + diff --git a/docs/knowledge-module/5-cmw.html b/docs/knowledge-module/5-tmw.html similarity index 56% rename from docs/knowledge-module/5-cmw.html rename to docs/knowledge-module/5-tmw.html index 1b029ed42..6c76a4831 100644 --- a/docs/knowledge-module/5-cmw.html +++ b/docs/knowledge-module/5-tmw.html @@ -1,7 +1,7 @@ - Complete Model World + The Model World @@ -12,6 +12,14 @@ + + + @@ -59,65 +67,69 @@
    - + -

    Once the assertions have all been read and reduced to inferences, and all the creations have been made, we take stock; sometimes we spot inconsistencies, sometimes we make deductions, and we try to complete our picture of the model world.

    + +

    Once the assertions have all been read and reduced to inferences, we try to complete our model world.

    -
    +
    -

    §1. Stages II to IV. The process of using existing facts to infer new ones is vulnerable -to timing bugs, so we organise the "making" process into five numbered -stages, given the Roman numerals I to V. Much of the work is done by plugins, -which can take a hand at any or all of the stages, using their contextual -knowledge to fill in missing properties. -

    - -
    • (I) Deducing the kind of any object whose kind is not known. Because this -can result in a change of kind, which can result in further creations by -assembly sentences like "A handle is part of every door", Stage I takes -place at the end of traverse 2 of the source text and, uniquely, gets the -opportunity to add fresh sentences to the source — thus extending the -traverse. By the end of Stage I, all kinds are fixed. -
    • (II) Stages II and III are for adding further properties or relationships, -which aren't explicit in the source text but which plugins can add on the -basis of contextual understanding. (Two stages are provided here to avoid -timing issues where one plugin has to act earlier than another.) -
    • (III) See (II). If a plugin is going to change the compilation order of -the objects (as the spatial-model plugin does), it must do so during -Stage III. -
    • (IV) A stage for consistency checks or to store away useful data, but where -nothing in the model may be changed — no properties or relationships -may be added. (Except that the instance-counting plugin is allowed to -add the linked-lists-of-instances properties, used to optimise loops -at run-time; they aren't visible at the I7 level so aren't properly -part of the model world.) -
    • (V) A final chance to add properties which will assist the run-time -implementation of, for instance, the command grammar, but again aren't -really part of the model world. (This can't be done earlier since the -command grammar isn't parsed until after World::complete; and we -aren't allowed to add I7-accessible properties.) -
    -

    The following routine, then, carries out stages II, III and IV. +

    §1. Introduction. World-building has five stages, written with Roman numerals I to V in this +source code. The logic in this section is all quite simple, but plugins are +allowed to intervene at each of the five stages, bringing domain-specific +wisdom to the process.

    +
    define WORLD_STAGE_I     1   Deduce kinds for object instances
    +define WORLD_STAGE_II    2   First chance to add further properties or relationships
    +define WORLD_STAGE_III   3   Second chance to add further properties or relationships
    +define WORLD_STAGE_IV    4   Perform mutual consistency checks
    +define WORLD_STAGE_V     5   Post-game: only implementation details can be added
    +
    -void World::complete(void) {
    -    Stages II and III of the completion process1.1;
    -    Stage IV of the completion process1.2;
    +int current_model_world_stage = 0;  not yet building the world model
    +
    +void World::ask_plugins_at_stage(int S) {
    +    if (S != current_model_world_stage + 1) internal_error("Stage mistimed");
    +    current_model_world_stage = S;
    +    Plugins::Call::complete_model(S);
    +}
    +
    +int World::current_building_stage(void) {
    +    return current_model_world_stage;
     }
     
    -

    §1.1. The model world is a broth with many cooks. On the one hand, we have the -various different INFSs, with their different needs — a various-to-various -relation, a global variable, and so on — and on the other hand we also -have the plugins, each of which takes its own global view of the situation. -We give everyone a turn. +

    §2. Stage I. Deducing the kind of any object whose kind is not known. The core compiler +has already done the best it can, but then it lacks domain-specific +understanding. So the only business done is by plugins, which understand +certain kinds and relationships better.

    -

    Stages II and III of the completion process1.1 = +

    Some instances change their kinds in Stage I, and this can result in further +creations by assembly sentences like "A handle is part of every door". Because +of that, Stage I takes place at the end of traverse 2 of the source text and, +uniquely, gets the opportunity to add fresh sentences to the source — thus +extending the traverse. But by the end of Stage I, all kinds are fixed, and +no further instances can be created.

    +void World::deduce_object_instance_kinds(void) {
    +    World::ask_plugins_at_stage(WORLD_STAGE_I);
    +}
    +
    +

    §3. Stages II and III. This is an opportunity for plugins to add further properties or relationships +on the basis of contextual understanding. Two stages, and thus two opportunities, +are provided here to avoid timing issues where one plugin has to act earlier +than another. +

    + +

    If a plugin is going to change the compilation order of the objects (as the +spatial-model plugin does), it must do so during Stage III, not Stage II. +

    + +
    +void World::stages_II_and_III(void) {
         inference_subject *infs;
         LOOP_OVER(infs, inference_subject) {
             InferenceSubjects::complete_model(infs);
    @@ -125,28 +137,27 @@ We give everyone a turn.
         }
         LOOP_OVER(infs, inference_subject)
             Assertions::Implications::consider_all(infs);
    -    Plugins::Call::complete_model(2);
    -    Plugins::Call::complete_model(3);
    +    World::ask_plugins_at_stage(WORLD_STAGE_II);
    +    World::ask_plugins_at_stage(WORLD_STAGE_III);
    +}
     
    -
    • This code is used in §1.
    -

    §1.2. Checking what we have, then. Once again each INFS is given an opportunity -to check itself, and then the plugins have a turn. -

    - -

    Stage IV of the completion process1.2 = +

    §4. Stage IV. This is for consistency checks or to store away useful data, but where +nothing in the model may be changed — no properties or relationships +may be added.

    +void World::stage_IV(void) {
         inference_subject *infs;
         LOOP_OVER(infs, inference_subject) {
             InferenceSubjects::check_model(infs);
    -        Check that properties are permitted1.2.1;
    -        Check that properties are not contradictory1.2.2;
    +        Check that properties are permitted4.1;
    +        Check that properties are not contradictory4.2;
         }
    -    Plugins::Call::complete_model(4);
    +    World::ask_plugins_at_stage(WORLD_STAGE_IV);
    +}
     
    -
    • This code is used in §1.
    -

    §1.2.1. These two checks may seem a little odd. After all, we've been throwing out +

    §4.1. These two checks may seem a little odd. After all, we've been throwing out impossible inferences with problem messages all along, while reading the source text. Why not perform these checks then, too?

    @@ -173,13 +184,13 @@ in plugins which add inconsistent properties.

    A nameless property added in Stages II and III does not need permission.

    -

    Check that properties are permitted1.2.1 = +

    Check that properties are permitted4.1 =

         inference *inf;
    -    KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
    -        property *prn = World::Inferences::get_property(inf);
    +    KNOWLEDGE_LOOP(inf, infs, property_inf) {
    +        property *prn = PropertyInferences::get_property(inf);
             if (Wordings::nonempty(prn->name))
                 if (World::Permissions::find(infs, prn, TRUE) == NULL)
                     StandardProblems::inference_problem(_p_(PM_PropertyNotPermitted),
    @@ -189,48 +200,49 @@ in plugins which add inconsistent properties.
                         "details.");
         }
     
    -
    • This code is used in §1.2.
    -

    §1.2.2. The following contradiction checks do not apply to properties added -in Stages II and III, since those are often I6 hacks added for run-time +

    • This code is used in §4.
    +

    §4.2. The following contradiction checks do not apply to properties added +in Stages II and III, since those are often Inter hacks added for run-time convenience, and don't have to follow the I7 rules.

    -

    Check that properties are not contradictory1.2.2 = +

    Check that properties are not contradictory4.2 =

         inference *narrow;
    -    KNOWLEDGE_LOOP(narrow, infs, PROPERTY_INF) {
    -        if (World::Inferences::added_in_construction(narrow) == FALSE) {
    -            property *prn = World::Inferences::get_property(narrow);
    +    KNOWLEDGE_LOOP(narrow, infs, property_inf) {
    +        if (Inferences::during_stage(narrow) == 0) {
    +            property *prn = PropertyInferences::get_property(narrow);
                 int sign = 1;
    -            if (World::Inferences::get_certainty(narrow) < 0) sign = -1;
    -            Look for clashes concerning this property from wider inferences1.2.2.1;
    -            if ((Properties::is_either_or(prn)) && (Properties::EitherOr::get_negation(prn))) {
    +            if (Inferences::get_certainty(narrow) < 0) sign = -1;
    +            Look for clashes concerning this property from wider inferences4.2.1;
    +            if ((Properties::is_either_or(prn)) &&
    +                (Properties::EitherOr::get_negation(prn))) {
                     prn = Properties::EitherOr::get_negation(prn);
                     sign = -sign;
    -                Look for clashes concerning this property from wider inferences1.2.2.1;
    +                Look for clashes concerning this property from wider inferences4.2.1;
                 }
             }
         }
     
    -
    • This code is used in §1.2.
    -

    §1.2.2.1. Look for clashes concerning this property from wider inferences1.2.2.1 = +

    • This code is used in §4.
    +

    §4.2.1. Look for clashes concerning this property from wider inferences4.2.1 =

         inference_subject *boss = InferenceSubjects::narrowest_broader_subject(infs);
         while (boss) {
             inference *wide;
    -        KNOWLEDGE_LOOP(wide, boss, PROPERTY_INF)
    -            if (World::Inferences::added_in_construction(wide) == FALSE)
    -                if (prn == World::Inferences::get_property(wide))
    -                    Check that these differently scoped inferences do not clash1.2.2.1.1;
    +        KNOWLEDGE_LOOP(wide, boss, property_inf)
    +            if (Inferences::during_stage(wide) == 0)
    +                if (prn == PropertyInferences::get_property(wide))
    +                    Check that these differently scoped inferences do not clash4.2.1.1;
             boss = InferenceSubjects::narrowest_broader_subject(boss);
         }
     
    -
    • This code is used in §1.2.2 (twice).
    -

    §1.2.2.1.1. It's never a problem when a vague fact about something general is contradicted +

    • This code is used in §4.2 (twice).
    +

    §4.2.1.1. It's never a problem when a vague fact about something general is contradicted by a fact about something specific; the problem comes with something like this:

    @@ -243,17 +255,17 @@ rather than LIKELY_CE< about the Portal, to stand.

    -

    Check that these differently scoped inferences do not clash1.2.2.1.1 = +

    Check that these differently scoped inferences do not clash4.2.1.1 =

    -    int abcw = World::Inferences::get_certainty(wide); if (abcw < 0) abcw = -abcw;
    +    int abcw = Inferences::get_certainty(wide); if (abcw < 0) abcw = -abcw;
         if (abcw == CERTAIN_CE) {
             int clash = FALSE;
    -        int wide_sign = 1; if (World::Inferences::get_certainty(wide) < 0) wide_sign = -1;
    +        int wide_sign = 1; if (Inferences::get_certainty(wide) < 0) wide_sign = -1;
             if (Properties::is_either_or(prn) == FALSE) {
    -            parse_node *narrow_val = World::Inferences::get_property_value(narrow);
    -            parse_node *wide_val = World::Inferences::get_property_value(wide);
    +            parse_node *narrow_val = PropertyInferences::get_value(narrow);
    +            parse_node *wide_val = PropertyInferences::get_value(wide);
                 if (Rvalues::compare_CONSTANT(narrow_val, wide_val) == FALSE) {
                     LOG("Clash of $P and $P\n  $I\n  $I\n",
                         narrow_val, wide_val, narrow, wide);
    @@ -262,38 +274,45 @@ about the Portal, to stand.
             }
             if (sign != wide_sign) clash = (clash)?FALSE:TRUE;
             if (clash) {
    -            int abcn = World::Inferences::get_certainty(narrow); if (abcn < 0) abcn = -abcn;
    +            int abcn = Inferences::get_certainty(narrow); if (abcn < 0) abcn = -abcn;
                 if (abcn == CERTAIN_CE)
    -                 Issue a problem message for clash with wider inference1.2.2.1.1.1
    +                 Issue a problem message for clash with wider inference4.2.1.1.1
                 else
    -                World::Inferences::set_certainty(narrow, IMPOSSIBLE_CE);
    +                Inferences::set_certainty(narrow, IMPOSSIBLE_CE);
             }
         }
     
    - -

    §1.2.2.1.1.1. Issue a problem message for clash with wider inference1.2.2.1.1.1 = +

    +

    §4.2.1.1.1. Issue a problem message for clash with wider inference4.2.1.1.1 =

         LOG("Checking infs $j compatible with infs $j for property $Y:\n  $I\n  $I\n",
             infs, boss, prn, narrow, wide);
         StandardProblems::infs_contradiction_problem(_p_(PM_InstanceContradiction),
    -        World::Inferences::where_inferred(narrow), World::Inferences::where_inferred(wide), infs,
    +        Inferences::where_inferred(narrow), Inferences::where_inferred(wide), infs,
             "therefore has to have two contradictory states of the same property at once",
             "which is impossible. When a kind's definition says that something is 'always' "
             "true, there is no way to override that for particular things of the kind.");
     
    - -

    §2. Stage V. See above. This is for the use of plugins only. +

    +

    §5. Stage V. A final chance to add properties which may assist the run-time implementation +of whatever a plugin is concerned with, but which is not allowed to make +changes to the model as it would be understood by the author. +

    + +

    For example, the Instance Counting (in runtime) plugin adds low-level properties +to improve run-time performance, but they have no names and cannot be referred +to or accessed by code written in Inform 7; they exist at the level of Inter only.

    -void World::complete_additions(void) {
    -    Plugins::Call::complete_model(5);
    +void World::stage_V(void) {
    +    World::ask_plugins_at_stage(WORLD_STAGE_V);
     }
     
    diff --git a/docs/knowledge-module/P-wtmd.html b/docs/knowledge-module/P-wtmd.html index f62a58693..220979521 100644 --- a/docs/knowledge-module/P-wtmd.html +++ b/docs/knowledge-module/P-wtmd.html @@ -132,17 +132,10 @@ proposition to a set of facts concerning things in the model; as we have seen, the model includes kinds, variables, instances and relations, and so we need a unified type for "something you can know a fact about". That type is called inference_subject. Each subject has its own list of known -facts: we call such a fact an inference because it has (usually) been +facts: we call such a fact an inference because it has (usually) been inferred from a proposition.

    -

    Chapter 2: Instances and Variables gives a general API for dealing with Inference Subjects, -and then works systematically through the various categories of these. -Kinds and binary predicates already exist from other modules (see -Chapter 2: Kinds (in kinds) and Chapter 3: Binary Predicates (in calculus) -respectively), but Instances and Nonlocal Variables are new. -

    -

    Chapter 3: Properties implements our system of properties: each different value or either-or property is a property object. There might be a puritan case for abolishing this type in favour of regarding either-or properties @@ -151,7 +144,16 @@ of binary_predicate -

    Finally, Chapter 4: Subjects builds the actual model. +

    Chapter 4: Subjects gives a general API for dealing with Inference Subjects, +and then works systematically through the various categories of these. +Kinds and binary predicates already exist from other modules (see +Chapter 2: Kinds (in kinds) and Chapter 3: Binary Predicates (in calculus) +respectively), but Instances and Nonlocal Variables are new. +

    + +

    Finally, Chapter 5: Modelling deals with the actual inferences, and with how the +model world is constructed. The core of Inform does nothing very interesting +here, but plugins from the if module add some domain-specific savvy.

    diff --git a/docs/runtime-module/4-cl.html b/docs/runtime-module/4-cl.html index 1e6b8f42c..4335f9c28 100644 --- a/docs/runtime-module/4-cl.html +++ b/docs/runtime-module/4-cl.html @@ -160,7 +160,7 @@ the list!); }
    diff --git a/docs/runtime-module/4-ct.html b/docs/runtime-module/4-ct.html index eb0162e2c..43029ffc3 100644 --- a/docs/runtime-module/4-ct.html +++ b/docs/runtime-module/4-ct.html @@ -470,7 +470,7 @@ exceptional case. }
    diff --git a/docs/runtime-module/4-efart.html b/docs/runtime-module/4-efart.html index 7bc865df2..77d1b29c4 100644 --- a/docs/runtime-module/4-efart.html +++ b/docs/runtime-module/4-efart.html @@ -178,7 +178,7 @@ and author. }
    diff --git a/docs/runtime-module/4-es.html b/docs/runtime-module/4-es.html index 34521abfd..16daca001 100644 --- a/docs/runtime-module/4-es.html +++ b/docs/runtime-module/4-es.html @@ -89,7 +89,7 @@ they provide values different from each other and from all other functions. }
    diff --git a/docs/runtime-module/4-fc.html b/docs/runtime-module/4-fc.html index 73f666b79..c79a4796b 100644 --- a/docs/runtime-module/4-fc.html +++ b/docs/runtime-module/4-fc.html @@ -216,7 +216,7 @@ Inform's own version number), but it belongs nowhere else either, so: }
    diff --git a/docs/runtime-module/4-i6i.html b/docs/runtime-module/4-i6i.html index b00e91b84..748149888 100644 --- a/docs/runtime-module/4-i6i.html +++ b/docs/runtime-module/4-i6i.html @@ -315,7 +315,7 @@ requests, which, again, we do by instructing the Template code. }
    diff --git a/docs/knowledge-module/5-ic.html b/docs/runtime-module/4-ic.html similarity index 66% rename from docs/knowledge-module/5-ic.html rename to docs/runtime-module/4-ic.html index 8d718872e..b3430bd48 100644 --- a/docs/knowledge-module/5-ic.html +++ b/docs/runtime-module/4-ic.html @@ -56,9 +56,9 @@ MathJax = {
  • core
  • assertions
  • values
  • -
  • knowledge
  • +
  • knowledge
  • imperative
  • -
  • runtime
  • +
  • runtime
  • if
  • multimedia
  • index
  • @@ -83,10 +83,10 @@ MathJax = {
    +

    A plugin which maintains run-time-accessible linked lists of instances of kinds, in order to speed up loops; and instance counts within kinds, in order to speed up relation storage; and the object-kind hierarchy, in order to speed up run-time checking of the type safety of property usage.

    -
    +

    §1. Every subject contains a pointer to its own unique copy of the following structure, but it only has relevance if the subject represents an object: @@ -96,8 +96,8 @@ structure, but it only has relevance if the subject represents an object:

     typedef struct counting_data {
    -    struct property *instance_count_prop;  the (I6 only) IK-Count property for this kind
    -    struct property *instance_link_prop;  the (I6 only) IK-Link property for this kind
    +    struct property *instance_count_prop;  the (I6 only) IK-Count property for this kind
    +    struct property *instance_link_prop;  the (I6 only) IK-Link property for this kind
         int has_instances;  are there any instances of this kind?
         CLASS_DEFINITION
     } counting_data;
    @@ -109,29 +109,29 @@ route-finding through relations on objects.
     

    -property *P_vector = NULL;
    -property *P_KD_Count = NULL;  see below
    +property *P_vector = NULL;
    +property *P_KD_Count = NULL;  see below
     

    §3. Plugin startup.

    -void PL::Counting::start(void) {
    -    PLUGIN_REGISTER(PLUGIN_NEW_SUBJECT_NOTIFY, PL::Counting::counting_new_subject_notify);
    -    PLUGIN_REGISTER(PLUGIN_COMPLETE_MODEL, PL::Counting::counting_complete_model);
    -    PLUGIN_REGISTER(PLUGIN_COMPILE_MODEL_TABLES, PL::Counting::counting_compile_model_tables);
    -    PLUGIN_REGISTER(PLUGIN_ESTIMATE_PROPERTY_USAGE, PL::Counting::counting_estimate_property_usage);
    +void PL::Counting::start(void) {
    +    PLUGIN_REGISTER(PLUGIN_NEW_SUBJECT_NOTIFY, PL::Counting::counting_new_subject_notify);
    +    PLUGIN_REGISTER(PLUGIN_COMPLETE_MODEL, PL::Counting::counting_complete_model);
    +    PLUGIN_REGISTER(PLUGIN_COMPILE_MODEL_TABLES, PL::Counting::counting_compile_model_tables);
    +    PLUGIN_REGISTER(PLUGIN_ESTIMATE_PROPERTY_USAGE, PL::Counting::counting_estimate_property_usage);
     }
     

    §4. Initialising. Counting data is actually relevant only for kinds, and remains blank for instances.

    -int PL::Counting::counting_new_subject_notify(inference_subject *subj) {
    -    ATTACH_PLUGIN_DATA_TO_SUBJECT(counting, subj, PL::Counting::new_data(subj));
    +int PL::Counting::counting_new_subject_notify(inference_subject *subj) {
    +    ATTACH_PLUGIN_DATA_TO_SUBJECT(counting, subj, PL::Counting::new_data(subj));
         return FALSE;
     }
     
    -counting_data *PL::Counting::new_data(inference_subject *subj) {
    +counting_data *PL::Counting::new_data(inference_subject *subj) {
         counting_data *cd = CREATE(counting_data);
         cd->instance_count_prop = NULL;
         cd->instance_link_prop = NULL;
    @@ -150,27 +150,27 @@ numbered 0.
     
     
    define INSTANCE_COUNT(I, K)
         kind_instance_counts[(I)->allocation_id*max_kind_instance_count +
    -        RTKinds::I6_classnumber(K)]
    +        RTKinds::I6_classnumber(K)]
     
     int *kind_instance_counts = NULL;
     int max_kind_instance_count = 0;
     
    -void PL::Counting::make_instance_counts(void) {
    -    Allocate the instance count array in memory5.1;
    -    Compute the instance count array5.2;
    +void PL::Counting::make_instance_counts(void) {
    +    Allocate the instance count array in memory5.1;
    +    Compute the instance count array5.2;
     }
     

    §5.1. Allocate the instance count array in memory5.1 =

    -    max_kind_instance_count = NUMBER_CREATED(inference_subject);
    +    max_kind_instance_count = NUMBER_CREATED(inference_subject);
         kind_instance_counts =
             Memory::calloc(max_kind_instance_count*max_kind_instance_count, sizeof(int),
    -            INSTANCE_COUNTING_MREASON);
    +            INSTANCE_COUNTING_MREASON);
     
    -
    • This code is used in §5.
    +
    • This code is used in §5.

    §5.2. The following is quadratic in the number of objects, but this has never been a problem in practice; the number seldom exceeds a few hundred.

    @@ -179,7 +179,7 @@ a problem in practice; the number seldom exceeds a few hundred.

    -    instance *I;
    +    instance *I;
         kind *K;
         LOOP_OVER_BASE_KINDS(K)
             if (Kinds::Behaviour::is_subkind_of_object(K))
    @@ -193,12 +193,12 @@ a problem in practice; the number seldom exceeds a few hundred.
                     INSTANCE_COUNT(I, K) = ix_count++;
             }
     
    -
    • This code is used in §5.
    +
    • This code is used in §5.

    §6. Instance counts are actually useful to several other plugins, so we provide:

    -int PL::Counting::instance_count(instance *I, kind *K) {
    +int PL::Counting::instance_count(instance *I, kind *K) {
         if (kind_instance_counts == NULL) internal_error("instance counts not available");
         if (K == NULL) internal_error("instance counts available only for objects");
         return INSTANCE_COUNT(I, K);
    @@ -218,17 +218,17 @@ an explicit player.
     

    -instance *PL::Counting::next_instance_of(instance *I, kind *k) {
    +instance *PL::Counting::next_instance_of(instance *I, kind *k) {
         if (k == NULL) return NULL;
         int resuming = TRUE;
    -    if (I == NULL) { I = FIRST_IN_INSTANCE_ORDERING; resuming = FALSE; }
    +    if (I == NULL) { I = FIRST_IN_INSTANCE_ORDERING; resuming = FALSE; }
         while (I) {
             if (resuming) I = NEXT_IN_INSTANCE_ORDERING(I);
             resuming = TRUE;
             if (I == NULL) break;
    -        if (InferenceSubjects::aliased_but_diverted(Instances::as_subject(I)))
    +        if (InferenceSubjects::aliased_but_diverted(Instances::as_subject(I)))
                 continue;  selfobj may not count
    -        if (Instances::of_kind(I, k)) return I;
    +        if (Instances::of_kind(I, k)) return I;
         }
         return NULL;
     }
    @@ -237,8 +237,8 @@ an explicit player.
     

    -parse_node *PL::Counting::next_instance_of_as_value(instance *I, kind *k) {
    -    instance *next = PL::Counting::next_instance_of(I, k);
    +parse_node *PL::Counting::next_instance_of_as_value(instance *I, kind *k) {
    +    instance *next = PL::Counting::next_instance_of(I, k);
         if (next) return Rvalues::from_instance(next);
         return Rvalues::new_nothing_object_constant();
     }
    @@ -256,51 +256,51 @@ since Inform always compiles code which knows which kind it's looping over.
     

    -inter_name *PL::Counting::first_instance(kind *K) {
    +inter_name *PL::Counting::first_instance(kind *K) {
         kind_constructor *con = Kinds::get_construct(K);
         inter_name *iname = Kinds::Constructors::first_instance_iname(con);
         if (iname == NULL) {
    -        iname = Hierarchy::derive_iname_in(FIRST_INSTANCE_HL, RTKinds::iname(K), Kinds::Behaviour::package(K));
    +        iname = Hierarchy::derive_iname_in(FIRST_INSTANCE_HL, RTKinds::iname(K), Kinds::Behaviour::package(K));
             Kinds::Constructors::set_first_instance_iname(con, iname);
         }
         return iname;
     }
     
    -inter_name *PL::Counting::next_instance(kind *K) {
    +inter_name *PL::Counting::next_instance(kind *K) {
         kind_constructor *con = Kinds::get_construct(K);
         inter_name *iname = Kinds::Constructors::next_instance_iname(con);
         if (iname == NULL) {
    -        iname = Hierarchy::derive_iname_in(NEXT_INSTANCE_HL, RTKinds::iname(K), Kinds::Behaviour::package(K));
    +        iname = Hierarchy::derive_iname_in(NEXT_INSTANCE_HL, RTKinds::iname(K), Kinds::Behaviour::package(K));
             Kinds::Constructors::set_next_instance_iname(con, iname);
         }
         return iname;
     }
     
    -inter_name *PL::Counting::instance_count_iname(kind *K) {
    -    int N = RTKinds::I6_classnumber(K);
    -    if (N == 1) return Hierarchy::make_iname_in(COUNT_INSTANCE_1_HL, Kinds::Behaviour::package(K));
    -    if (N == 2) return Hierarchy::make_iname_in(COUNT_INSTANCE_2_HL, Kinds::Behaviour::package(K));
    -    if (N == 3) return Hierarchy::make_iname_in(COUNT_INSTANCE_3_HL, Kinds::Behaviour::package(K));
    -    if (N == 4) return Hierarchy::make_iname_in(COUNT_INSTANCE_4_HL, Kinds::Behaviour::package(K));
    -    if (N == 5) return Hierarchy::make_iname_in(COUNT_INSTANCE_5_HL, Kinds::Behaviour::package(K));
    -    if (N == 6) return Hierarchy::make_iname_in(COUNT_INSTANCE_6_HL, Kinds::Behaviour::package(K));
    -    if (N == 7) return Hierarchy::make_iname_in(COUNT_INSTANCE_7_HL, Kinds::Behaviour::package(K));
    -    if (N == 8) return Hierarchy::make_iname_in(COUNT_INSTANCE_8_HL, Kinds::Behaviour::package(K));
    -    if (N == 9) return Hierarchy::make_iname_in(COUNT_INSTANCE_9_HL, Kinds::Behaviour::package(K));
    -    if (N == 10) return Hierarchy::make_iname_in(COUNT_INSTANCE_10_HL, Kinds::Behaviour::package(K));
    -    return Hierarchy::derive_iname_in(COUNT_INSTANCE_HL, RTKinds::iname(K), Kinds::Behaviour::package(K));
    +inter_name *PL::Counting::instance_count_iname(kind *K) {
    +    int N = RTKinds::I6_classnumber(K);
    +    if (N == 1) return Hierarchy::make_iname_in(COUNT_INSTANCE_1_HL, Kinds::Behaviour::package(K));
    +    if (N == 2) return Hierarchy::make_iname_in(COUNT_INSTANCE_2_HL, Kinds::Behaviour::package(K));
    +    if (N == 3) return Hierarchy::make_iname_in(COUNT_INSTANCE_3_HL, Kinds::Behaviour::package(K));
    +    if (N == 4) return Hierarchy::make_iname_in(COUNT_INSTANCE_4_HL, Kinds::Behaviour::package(K));
    +    if (N == 5) return Hierarchy::make_iname_in(COUNT_INSTANCE_5_HL, Kinds::Behaviour::package(K));
    +    if (N == 6) return Hierarchy::make_iname_in(COUNT_INSTANCE_6_HL, Kinds::Behaviour::package(K));
    +    if (N == 7) return Hierarchy::make_iname_in(COUNT_INSTANCE_7_HL, Kinds::Behaviour::package(K));
    +    if (N == 8) return Hierarchy::make_iname_in(COUNT_INSTANCE_8_HL, Kinds::Behaviour::package(K));
    +    if (N == 9) return Hierarchy::make_iname_in(COUNT_INSTANCE_9_HL, Kinds::Behaviour::package(K));
    +    if (N == 10) return Hierarchy::make_iname_in(COUNT_INSTANCE_10_HL, Kinds::Behaviour::package(K));
    +    return Hierarchy::derive_iname_in(COUNT_INSTANCE_HL, RTKinds::iname(K), Kinds::Behaviour::package(K));
     }
     
    -int PL::Counting::counting_compile_model_tables(void) {
    +int PL::Counting::counting_compile_model_tables(void) {
         kind *K;
         LOOP_OVER_BASE_KINDS(K)
             if (Kinds::Behaviour::is_subkind_of_object(K)) {
    -            inter_name *iname = PL::Counting::first_instance(K);
    -            instance *next = PL::Counting::next_instance_of(NULL, K);
    +            inter_name *iname = PL::Counting::first_instance(K);
    +            instance *next = PL::Counting::next_instance_of(NULL, K);
                 if (next) {
    -                Emit::named_iname_constant(iname, K_object, RTInstances::emitted_iname(next));
    +                Emit::named_iname_constant(iname, K_object, RTInstances::emitted_iname(next));
                 } else {
    -                Emit::named_iname_constant(iname, K_object, NULL);
    +                Emit::named_iname_constant(iname, K_object, NULL);
                 }
             }
         return FALSE;
    @@ -310,7 +310,7 @@ since Inform always compiles code which knows which kind it's looping over.
     

    -int PL::Counting::kind_of_object_count(kind *K) {
    +int PL::Counting::kind_of_object_count(kind *K) {
         int c = 0;
         if (K == NULL) return 0;
         kind *IK;
    @@ -341,14 +341,14 @@ of model completion:
     

    -int PL::Counting::counting_complete_model(int stage) {
    -    if (stage == 1) {
    -        Create and assert zero values of the vector property11.1;
    +int PL::Counting::counting_complete_model(int stage) {
    +    if (stage == WORLD_STAGE_I) {
    +        Create and assert zero values of the vector property11.1;
         }
    -    if (stage == 4) {
    -        Create the two instance properties for each kind of object11.2;
    -        PL::Counting::make_instance_counts();
    -        Assert values of the two instance properties for each instance11.3;
    +    if (stage == WORLD_STAGE_V) {
    +        Create the two instance properties for each kind of object11.2;
    +        PL::Counting::make_instance_counts();
    +        Assert values of the two instance properties for each instance11.3;
         }
         return FALSE;
     }
    @@ -361,14 +361,14 @@ for the relation-route-finding code at run time.
     

    -    P_vector = Properties::Valued::new_nameless(I"vector", K_number);
    +    P_vector = Properties::Valued::new_nameless(I"vector", K_number);
         parse_node *zero = Rvalues::from_int(0, EMPTY_WORDING);
    -    instance *I;
    +    instance *I;
         LOOP_OVER_INSTANCES(I, K_object)
    -        Properties::Valued::assert(P_vector,
    -            Instances::as_subject(I), zero, CERTAIN_CE);
    +        Properties::Valued::assert(P_vector,
    +            Instances::as_subject(I), zero, CERTAIN_CE);
     
    -
    • This code is used in §11.
    +
    • This code is used in §11.

    §11.2. Create the two instance properties for each kind of object11.2 =

    @@ -376,40 +376,40 @@ for the relation-route-finding code at run time. kind *K; LOOP_OVER_BASE_KINDS(K) if (Kinds::Behaviour::is_subkind_of_object(K)) { - inference_subject *subj = KindSubjects::from_kind(K); - inter_name *count_iname = PL::Counting::instance_count_iname(K); + inference_subject *subj = KindSubjects::from_kind(K); + inter_name *count_iname = PL::Counting::instance_count_iname(K); COUNTING_DATA(subj)->instance_count_prop = - Properties::Valued::new_nameless_using(K_number, Kinds::Behaviour::package(K), count_iname); + Properties::Valued::new_nameless_using(K_number, Kinds::Behaviour::package(K), count_iname); - inter_name *next_iname = PL::Counting::next_instance(K); + inter_name *next_iname = PL::Counting::next_instance(K); COUNTING_DATA(subj)->instance_link_prop = - Properties::Valued::new_nameless_using(K_object, Kinds::Behaviour::package(K), next_iname); + Properties::Valued::new_nameless_using(K_object, Kinds::Behaviour::package(K), next_iname); } - P_KD_Count = Properties::Valued::new_nameless(I"KD_Count", K_number); + P_KD_Count = Properties::Valued::new_nameless(I"KD_Count", K_number);
    -
    • This code is used in §11.
    +
    • This code is used in §11.

    §11.3. Assert values of the two instance properties for each instance11.3 =

    -    instance *I;
    +    instance *I;
         LOOP_OVER_INSTANCES(I, K_object) {
    -        Fill in the special IK0-Count property11.3.1;
    -        inference_subject *infs;
    -        for (infs = KindSubjects::from_kind(Instances::to_kind(I));
    -            infs; infs = InferenceSubjects::narrowest_broader_subject(infs)) {
    -            kind *K = KindSubjects::to_kind(infs);
    +        Fill in the special IK0-Count property11.3.1;
    +        inference_subject *infs;
    +        for (infs = KindSubjects::from_kind(Instances::to_kind(I));
    +            infs; infs = InferenceSubjects::narrowest_broader_subject(infs)) {
    +            kind *K = KindSubjects::to_kind(infs);
                 if (Kinds::Behaviour::is_subkind_of_object(K)) {
    -                inference_subject *subj = KindSubjects::from_kind(K);
    +                inference_subject *subj = KindSubjects::from_kind(K);
                     COUNTING_DATA(subj)->has_instances = TRUE;
    -                Fill in this IK-Count property11.3.2;
    -                Fill in this IK-Link property11.3.3;
    +                Fill in this IK-Count property11.3.2;
    +                Fill in this IK-Link property11.3.3;
                 }
             }
         }
     
    -
    • This code is used in §11.
    +
    • This code is used in §11.

    §11.3.1. As noted above, KD_Count is a special case. This looks as if it should be the instance count of "kind" itself, but that would be useless, since no instance object can ever have kind "kind" — instances aren't kinds. @@ -426,12 +426,12 @@ usage is legal.

    -    int ic = PL::Counting::kind_of_object_count(Instances::to_kind(I));
    +    int ic = PL::Counting::kind_of_object_count(Instances::to_kind(I));
         parse_node *the_count = Rvalues::from_int(ic, EMPTY_WORDING);
    -    Properties::Valued::assert(
    -        P_KD_Count, Instances::as_subject(I), the_count, CERTAIN_CE);
    +    Properties::Valued::assert(
    +        P_KD_Count, Instances::as_subject(I), the_count, CERTAIN_CE);
     
    - +

    §11.3.2. And otherwise, for every kind that the instance belongs to (directly or indirectly) it gets the relevant instance count as a property value. For example, the red door might have IK4_Count set to 3 — it's door number 3, @@ -446,11 +446,11 @@ and so on for all other kinds.

         int ic = INSTANCE_COUNT(I, K);
         parse_node *the_count = Rvalues::from_int(ic, EMPTY_WORDING);
    -    Properties::Valued::assert(
    +    Properties::Valued::assert(
             COUNTING_DATA(subj)->instance_count_prop,
    -        Instances::as_subject(I), the_count, CERTAIN_CE);
    +        Instances::as_subject(I), the_count, CERTAIN_CE);
     
    - +

    §11.3.3. The IK-Link property is never set for kind 0, so there's no special case. It records the next instance in compilation order:

    @@ -459,19 +459,19 @@ records the next instance in compilation order:

    -    Properties::Valued::assert(
    +    Properties::Valued::assert(
             COUNTING_DATA(subj)->instance_link_prop,
    -        Instances::as_subject(I), PL::Counting::next_instance_of_as_value(I, K), CERTAIN_CE);
    +        Instances::as_subject(I), PL::Counting::next_instance_of_as_value(I, K), CERTAIN_CE);
     
    - +

    §12.

    -inter_name *PL::Counting::instance_count_property_symbol(kind *K) {
    +inter_name *PL::Counting::instance_count_property_symbol(kind *K) {
         if (Kinds::Behaviour::is_subkind_of_object(K)) {
    -        inference_subject *subj = KindSubjects::from_kind(K);
    -        property *P = COUNTING_DATA(subj)->instance_count_prop;
    -        if (P) return Properties::iname(P);
    +        inference_subject *subj = KindSubjects::from_kind(K);
    +        property *P = COUNTING_DATA(subj)->instance_count_prop;
    +        if (P) return Properties::iname(P);
         }
         return NULL;
     }
    @@ -481,11 +481,11 @@ per instance per kind, so:
     

    -int PL::Counting::counting_estimate_property_usage(kind *k, int *words_used) {
    -    inference_subject *infs;
    -    for (infs = InferenceSubjects::narrowest_broader_subject(KindSubjects::from_kind(k));
    -        infs; infs = InferenceSubjects::narrowest_broader_subject(infs)) {
    -        kind *k2 = KindSubjects::to_kind(infs);
    +int PL::Counting::counting_estimate_property_usage(kind *k, int *words_used) {
    +    inference_subject *infs;
    +    for (infs = InferenceSubjects::narrowest_broader_subject(KindSubjects::from_kind(k));
    +        infs; infs = InferenceSubjects::narrowest_broader_subject(infs)) {
    +        kind *k2 = KindSubjects::to_kind(infs);
             if (Kinds::Behaviour::is_subkind_of_object(k2))
                 *words_used += 4;
         }
    @@ -499,21 +499,21 @@ constants, and use the Link constants to progress; we stop at 
     int PL::Counting::optimise_loop(i6_schema *sch, kind *K) {
    -    if (Plugins::Manage::plugged_in(counting_plugin) == FALSE) return FALSE;
    -    inference_subject *subj = KindSubjects::from_kind(K);
    +    if (Plugins::Manage::plugged_in(counting_plugin) == FALSE) return FALSE;
    +    inference_subject *subj = KindSubjects::from_kind(K);
         if (COUNTING_DATA(subj)->has_instances == FALSE)  (to avoid writing misleading code)
             Calculus::Schemas::modify(sch,
                 "for (*1=nothing: false: )");
         else {
    -        inter_name *first_iname = PL::Counting::first_instance(K);
    -        inter_name *next_iname = PL::Counting::next_instance(K);
    +        inter_name *first_iname = PL::Counting::first_instance(K);
    +        inter_name *next_iname = PL::Counting::next_instance(K);
             Calculus::Schemas::modify(sch, "for (*1=%n: *1: *1=*1.%n)", first_iname, next_iname);
         }
         return TRUE;
     }
     
    diff --git a/docs/runtime-module/4-ins.html b/docs/runtime-module/4-ins.html index 33a682567..bbdca8598 100644 --- a/docs/runtime-module/4-ins.html +++ b/docs/runtime-module/4-ins.html @@ -144,7 +144,7 @@ declarations) and finally return Properties::Emit::emit_subject(infs); } -inter_name *RTInstances::emitted_iname(instance *I) { +inter_name *RTInstances::emitted_iname(instance *I) { if (I == NULL) return NULL; inter_name *iname = RTInstances::iname(I); if (I->icd.instance_emitted == FALSE) { @@ -160,7 +160,7 @@ declarations) and finally return }
    diff --git a/docs/runtime-module/4-itc.html b/docs/runtime-module/4-itc.html index 3227d43d6..abc194ed8 100644 --- a/docs/runtime-module/4-itc.html +++ b/docs/runtime-module/4-itc.html @@ -563,7 +563,7 @@ only and may change at any time without notice.
    • This code is used in §7.
    diff --git a/docs/runtime-module/4-iti.html b/docs/runtime-module/4-iti.html index abf1d2bd3..aca024590 100644 --- a/docs/runtime-module/4-iti.html +++ b/docs/runtime-module/4-iti.html @@ -420,7 +420,7 @@ time.) {-index:name}}
    diff --git a/docs/runtime-module/4-jl.html b/docs/runtime-module/4-jl.html index 3aec2f721..f0aeb91c1 100644 --- a/docs/runtime-module/4-jl.html +++ b/docs/runtime-module/4-jl.html @@ -202,7 +202,7 @@ specification --> 0 }
    diff --git a/docs/runtime-module/4-lpart.html b/docs/runtime-module/4-lpart.html index cd3d6eb6e..cd39c6251 100644 --- a/docs/runtime-module/4-lpart.html +++ b/docs/runtime-module/4-lpart.html @@ -1551,7 +1551,7 @@ the sorting measure. }
    diff --git a/docs/runtime-module/4-lt.html b/docs/runtime-module/4-lt.html index cb18e9085..bab33e3a6 100644 --- a/docs/runtime-module/4-lt.html +++ b/docs/runtime-module/4-lt.html @@ -182,7 +182,7 @@ is significant to the run-time list-printing code.
    • This code is used in §3.
    diff --git a/docs/runtime-module/4-ni.html b/docs/runtime-module/4-ni.html index 46f22b90d..5dcf56fab 100644 --- a/docs/runtime-module/4-ni.html +++ b/docs/runtime-module/4-ni.html @@ -159,7 +159,7 @@ instance, the Standard Rules want the player-character object to be called }
    diff --git a/docs/runtime-module/4-pc.html b/docs/runtime-module/4-pc.html index 072b3278f..96d2f1451 100644 --- a/docs/runtime-module/4-pc.html +++ b/docs/runtime-module/4-pc.html @@ -81,6 +81,7 @@ function togglePopup(material_id) {
    define PLUGIN_NEW_VARIABLE_NOTIFY 1
     define PLUGIN_IRREGULAR_GENITIVE 4
     define PLUGIN_SET_KIND_NOTIFY 6
    +define PLUGIN_CREATE_INFERENCE_FAMILIES 10
     define PLUGIN_COMPLETE_MODEL 11
     define PLUGIN_PARSE_COMPOSITE_NQS 12
     define PLUGIN_REFINE_IMPLICIT_NOUN 14
    @@ -228,8 +229,12 @@ function togglePopup(material_id) {
         PLUGINS_CALL(PLUGIN_SET_SUBKIND_NOTIFY, sub, super);
     }
     
    +int Plugins::Call::create_inference_families(void) {
    +    PLUGINS_CALLV(PLUGIN_CREATE_INFERENCE_FAMILIES);
    +}
    +
     int Plugins::Call::complete_model(int stage) {
    -    World::Inferences::diversion_off();
    +    Inferences::diversion_off();
         PLUGINS_CALL(PLUGIN_COMPLETE_MODEL, stage);
     }
     
    @@ -331,7 +336,7 @@ function togglePopup(material_id) {
     }
     
    diff --git a/docs/runtime-module/4-plg.html b/docs/runtime-module/4-plg.html index 7d2b48a93..bd576455c 100644 --- a/docs/runtime-module/4-plg.html +++ b/docs/runtime-module/4-plg.html @@ -242,7 +242,7 @@ present. CREATE_STARTLESS_PLUGIN(IF_plugin, FALSE, IF_PLUGIN_NAME, IF_PLUGIN_NAME); CREATE_STARTLESS_PLUGIN(multimedia_plugin, FALSE, MULTIMEDIA_PLUGIN_NAME, MULTIMEDIA_PLUGIN_NAME); - CREATE_PLUGIN(counting_plugin, PL::Counting::start, TRUE, INSTANCE_COUNTING_PLUGIN_NAME, CORE_PLUGIN_NAME); + CREATE_PLUGIN(counting_plugin, PL::Counting::start, TRUE, INSTANCE_COUNTING_PLUGIN_NAME, CORE_PLUGIN_NAME); #ifdef IF_MODULE CREATE_PLUGIN(naming_plugin, PL::Naming::start, FALSE, NAMING_PLUGIN_NAME, CORE_PLUGIN_NAME); @@ -462,12 +462,12 @@ with the following. WRITE(".\n"); } -int Plugins::Manage::plugged_in(plugin *P) { +int Plugins::Manage::plugged_in(plugin *P) { return P->now_plugged_in; }
    diff --git a/docs/runtime-module/4-rart.html b/docs/runtime-module/4-rart.html index 12bcd6009..f1cfb1153 100644 --- a/docs/runtime-module/4-rart.html +++ b/docs/runtime-module/4-rart.html @@ -1317,10 +1317,10 @@ this is done by the routine R kind *right_kind = BinaryPredicates::term_kind(bp, 1); if ((Kinds::Behaviour::is_subkind_of_object(left_kind)) && (left_count > 0)) { - Emit::array_iname_entry(PL::Counting::instance_count_property_symbol(left_kind)); + Emit::array_iname_entry(PL::Counting::instance_count_property_symbol(left_kind)); } else Emit::array_numeric_entry(0); if ((Kinds::Behaviour::is_subkind_of_object(right_kind)) && (right_count > 0)) { - Emit::array_iname_entry(PL::Counting::instance_count_property_symbol(right_kind)); + Emit::array_iname_entry(PL::Counting::instance_count_property_symbol(right_kind)); } else Emit::array_numeric_entry(0); Emit::array_numeric_entry((inter_ti) left_count); @@ -1433,9 +1433,9 @@ to send the pairs in that row in any order.
         inference *inf;
    -    POSITIVE_KNOWLEDGE_LOOP(inf, World::Inferences::bp_as_subject(bp), ARBITRARY_RELATION_INF) {
    +    POSITIVE_KNOWLEDGE_LOOP(inf, Inferences::bp_as_subject(bp), arbitrary_relation_inf) {
             inference_subject *left_infs, *right_infs;
    -        World::Inferences::get_references(inf, &left_infs, &right_infs);
    +        Inferences::get_references(inf, &left_infs, &right_infs);
             if (infs == left_infs) row_flags[RTRelations::get_relation_index(right_infs, 1)] = 1;
         }
     
    @@ -2153,9 +2153,9 @@ matches the specific necessary kind of object if there is one. packaging_state save = Routines::begin(RTRelations::initialiser_iname(bp)); inference *i; inter_name *rtiname = Hierarchy::find(RELATIONTEST_HL); - POSITIVE_KNOWLEDGE_LOOP(i, World::Inferences::bp_as_subject(bp), ARBITRARY_RELATION_INF) { + POSITIVE_KNOWLEDGE_LOOP(i, Inferences::bp_as_subject(bp), arbitrary_relation_inf) { parse_node *spec0, *spec1; - World::Inferences::get_references_spec(i, &spec0, &spec1); + Inferences::get_references_spec(i, &spec0, &spec1); RTRelations::mark_as_needed(bp); Produce::inv_call_iname(Emit::tree(), rtiname); Produce::down(Emit::tree()); @@ -2175,7 +2175,7 @@ matches the specific necessary kind of object if there is one. }
    diff --git a/docs/runtime-module/4-rsfk.html b/docs/runtime-module/4-rsfk.html index 905e29eab..ba034f140 100644 --- a/docs/runtime-module/4-rsfk.html +++ b/docs/runtime-module/4-rsfk.html @@ -131,7 +131,7 @@ kinds being compiled to an I6 return NULL; } -int RTKinds::I6_classnumber(kind *K) { +int RTKinds::I6_classnumber(kind *K) { return Kinds::Behaviour::get_range_number(K); }
    @@ -1129,7 +1129,7 @@ each such kind, and needed at run-time.
    define MAX_KIND_ARITY 32
     
    -inter_name *RTKinds::iname(kind *K) {
    +inter_name *RTKinds::iname(kind *K) {
         if (RTKinds::base_represented_in_inter(K) == FALSE) {
             kind_interaction *KI;
             LOOP_OVER(KI, kind_interaction)
    @@ -2225,7 +2225,7 @@ particular order.
     }
     
    diff --git a/docs/runtime-module/4-rsft.html b/docs/runtime-module/4-rsft.html index f8cef0071..66e2ec5ad 100644 --- a/docs/runtime-module/4-rsft.html +++ b/docs/runtime-module/4-rsft.html @@ -541,7 +541,7 @@ should return FALSE}
    diff --git a/docs/runtime-module/4-rsp.html b/docs/runtime-module/4-rsp.html index 69a100cc9..bc7d4bfae 100644 --- a/docs/runtime-module/4-rsp.html +++ b/docs/runtime-module/4-rsp.html @@ -697,7 +697,7 @@ text needs to be printed in a particular way.
    diff --git a/docs/runtime-module/4-rtn.html b/docs/runtime-module/4-rtn.html index 8b2a4f691..03af8b600 100644 --- a/docs/runtime-module/4-rtn.html +++ b/docs/runtime-module/4-rtn.html @@ -307,7 +307,7 @@ after the call parameters, and is used only as a scratch variable.
    • This code is used in §4.
    diff --git a/docs/runtime-module/4-tl.html b/docs/runtime-module/4-tl.html index 6faaa6006..3fd043379 100644 --- a/docs/runtime-module/4-tl.html +++ b/docs/runtime-module/4-tl.html @@ -445,7 +445,7 @@ number -1). }
    diff --git a/docs/runtime-module/4-ts.html b/docs/runtime-module/4-ts.html index d324e7281..02db387f2 100644 --- a/docs/runtime-module/4-ts.html +++ b/docs/runtime-module/4-ts.html @@ -460,7 +460,7 @@ we aren't doing very much; most TSs will be passed quickly over. }
    diff --git a/docs/runtime-module/4-ts2.html b/docs/runtime-module/4-ts2.html index 244745e6b..67fbea940 100644 --- a/docs/runtime-module/4-ts2.html +++ b/docs/runtime-module/4-ts2.html @@ -297,7 +297,7 @@ stipulations on place and possessions attached. }
    diff --git a/docs/runtime-module/4-tv.html b/docs/runtime-module/4-tv.html index a7df96677..b403a3fcc 100644 --- a/docs/runtime-module/4-tv.html +++ b/docs/runtime-module/4-tv.html @@ -169,7 +169,7 @@ hacky constructs which only the SR should ever refer to. }
    diff --git a/docs/runtime-module/4-uoart.html b/docs/runtime-module/4-uoart.html index b7370af7f..14e34aeaf 100644 --- a/docs/runtime-module/4-uoart.html +++ b/docs/runtime-module/4-uoart.html @@ -205,7 +205,7 @@ source code: see the DM4 for details. }
    diff --git a/docs/runtime-module/4-vart.html b/docs/runtime-module/4-vart.html index b75da4909..f72ff7689 100644 --- a/docs/runtime-module/4-vart.html +++ b/docs/runtime-module/4-vart.html @@ -649,7 +649,7 @@ usages to the debugging log. }
    diff --git a/docs/runtime-module/4-vrb.html b/docs/runtime-module/4-vrb.html index 680588847..b31089bde 100644 --- a/docs/runtime-module/4-vrb.html +++ b/docs/runtime-module/4-vrb.html @@ -476,7 +476,7 @@ which makes its kind safe. Hence the error messages.
    • This code is used in §6.
    diff --git a/docs/runtime-module/index.html b/docs/runtime-module/index.html index 71f09b91f..0708bcf5d 100644 --- a/docs/runtime-module/index.html +++ b/docs/runtime-module/index.html @@ -243,6 +243,11 @@ Instances
    - To compile run-time support for instances.

    +
  • +

    + Instance Counting - + A plugin which maintains run-time-accessible linked lists of instances of kinds, in order to speed up loops; and instance counts within kinds, in order to speed up relation storage; and the object-kind hierarchy, in order to speed up run-time checking of the type safety of property usage.

    +
  • Adjectives - diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt index 1067fd68a..99325dd6f 100644 --- a/inform7/Figures/memory-diagnostics.txt +++ b/inform7/Figures/memory-diagnostics.txt @@ -1,14 +1,14 @@ -Total memory consumption was 258318K = 252 MB +Total memory consumption was 258538K = 252 MB -62.5% was used for 1333781 objects, in 275500 frames in 202 x 800K = 161600K = 157 MB: +62.5% was used for 1336464 objects, in 278183 frames in 202 x 800K = 161600K = 157 MB: 9.8% inter_tree_node_array 36 x 8192 = 294912 objects, 25953408 bytes 5.5% text_stream_array 2592 x 100 = 259200 objects, 14598144 bytes 3.9% parse_node 129993 objects, 10399440 bytes 2.8% verb_conjugation 160 objects, 7425280 bytes 2.6% parse_node_annotation_array 431 x 500 = 215500 objects, 6909792 bytes + 2.4% linked_list 11741 objects, 6574960 bytes 2.3% inter_symbol_array 70 x 1024 = 71680 objects, 6310080 bytes - 2.2% linked_list 10403 objects, 5825680 bytes 1.2% pcalc_prop_array 24 x 1000 = 24000 objects, 3264768 bytes 1.1% map_data 668 objects, 3168992 bytes 0.9% kind_array 65 x 1000 = 65000 objects, 2602080 bytes @@ -41,7 +41,7 @@ Total memory consumption was 258318K = 252 MB 0.1% noun 2379 objects, 285480 bytes ---- action_name_list_array 3 x 1000 = 3000 objects, 240096 bytes ---- inter_annotation_array 1 x 8192 objects, 196640 bytes - ---- inference 1703 objects, 177112 bytes + ---- inference 1703 objects, 163488 bytes ---- linguistic_stock_item 3315 objects, 159120 bytes ---- binary_predicate 321 objects, 156648 bytes ---- stacked_variable_owner_list_array 38 x 100 = 3800 objects, 153216 bytes @@ -66,6 +66,7 @@ Total memory consumption was 258318K = 252 MB ---- ph_stack_frame_box 577 objects, 55392 bytes ---- property_permission 96 objects, 55296 bytes ---- kind_constructor 77 objects, 54824 bytes + ---- property_inference_data 1315 objects, 52600 bytes ---- text_substitution 436 objects, 48832 bytes ---- grammar_line 230 objects, 46000 bytes ---- table 7 objects, 45528 bytes @@ -88,15 +89,15 @@ Total memory consumption was 258318K = 252 MB ---- nonlocal_variable 93 objects, 19344 bytes ---- action_name 90 objects, 18720 bytes ---- parse_node_tree 20 objects, 17280 bytes - ---- linked_list_item_array 1 x 1000 objects, 16032 bytes ---- match_avinue_array 1 x 1000 objects, 16032 bytes + ---- linked_list_item_array 1 x 1000 objects, 16032 bytes ---- to_phrase_request 59 objects, 15576 bytes - ---- method 317 objects, 15216 bytes + ---- method 323 objects, 15504 bytes ---- adjective 137 objects, 14248 bytes ---- plugin 23 objects, 13432 bytes ---- literal_text 147 objects, 12936 bytes ---- adjective_iname_holder 320 objects, 12800 bytes - ---- stopwatch_timer 148 objects, 11840 bytes + ---- stopwatch_timer 150 objects, 12000 bytes ---- understanding_reference_array 2 x 100 = 200 objects, 11264 bytes ---- pathname 262 objects, 10480 bytes ---- filename 208 objects, 8320 bytes @@ -112,31 +113,31 @@ Total memory consumption was 258318K = 252 MB ---- parsing_pp_data 96 objects, 4608 bytes ---- build_vertex 40 objects, 4480 bytes ---- hierarchy_attachment_point 48 objects, 4224 bytes - ---- stacked_variable_list_array 1 x 100 objects, 4032 bytes ---- placement_affecting_array 1 x 100 objects, 4032 bytes + ---- stacked_variable_list_array 1 x 100 objects, 4032 bytes ---- activity 35 objects, 3920 bytes ---- inbuild_edition 54 objects, 3888 bytes ---- parse_node_annotation_type 118 objects, 3776 bytes ---- inbuild_copy 35 objects, 3640 bytes ---- command_line_switch 43 objects, 3440 bytes ---- property_setting_bp_data 84 objects, 3360 bytes - ---- instance_usage_array 1 x 200 objects, 3232 bytes ---- kind_constructor_comparison_schema_array 1 x 100 objects, 3232 bytes - ---- definition 44 objects, 3168 bytes + ---- instance_usage_array 1 x 200 objects, 3232 bytes + ---- method_set 100 objects, 3200 bytes ---- compatibility_specification 66 objects, 3168 bytes + ---- definition 44 objects, 3168 bytes ---- inform_extension 19 objects, 3040 bytes ---- property_of_value_storage 93 objects, 2976 bytes ---- submodule_request 72 objects, 2880 bytes - ---- method_set 89 objects, 2848 bytes ---- inter_construct 32 objects, 2560 bytes - ---- kind_constructor_casting_rule_array 1 x 100 objects, 2432 bytes ---- kind_constructor_instance_array 1 x 100 objects, 2432 bytes + ---- kind_constructor_casting_rule_array 1 x 100 objects, 2432 bytes ---- equation_symbol 30 objects, 2400 bytes ---- semver_range 22 objects, 2288 bytes ---- use_option 29 objects, 1856 bytes ---- pronoun_usage 42 objects, 1680 bytes - ---- activity_crossref_array 1 x 100 objects, 1632 bytes ---- table_contribution_array 1 x 100 objects, 1632 bytes + ---- activity_crossref_array 1 x 100 objects, 1632 bytes ---- plugin_call_array 1 x 100 objects, 1632 bytes ---- kind_interaction 39 objects, 1560 bytes ---- inter_annotation_form 37 objects, 1480 bytes @@ -144,8 +145,8 @@ Total memory consumption was 258318K = 252 MB ---- noun_filter_token 22 objects, 1408 bytes ---- scene 1 object, 1344 bytes ---- special_meaning_holder 33 objects, 1320 bytes - ---- constant_phrase 20 objects, 1280 bytes ---- build_script 40 objects, 1280 bytes + ---- constant_phrase 20 objects, 1280 bytes ---- invocation_options_array 1 x 100 objects, 1224 bytes ---- hierarchy_metadatum 15 objects, 1200 bytes ---- quantifier 16 objects, 1024 bytes @@ -156,38 +157,39 @@ Total memory consumption was 258318K = 252 MB ---- cached_understanding 21 objects, 840 bytes ---- runtime_kind_structure 13 objects, 832 bytes ---- phrase_option_array 1 x 100 objects, 824 bytes - ---- pipeline_stage 17 objects, 816 bytes ---- target_vm 6 objects, 816 bytes + ---- pipeline_stage 17 objects, 816 bytes ---- generated_segment 25 objects, 800 bytes ---- inter_data_type 14 objects, 784 bytes ---- submodule_identity 23 objects, 736 bytes - ---- implication 13 objects, 728 bytes ---- rulebook_outcome 17 objects, 680 bytes ---- inform_language 6 objects, 672 bytes ---- inter_warehouse_room 10 objects, 640 bytes - ---- relation_guard 5 objects, 640 bytes ---- I6T_intervention 8 objects, 640 bytes + ---- relation_guard 5 objects, 640 bytes ---- nascent_array 7 objects, 616 bytes - ---- named_rulebook_outcome 15 objects, 600 bytes ---- inbuild_search_result 15 objects, 600 bytes + ---- named_rulebook_outcome 15 objects, 600 bytes ---- label_namespace 10 objects, 560 bytes ---- small_word_set 11 objects, 528 bytes + ---- implication 13 objects, 520 bytes ---- inform_kit 5 objects, 520 bytes - ---- i6_memory_setting 13 objects, 416 bytes + ---- inference_family 11 objects, 440 bytes ---- equation 4 objects, 416 bytes - ---- module_package 10 objects, 400 bytes + ---- i6_memory_setting 13 objects, 416 bytes ---- dval_written 10 objects, 400 bytes + ---- module_package 10 objects, 400 bytes ---- bp_family 12 objects, 384 bytes ---- article_usage 8 objects, 384 bytes ---- source_file 5 objects, 360 bytes ---- inbuild_genre 7 objects, 336 bytes - ---- pronoun 8 objects, 320 bytes - ---- grammatical_category 8 objects, 320 bytes ---- door_dir_notice 5 objects, 320 bytes - ---- up_family 9 objects, 288 bytes + ---- grammatical_category 8 objects, 320 bytes + ---- pronoun 8 objects, 320 bytes ---- build_step 4 objects, 288 bytes - ---- explicit_bp_data 5 objects, 280 bytes + ---- up_family 9 objects, 288 bytes ---- door_to_notice 5 objects, 280 bytes + ---- explicit_bp_data 5 objects, 280 bytes ---- inform_pipeline 4 objects, 256 bytes ---- verb_usage_tier 5 objects, 240 bytes ---- adjective_meaning_family 7 objects, 224 bytes @@ -197,33 +199,33 @@ Total memory consumption was 258318K = 252 MB ---- plural_dictionary_entry 4 objects, 192 bytes ---- kit_dependency 4 objects, 192 bytes ---- inform_project 1 object, 176 bytes - ---- code_generation_target 4 objects, 160 bytes - ---- inter_architecture 4 objects, 160 bytes - ---- inference_subject_family 5 objects, 160 bytes ---- link_instruction 4 objects, 160 bytes ---- pointer_allocation 2 objects, 160 bytes + ---- inter_architecture 4 objects, 160 bytes + ---- code_generation_target 4 objects, 160 bytes + ---- inference_subject_family 5 objects, 160 bytes ---- element_activation 4 objects, 128 bytes ---- codegen_pipeline 1 object, 128 bytes ---- inbuild_nest 3 objects, 120 bytes ---- inform_kit_ittt 2 objects, 96 bytes - ---- compile_task_data 1 object, 80 bytes ---- article 2 objects, 80 bytes + ---- compile_task_data 1 object, 80 bytes ---- list_together_routine 2 objects, 80 bytes - ---- inter_warehouse 1 object, 56 bytes ---- build_methodology 1 object, 56 bytes - ---- HTML_file_state 1 object, 48 bytes - ---- blorb_figure 1 object, 48 bytes + ---- inter_warehouse 1 object, 56 bytes ---- star_invention 1 object, 48 bytes - ---- loop_over_scope 1 object, 40 bytes + ---- blorb_figure 1 object, 48 bytes + ---- HTML_file_state 1 object, 48 bytes ---- by_routine_bp_data 1 object, 40 bytes - ---- kind_template_definition 1 object, 40 bytes ---- parse_name_notice 1 object, 40 bytes + ---- loop_over_scope 1 object, 40 bytes + ---- kind_template_definition 1 object, 40 bytes 37.4% was used for memory not allocated for objects: - 15.9% text stream storage 42223988 bytes in 265557 claims + 15.9% text stream storage 42228404 bytes in 265592 claims 3.5% dictionary storage 9266176 bytes in 16348 claims - ---- sorting 1048 bytes in 3 claims + ---- sorting 1064 bytes in 3 claims 2.7% source text 7200000 bytes in 3 claims 4.0% source text details 10800000 bytes in 2 claims ---- linguistic stock array 81920 bytes in 2 claims @@ -231,12 +233,11 @@ Total memory consumption was 258318K = 252 MB 0.8% inter symbols storage 2277376 bytes in 13914 claims 6.3% inter bytecode storage 16802820 bytes in 14 claims 3.3% inter links storage 8750208 bytes in 246 claims - 0.5% instance-of-kind counting 1468944 bytes in 1 claim - ---- size estimates for compiled objects 308 bytes in 1 claim + 0.6% instance-of-kind counting 1690000 bytes in 1 claim ---- compilation workspace for objects 21816 bytes in 25 claims ---- lists for type-checking invocations 16000 bytes in 1 claim ---- emitter array storage 14368 bytes in 8 claims ---- code generation workspace for objects 9200 bytes in 9 claims -20.1% was overhead - 53384224 bytes = 52133K = 50 MB +19.8% was overhead - 52594936 bytes = 51362K = 50 MB diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index 63c7d6eff..e4644a922 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,27 +1,28 @@ 100.0% in inform7 run 67.8% in compilation to Inter - 26.8% in //Phrases::Manager::compile_first_block// + 26.6% in //Phrases::Manager::compile_first_block// 8.3% in //Phrases::Manager::compile_as_needed// - 6.7% in //Strings::compile_responses// - 6.2% in //World::Compile::compile// - 4.2% in //MajorNodes::pre_pass// + 6.9% in //Strings::compile_responses// + 6.0% in //InferenceSubjects::emit_all// + 4.3% in //MajorNodes::pre_pass// 3.3% in //MajorNodes::pass_1// - 1.9% in //Phrases::Manager::RulePrintingRule_routine// - 1.7% in //Phrases::Manager::rulebooks_array// + 2.0% in //Phrases::Manager::RulePrintingRule_routine// + 1.9% in //Phrases::Manager::rulebooks_array// 1.0% in //RTVerbs::ConjugateVerb// 0.8% in //Phrases::Manager::traverse// 0.5% in //Phrases::Manager::parse_rule_parameters// - 0.5% in //World::complete// + 0.5% in //World::stage_V// 0.3% in //MajorNodes::pass_2// 0.3% in //Phrases::Manager::compile_rulebooks// 0.3% in //RTRelations::compile_defined_relations// 0.1% in //PL::Parsing::Verbs::compile_all// 0.1% in //RTKinds::compile_data_type_support_routines// 0.1% in //Task::make_built_in_kind_constructors// - 3.7% not specifically accounted for - 30.0% in running Inter pipeline - 9.7% in step preparation + 0.1% in //World::stages_II_and_III// + 3.5% not specifically accounted for + 29.7% in running Inter pipeline 9.5% in inter step 2/12: link + 9.5% in step preparation 6.9% in inter step 12/12: generate inform6 -> auto.inf 0.3% in inter step 9/12: make-identifiers-unique 0.1% in inter step 10/12: reconcile-verbs @@ -31,5 +32,5 @@ 0.1% in inter step 7/12: resolve-external-symbols 0.1% in inter step 8/12: inspect-plugs 2.3% not specifically accounted for - 1.9% in supervisor - 0.2% not specifically accounted for + 2.0% in supervisor + 0.4% not specifically accounted for diff --git a/inform7/assertions-module/Chapter 2/Passes through Major Nodes.w b/inform7/assertions-module/Chapter 2/Passes through Major Nodes.w index a093e1a8a..70a98f712 100644 --- a/inform7/assertions-module/Chapter 2/Passes through Major Nodes.w +++ b/inform7/assertions-module/Chapter 2/Passes through Major Nodes.w @@ -83,7 +83,7 @@ any additional sentences generated. @ = current_sentence = last; global_pass_state.assembly_position = current_sentence; - Plugins::Call::complete_model(1); + World::deduce_object_instance_kinds(); SyntaxTree::traverse_nodep_from(last, MajorNodes::visit, &last); @ Let us go, and make our visit: diff --git a/inform7/assertions-module/Chapter 4/Implications.w b/inform7/assertions-module/Chapter 4/Implications.w index 46e2b089f..5964b14ed 100644 --- a/inform7/assertions-module/Chapter 4/Implications.w +++ b/inform7/assertions-module/Chapter 4/Implications.w @@ -14,10 +14,9 @@ description only, whereas B could be any subtree of an assertion. = typedef struct implication { - struct pcalc_prop *if_spec; /* which objects are affected */ + struct pcalc_prop *if_proposition; /* which objects are affected */ struct parse_node *then_pn; /* what assertion is implied about them */ int implied_likelihood; /* with what certainty level */ - struct implication *next_implication; /* in list of implications */ CLASS_DEFINITION } implication; @@ -61,15 +60,13 @@ void Assertions::Implications::new(parse_node *px, parse_node *py) { @; implication *imp = CREATE(implication); - imp->if_spec = premiss; + imp->if_proposition = premiss; imp->then_pn = py; imp->implied_likelihood = prevailing_mood; - - imp->next_implication = InferenceSubjects::get_implications(premiss_kind); - InferenceSubjects::set_implications(premiss_kind, imp); + ADD_TO_LINKED_LIST(imp, implication, InferenceSubjects::get_implications(premiss_kind)); LOGIF(IMPLICATIONS, "Forming implication for $j: $D implies\n $T", - premiss_kind, imp->if_spec, imp->then_pn); + premiss_kind, imp->if_proposition, imp->then_pn); @ = parse_node *loc = px; @@ -156,9 +153,9 @@ void Assertions::Implications::set_possessed_flags(inference_subject *infs) { if (k) Assertions::Implications::set_possessed_flags(k); inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); - if ((Properties::is_either_or(prn)) && (World::Inferences::get_certainty(inf) != UNKNOWN_CE)) + KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *prn = PropertyInferences::get_property(inf); + if ((Properties::is_either_or(prn)) && (Inferences::get_certainty(inf) != UNKNOWN_CE)) @; } } @@ -168,7 +165,7 @@ both of them, because an inference of being closed is as good as an inference of not being open, and vice versa. @ = - int truth_state = TRUE, certainty = World::Inferences::get_certainty(inf); + int truth_state = TRUE, certainty = Inferences::get_certainty(inf); if (certainty < 0) { certainty = -certainty; truth_state = FALSE; } possession_marker *pom = Properties::get_possession_marker(prn); @@ -202,12 +199,12 @@ int Assertions::Implications::check_implications_of(inference_subject *domain, inference_subject *k = InferenceSubjects::narrowest_broader_subject(domain); if ((k) && (Assertions::Implications::check_implications_of(k, candidate))) return TRUE; - if (InferenceSubjects::get_implications(domain)) + if (LinkedLists::len(InferenceSubjects::get_implications(domain)) > 0) LOGIF(IMPLICATIONS, "Considering implications about $j as they apply to $j:\n", domain, candidate); implication *imp; - for (imp = InferenceSubjects::get_implications(domain); imp; imp = imp->next_implication) + LOOP_OVER_LINKED_LIST(imp, implication, InferenceSubjects::get_implications(domain)) @; return FALSE; @@ -220,7 +217,7 @@ int Assertions::Implications::check_implications_of(inference_subject *domain, if (imp->implied_likelihood < 0) conclusion_state = (conclusion_state)?FALSE:TRUE; LOGIF(IMPLICATIONS, "$D => $T (certainty %d; changed state %d)\n", - imp->if_spec, imp->then_pn, imp->implied_likelihood, conclusion_state); + imp->if_proposition, imp->then_pn, imp->implied_likelihood, conclusion_state); property *conclusion_prop = AdjectiveAmbiguity::has_either_or_property_meaning( AdjectivalPredicates::to_adjective(pred), NULL); @@ -229,7 +226,7 @@ int Assertions::Implications::check_implications_of(inference_subject *domain, possession_marker *pom = Properties::get_possession_marker(conclusion_prop); @; - int candidate_qualifies = Assert::test_at_compile_time(imp->if_spec, candidate); + int candidate_qualifies = Assert::test_at_compile_time(imp->if_proposition, candidate); if (candidate_qualifies) { LOGIF(IMPLICATIONS, "PASS: changing property $Y of $j\n", conclusion_prop, candidate); diff --git a/inform7/assertions-module/Chapter 6/Explicit Relations.w b/inform7/assertions-module/Chapter 6/Explicit Relations.w index 3244c471f..f48c66ea7 100644 --- a/inform7/assertions-module/Chapter 6/Explicit Relations.w +++ b/inform7/assertions-module/Chapter 6/Explicit Relations.w @@ -161,14 +161,14 @@ int Relations::Explicit::REL_assert(bp_family *self, binary_predicate *bp, @; if (Relations::Explicit::stored_dynamically(bp)) { - World::Inferences::draw_relation_spec(bp, spec0, spec1); + Inferences::draw_relation_spec(bp, spec0, spec1); return TRUE; } else { if ((infs0 == NULL) || (infs1 == NULL)) @; if (Relations::Explicit::allow_arbitrary_assertions(bp)) { - World::Inferences::draw_relation(bp, infs0, infs1); + Inferences::draw_relation(bp, infs0, infs1); if ((Relations::Explicit::get_form_of_relation(bp) == Relation_Sym_VtoV) && (infs0 != infs1)) - World::Inferences::draw_relation(bp, infs1, infs0); + Inferences::draw_relation(bp, infs1, infs0); return TRUE; } if (Relations::Explicit::is_explicit_with_runtime_storage(bp)) { @@ -218,7 +218,7 @@ void Relations::Explicit::infer_property_based_relation(binary_predicate *bp, inference_subject *swap=infs0; infs0=infs1; infs1=swap; } property *prn = Relations::Explicit::get_i6_storage_property(bp); - World::Inferences::draw_property(infs0, prn, InferenceSubjects::as_constant(infs1)); + PropertyInferences::draw(infs0, prn, InferenceSubjects::as_constant(infs1)); } @ We need do nothing special: these relations can be compiled from their schemas. diff --git a/inform7/assertions-module/Chapter 6/The Equality Relation Revisited.w b/inform7/assertions-module/Chapter 6/The Equality Relation Revisited.w index aef58ee96..e6475d438 100644 --- a/inform7/assertions-module/Chapter 6/The Equality Relation Revisited.w +++ b/inform7/assertions-module/Chapter 6/The Equality Relation Revisited.w @@ -114,7 +114,7 @@ int EqualityDetails::REL_assert(bp_family *self, binary_predicate *bp, "a variable can only be given its value straightforwardly or " "qualified by 'usually'", "not with 'always', 'seldom' or 'never'."); - else World::Inferences::draw_property( + else PropertyInferences::draw( NonlocalVariables::to_subject(q), P_variable_initial_value, spec1); return TRUE; } diff --git a/inform7/core-module/Chapter 1/Class Predeclarations.w b/inform7/core-module/Chapter 1/Class Predeclarations.w index 2ee15fa01..5002cea35 100644 --- a/inform7/core-module/Chapter 1/Class Predeclarations.w +++ b/inform7/core-module/Chapter 1/Class Predeclarations.w @@ -92,12 +92,14 @@ DECLARE_CLASS(text_substitution) @e comparative_bp_data_CLASS @e counting_data_CLASS @e inference_CLASS +@e inference_family_CLASS @e inference_subject_CLASS @e inference_subject_family_CLASS @e measurement_definition_CLASS @e named_rulebook_outcome_CLASS @e placement_affecting_CLASS @e property_CLASS +@e property_inference_data_CLASS @e property_permission_CLASS @e property_of_value_storage_CLASS @e property_setting_bp_data_CLASS @@ -118,6 +120,7 @@ DECLARE_CLASS(booking) DECLARE_CLASS(comparative_bp_data) DECLARE_CLASS(counting_data) DECLARE_CLASS(inference) +DECLARE_CLASS(inference_family) DECLARE_CLASS(inference_subject) DECLARE_CLASS(inference_subject_family) DECLARE_CLASS(measurement_definition) @@ -126,6 +129,7 @@ DECLARE_CLASS_ALLOCATED_IN_ARRAYS(placement_affecting, 100) DECLARE_CLASS(property_of_value_storage) DECLARE_CLASS(property_permission) DECLARE_CLASS(property) +DECLARE_CLASS(property_inference_data) DECLARE_CLASS(property_setting_bp_data) DECLARE_CLASS(rule) DECLARE_CLASS(rulebook) diff --git a/inform7/core-module/Chapter 1/How To Compile.w b/inform7/core-module/Chapter 1/How To Compile.w index 6008cfa61..66a07d9ee 100644 --- a/inform7/core-module/Chapter 1/How To Compile.w +++ b/inform7/core-module/Chapter 1/How To Compile.w @@ -153,7 +153,8 @@ so on. Those absolute basics are made here. BENCH(NounIdentifiers::name_all) BENCH(OrderingInstances::objects_in_definition_sequence) Task::advance_stage_to(MODEL_COMPLETE_CSEQ, I"Completing the model world", -1); - BENCH(World::complete) + BENCH(World::stages_II_and_III) + BENCH(World::stage_IV) @ = Task::advance_stage_to(TABLES_CSEQ, I"Tables and grammar", -1); @@ -166,7 +167,7 @@ so on. Those absolute basics are made here. BENCH(Tables::check_tables_for_kind_clashes) BENCH(RTTables::compile_print_table_names) BENCH(PL::Parsing::traverse) - BENCH(World::complete_additions) + BENCH(World::stage_V) @ = Task::advance_stage_to(PHRASES_CSEQ, I"Phrases and rules", 3); @@ -199,7 +200,8 @@ so on. Those absolute basics are made here. BENCH(RTRelations::compile_defined_relation_constants) BENCH(RTKinds::compile_data_type_support_routines) BENCH(RTKinds::I7_Kind_Name_routine) - BENCH(World::Compile::compile) + BENCH(Plugins::Call::compile_model_tables) + BENCH(InferenceSubjects::emit_all) BENCH_IF(backdrops_plugin, PL::Backdrops::write_found_in_routines) BENCH_IF(map_plugin, PL::Map::write_door_dir_routines) BENCH_IF(map_plugin, PL::Map::write_door_to_routines) diff --git a/inform7/core-module/Chapter 2/Supplementary Issues.w b/inform7/core-module/Chapter 2/Supplementary Issues.w index bcad5538e..c77502a2a 100644 --- a/inform7/core-module/Chapter 2/Supplementary Issues.w +++ b/inform7/core-module/Chapter 2/Supplementary Issues.w @@ -235,10 +235,10 @@ void StandardProblems::inference_problem(SIGIL_ARGUMENTS, inference_subject *inf char *message, char *explanation) { ACT_ON_SIGIL Problems::quote_subject(1, infs); - Problems::quote_source(2, World::Inferences::where_inferred(inf)); + Problems::quote_source(2, Inferences::where_inferred(inf)); Problems::quote_text(3, message); Problems::quote_text(4, explanation); - Problems::quote_property(5, World::Inferences::get_property(inf)); + Problems::quote_property(5, PropertyInferences::get_property(inf)); Problems::issue_problem_begin(Task::syntax_tree(), explanation); Problems::issue_problem_segment( "You wrote %2: but the property %5 for the %1 %3%S.%L, %4"); diff --git a/inform7/if-module/Chapter 3/Backdrops.w b/inform7/if-module/Chapter 3/Backdrops.w index d3e94fc34..0b97a86bc 100644 --- a/inform7/if-module/Chapter 3/Backdrops.w +++ b/inform7/if-module/Chapter 3/Backdrops.w @@ -9,10 +9,10 @@ spread, probably background, things, such as the sky, and they placing one inside something generates |FOUND_IN_INF| rather than |PARENTAGE_INF| inferences to avoid piling up bogus inconsistencies. -@d FOUND_IN_INF 56 /* for backdrop things in many places */ -@d FOUND_EVERYWHERE_INF 57 /* ditto */ - = (early code) +inference_family *FOUND_IN_INF = NULL; /* 56; for backdrop things in many places */ +inference_family *FOUND_EVERYWHERE_INF = NULL; /* 57; ditto */ + kind *K_backdrop = NULL; property *P_scenery = NULL; /* an I7 either/or property marking something as scenery */ property *P_absent = NULL; /* an I6-only property for backdrops out of play */ @@ -29,6 +29,10 @@ typedef struct backdrop_found_in_notice { = void PL::Backdrops::start(void) { + FOUND_IN_INF = Inferences::new_family(I"FOUND_IN_INF", CI_DIFFER_IN_INFS1); + FOUND_EVERYWHERE_INF = Inferences::new_family(I"FOUND_EVERYWHERE_INF", CI_DIFFER_IN_INFS1); + + PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Backdrops::create_inference_families); PLUGIN_REGISTER(PLUGIN_NEW_BASE_KIND_NOTIFY, PL::Backdrops::backdrops_new_base_kind_notify); PLUGIN_REGISTER(PLUGIN_NEW_PROPERTY_NOTIFY, PL::Backdrops::backdrops_new_property_notify); PLUGIN_REGISTER(PLUGIN_COMPLETE_MODEL, PL::Backdrops::backdrops_complete_model); @@ -37,6 +41,10 @@ void PL::Backdrops::start(void) { PLUGIN_REGISTER(PLUGIN_INTERVENE_IN_ASSERTION, PL::Backdrops::backdrops_intervene_in_assertion); } +int PL::Backdrops::create_inference_families(void) { + return FALSE; +} + @h Kinds. This a kind name to do with backdrops which Inform provides special support for; it recognises the English name when defined by the Standard Rules. (So @@ -78,7 +86,7 @@ int PL::Backdrops::backdrops_new_property_notify(property *prn) { } int PL::Backdrops::object_is_scenery(instance *I) { - if (World::Inferences::get_EO_state(Instances::as_subject(I), P_scenery) > 0) + if (Inferences::get_EO_state(Instances::as_subject(I), P_scenery) > 0) return TRUE; return FALSE; } @@ -95,10 +103,6 @@ int PL::Backdrops::backdrops_estimate_property_usage(kind *k, int *words_used) { = int PL::Backdrops::backdrops_log_inference_type(int it) { - switch(it) { - case FOUND_IN_INF: LOG("FOUND_IN_INF"); return TRUE; - case FOUND_EVERYWHERE_INF: LOG("FOUND_EVERYWHERE_INF"); return TRUE; - } return FALSE; } @@ -121,9 +125,9 @@ int PL::Backdrops::assert_relations(binary_predicate *relation, (relation == R_regional_containment))) { inference_subject *bd = Instances::as_subject(I1); inference_subject *loc = Instances::as_subject(I0); - World::Inferences::draw(PART_OF_INF, bd, IMPOSSIBLE_CE, loc, NULL); - World::Inferences::draw(IS_ROOM_INF, bd, IMPOSSIBLE_CE, NULL, NULL); - World::Inferences::draw(FOUND_IN_INF, bd, CERTAIN_CE, loc, loc); + Inferences::draw(PART_OF_INF, bd, IMPOSSIBLE_CE, loc, NULL); + Inferences::draw(IS_ROOM_INF, bd, IMPOSSIBLE_CE, NULL, NULL); + Inferences::draw(FOUND_IN_INF, bd, CERTAIN_CE, loc, loc); return TRUE; } @@ -136,7 +140,7 @@ int PL::Backdrops::assert_relations(binary_predicate *relation, LOOP_OVER_INSTANCES(B, K_object) if (PL::Backdrops::object_is_a_backdrop(B)) POSITIVE_KNOWLEDGE_LOOP(I, Instances::as_subject(B), FOUND_IN_INF) - if (World::Inferences::get_reference_as_object(I) == P) + if (Inferences::get_reference_as_object(I) == P) @d LOOP_OVER_BACKDROPS_EVERYWHERE(B, I) LOOP_OVER_INSTANCES(B, K_object) @@ -225,7 +229,7 @@ void PL::Backdrops::infer_presence_everywhere(instance *I) { "is a vehicle which is everywhere.' is not."); return; } - World::Inferences::draw(FOUND_EVERYWHERE_INF, + Inferences::draw(FOUND_EVERYWHERE_INF, Instances::as_subject(I), prevailing_mood, NULL, NULL); } @@ -234,7 +238,7 @@ We intervene only at Stage II, the spatial modelling stage. = int PL::Backdrops::backdrops_complete_model(int stage) { - if (stage == 2) { + if (stage == WORLD_STAGE_II) { P_absent = Properties::EitherOr::new_nameless(L"absent"); Properties::EitherOr::implement_as_attribute(P_absent, TRUE); instance *I; @@ -265,7 +269,7 @@ int PL::Backdrops::backdrops_complete_model(int stage) { @ = inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) { - instance *loc = World::Inferences::get_reference_as_object(inf); + instance *loc = Inferences::get_reference_as_object(inf); if ((K_region) && (Instances::of_kind(loc, K_region))) region_count++; else room_count++; } @@ -276,7 +280,7 @@ int PL::Backdrops::backdrops_complete_model(int stage) { packaging_state save = Emit::named_array_begin(FOUNDIN, K_value); inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) - Emit::array_iname_entry(RTInstances::iname(World::Inferences::get_reference_as_object(inf))); + Emit::array_iname_entry(RTInstances::iname(Inferences::get_reference_as_object(inf))); Emit::array_end(save); Produce::annotate_i(FOUNDIN, INLINE_ARRAY_IANN, 1); @@ -319,7 +323,7 @@ void PL::Backdrops::write_found_in_routines(void) { packaging_state save = Routines::begin(notice->found_in_routine_iname); inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), FOUND_IN_INF) { - instance *loc = World::Inferences::get_reference_as_object(inf); + instance *loc = Inferences::get_reference_as_object(inf); Produce::inv_primitive(Emit::tree(), IF_BIP); Produce::down(Emit::tree()); if ((K_region) && (Instances::of_kind(loc, K_region))) { diff --git a/inform7/if-module/Chapter 3/Devices.w b/inform7/if-module/Chapter 3/Devices.w index a02da43fc..3b6cd8e8b 100644 --- a/inform7/if-module/Chapter 3/Devices.w +++ b/inform7/if-module/Chapter 3/Devices.w @@ -30,7 +30,7 @@ int PL::Devices::devices_new_base_kind_notify(kind *new_base, text_stream *name, @ = int PL::Devices::IF_complete_model(int stage) { - if (stage == 3) { + if (stage == WORLD_STAGE_III) { P_switchable = Properties::EitherOr::new_nameless(L"switchable"); Properties::EitherOr::implement_as_attribute(P_switchable, TRUE); instance *I; diff --git a/inform7/if-module/Chapter 3/EPS Map.w b/inform7/if-module/Chapter 3/EPS Map.w index 9a2d98f5c..70ab472de 100644 --- a/inform7/if-module/Chapter 3/EPS Map.w +++ b/inform7/if-module/Chapter 3/EPS Map.w @@ -1120,7 +1120,7 @@ void PL::EPSMap::plot_text_at(OUTPUT_STREAM, wchar_t *text_to_plot, instance *I, @ = if (P_printed_name) { - parse_node *V = World::Inferences::get_prop_state_at( + parse_node *V = Inferences::get_prop_state_at( Instances::as_subject(I), P_printed_name, NULL); if ((Rvalues::is_CONSTANT_of_kind(V, K_text)) && (Wordings::nonempty(Node::get_text(V)))) { diff --git a/inform7/if-module/Chapter 3/Map Connection Relations.w b/inform7/if-module/Chapter 3/Map Connection Relations.w index 2e98dd608..9614bc3c3 100644 --- a/inform7/if-module/Chapter 3/Map Connection Relations.w +++ b/inform7/if-module/Chapter 3/Map Connection Relations.w @@ -258,10 +258,10 @@ int PL::MapDirections::REL_assert(bp_family *self, binary_predicate *bp, inference_subject *infs_from = infs0; inference_subject *infs_to = infs1; - World::Inferences::draw(IS_ROOM_INF, infs_from, prevailing_mood, NULL, NULL); + Inferences::draw(IS_ROOM_INF, infs_from, prevailing_mood, NULL, NULL); if ((prevailing_mood >= 0) && (infs_to)) - World::Inferences::draw(IS_ROOM_INF, infs_to, LIKELY_CE, NULL, NULL); - World::Inferences::draw(DIRECTION_INF, infs_from, prevailing_mood, + Inferences::draw(IS_ROOM_INF, infs_to, LIKELY_CE, NULL, NULL); + Inferences::draw(DIRECTION_INF, infs_from, prevailing_mood, infs_to, o_dir?(Instances::as_subject(o_dir)):NULL); return TRUE; diff --git a/inform7/if-module/Chapter 3/Persons.w b/inform7/if-module/Chapter 3/Persons.w index 23a69bc6c..bce947862 100644 --- a/inform7/if-module/Chapter 3/Persons.w +++ b/inform7/if-module/Chapter 3/Persons.w @@ -20,7 +20,7 @@ void PL::Persons::start(void) { @ = int PL::Persons::IF_complete_model(int stage) { - if ((stage == 3) && (K_person)) { + if ((stage == WORLD_STAGE_III) && (K_person)) { P_animate = Properties::EitherOr::new_nameless(L"animate"); Properties::EitherOr::implement_as_attribute(P_animate, TRUE); P_before = Properties::Valued::new_nameless(I"before", K_value); diff --git a/inform7/if-module/Chapter 3/Regions.w b/inform7/if-module/Chapter 3/Regions.w index 3cac373fe..3685d0fd7 100644 --- a/inform7/if-module/Chapter 3/Regions.w +++ b/inform7/if-module/Chapter 3/Regions.w @@ -273,7 +273,7 @@ int PL::Regions::assert_relations(binary_predicate *relation, @ = inference_subject *inner = Instances::as_subject(I1); inference_subject *outer = Instances::as_subject(I0); - World::Inferences::draw(PARENTAGE_INF, inner, CERTAIN_CE, outer, NULL); + Inferences::draw(PARENTAGE_INF, inner, CERTAIN_CE, outer, NULL); @ Anything in or part of a region is necessarily a room, if it isn't known to be a region already: @@ -282,7 +282,7 @@ to be a region already: inference_subject *rm = Instances::as_subject(I1); parse_node *spec = Rvalues::from_instance(I0); Propositions::Abstract::assert_kind_of_instance(I1, K_room); - World::Inferences::draw_property(rm, P_map_region, spec); + PropertyInferences::draw(rm, P_map_region, spec); @ Note that because we use regular |PARENTAGE_INF| inferences to remember that one region is inside another, it follows that the progenitor of a @@ -301,8 +301,8 @@ instance *PL::Regions::enclosing(instance *reg) { = int PL::Regions::regions_complete_model(int stage) { - if (stage == 2) @; - if (stage == 3) @; + if (stage == WORLD_STAGE_II) @; + if (stage == WORLD_STAGE_III) @; return FALSE; } @@ -316,7 +316,7 @@ int PL::Regions::regions_complete_model(int stage) { if ((Instances::of_kind(I, K_room)) || (Instances::of_kind(I, K_region))) { parse_node *where = NULL; - parse_node *val = World::Inferences::get_prop_state_at( + parse_node *val = Inferences::get_prop_state_at( Instances::as_subject(I), P_map_region, &where); if (val) { instance *reg = diff --git a/inform7/if-module/Chapter 3/Spatial Map.w b/inform7/if-module/Chapter 3/Spatial Map.w index f4b5b0e54..964875f77 100644 --- a/inform7/if-module/Chapter 3/Spatial Map.w +++ b/inform7/if-module/Chapter 3/Spatial Map.w @@ -2746,7 +2746,7 @@ void PL::SpatialMap::log_precis_of_map(void) { if (Instances::of_kind(R, K_door)) { wording W = Instances::get_name(R, FALSE); LOG("%+W is a door.\n", W); - parse_node *S = World::Inferences::get_prop_state( + parse_node *S = Inferences::get_prop_state( Instances::as_subject(R), P_other_side); instance *X = Rvalues::to_object_instance(S); if (X) { diff --git a/inform7/if-module/Chapter 3/Spatial Model.w b/inform7/if-module/Chapter 3/Spatial Model.w index f3397daa0..a92491370 100644 --- a/inform7/if-module/Chapter 3/Spatial Model.w +++ b/inform7/if-module/Chapter 3/Spatial Model.w @@ -49,12 +49,13 @@ typedef struct spatial_data { @ Here, first, are the special kinds of inference needed to store these vague indications of spatial structure: -@d IS_ROOM_INF 50 /* is O a room? */ -@d CONTAINS_THINGS_INF 51 /* does O contain things? */ -@d PARENTAGE_INF 52 /* where is O located? */ -@d PARENTAGE_HERE_INF 53 /* located vaguely as "here"? */ -@d PARENTAGE_NOWHERE_INF 54 /* located vaguely as "nowhere"? */ -@d PART_OF_INF 55 /* is O a part of another object? */ += (early code) +inference_family *IS_ROOM_INF = NULL; /* 50 is O a room? */ +inference_family *CONTAINS_THINGS_INF = NULL; /* 51 does O contain things? */ +inference_family *PARENTAGE_INF = NULL; /* 52 where is O located? */ +inference_family *PARENTAGE_HERE_INF = NULL; /* 53 located vaguely as "here"? */ +inference_family *PARENTAGE_NOWHERE_INF = NULL; /* 54 located vaguely as "nowhere"? */ +inference_family *PART_OF_INF = NULL; /* 55 is O a part of another object? */ @ The Spatial plugin also needs to know about a considerable number of special kinds and properties: @@ -95,6 +96,16 @@ inference_subject *infs_person = NULL; = void PL::Spatial::start(void) { + IS_ROOM_INF = Inferences::new_family(I"IS_ROOM_INF", CI_DIFFER_IN_INFS1); + METHOD_ADD(IS_ROOM_INF, EXPLAIN_CONTRADICTION_INF_MTID, PL::Spatial::is_room_explain_contradiction); + CONTAINS_THINGS_INF = Inferences::new_family(I"CONTAINS_THINGS_INF", CI_DIFFER_IN_INFS1); + PARENTAGE_INF = Inferences::new_family(I"PARENTAGE_INF", CI_DIFFER_IN_INFS1); + METHOD_ADD(PARENTAGE_INF, EXPLAIN_CONTRADICTION_INF_MTID, PL::Spatial::parentage_explain_contradiction); + PARENTAGE_HERE_INF = Inferences::new_family(I"PARENTAGE_HERE_INF", CI_DIFFER_IN_INFS1); + PARENTAGE_NOWHERE_INF = Inferences::new_family(I"PARENTAGE_NOWHERE_INF", CI_DIFFER_IN_INFS1); + PART_OF_INF = Inferences::new_family(I"PART_OF_INF", CI_DIFFER_IN_INFS1); + + PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Spatial::create_inference_families); PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCES, PL::Spatial::create_inference_subjects); PLUGIN_REGISTER(PLUGIN_NEW_BASE_KIND_NOTIFY, PL::Spatial::spatial_new_base_kind_notify); PLUGIN_REGISTER(PLUGIN_ACT_ON_SPECIAL_NPS, PL::Spatial::spatial_act_on_special_NPs); @@ -113,6 +124,43 @@ void PL::Spatial::start(void) { PLUGIN_REGISTER(PLUGIN_INTERVENE_IN_ASSERTION, PL::Spatial::spatial_intervene_in_assertion); } +int PL::Spatial::is_room_explain_contradiction(inference_family *f, inference *A, + inference *B, int similarity, inference_subject *subj) { + StandardProblems::two_sentences_problem(_p_(PM_WhenIsARoomNotARoom), + A->inferred_from, + "this looks like a contradiction", + "because apparently something would have to be both a room and not a " + "room at the same time."); + return TRUE; +} + +int PL::Spatial::parentage_explain_contradiction(inference_family *f, inference *A, + inference *B, int similarity, inference_subject *subj) { + if (Inferences::get_reference_as_object(A) != Inferences::get_reference_as_object(B)) { + Problems::quote_source(1, Inferences::where_inferred(A)); + Problems::quote_source(2, Inferences::where_inferred(B)); + Problems::quote_subject(3, subj); + Problems::quote_object(4, Inferences::get_reference_as_object(A)); + Problems::quote_object(5, Inferences::get_reference_as_object(B)); + StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_SpatialContradiction)); + Problems::issue_problem_segment( + "You wrote %1, but also %2: that seems to be saying that the same " + "object (%3) must be in two different places (%4 and %5). This " + "looks like a contradiction. %P" + "This sometimes happens as a result of a sentence like 'Every person " + "carries a bag', when Inform doesn't know 'bag' as the name of any " + "kind - so that it makes only a single thing called 'bag', and then " + "the sentence looks as if it says everyone is carrying the same bag."); + Problems::issue_problem_end(); + return TRUE; + } + return FALSE; +} + +int PL::Spatial::create_inference_families(void) { + return FALSE; +} + @ In talking about some of the fundamental spatial domains we potentially have a vicious circle, because (a) we need fundamental kinds like "thing" and "room" in order to @@ -179,35 +227,27 @@ multiple |PARENTAGE_INF|s can contradict each other. = int PL::Spatial::spatial_log_inference_type(int it) { - switch(it) { - case CONTAINS_THINGS_INF: LOG("CONTAINS_THINGS_INF"); return TRUE; - case IS_ROOM_INF: LOG("IS_ROOM_INF"); return TRUE; - case PARENTAGE_HERE_INF: LOG("PARENTAGE_HERE_INF"); return TRUE; - case PARENTAGE_NOWHERE_INF: LOG("PARENTAGE_NOWHERE_INF"); return TRUE; - case PARENTAGE_INF: LOG("PARENTAGE_INF"); return TRUE; - case PART_OF_INF: LOG("PART_OF_INF"); return TRUE; - } return FALSE; } int PL::Spatial::spatial_inferences_contradict(inference *A, inference *B, int similarity) { - if ((World::Inferences::get_inference_type(A) == PARENTAGE_INF) && - (World::Inferences::get_reference_as_object(A) != - World::Inferences::get_reference_as_object(B))) + if ((Inferences::get_inference_type(A) == PARENTAGE_INF) && + (Inferences::get_reference_as_object(A) != + Inferences::get_reference_as_object(B))) return TRUE; return FALSE; } int PL::Spatial::spatial_explain_contradiction(inference *A, inference *B, int similarity, inference_subject *subj) { - if ((World::Inferences::get_inference_type(A) == PARENTAGE_INF) && - (World::Inferences::get_reference_as_object(A) != - World::Inferences::get_reference_as_object(B))) { - Problems::quote_source(1, World::Inferences::where_inferred(A)); - Problems::quote_source(2, World::Inferences::where_inferred(B)); +/* if ((Inferences::get_inference_type(A) == PARENTAGE_INF) && + (Inferences::get_reference_as_object(A) != + Inferences::get_reference_as_object(B))) { + Problems::quote_source(1, Inferences::where_inferred(A)); + Problems::quote_source(2, Inferences::where_inferred(B)); Problems::quote_subject(3, subj); - Problems::quote_object(4, World::Inferences::get_reference_as_object(A)); - Problems::quote_object(5, World::Inferences::get_reference_as_object(B)); + Problems::quote_object(4, Inferences::get_reference_as_object(A)); + Problems::quote_object(5, Inferences::get_reference_as_object(B)); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_SpatialContradiction)); Problems::issue_problem_segment( "You wrote %1, but also %2: that seems to be saying that the same " @@ -220,6 +260,7 @@ int PL::Spatial::spatial_explain_contradiction(inference *A, inference *B, int s Problems::issue_problem_end(); return TRUE; } +*/ return FALSE; } @@ -266,7 +307,7 @@ int PL::Spatial::spatial_set_kind_notify(instance *I, kind *k) { kind *kw = Instances::to_kind(I); if ((!(Kinds::Behaviour::is_object_of_kind(kw, K_room))) && (Kinds::Behaviour::is_object_of_kind(k, K_room))) - World::Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, + Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, NULL, NULL); return FALSE; } @@ -375,9 +416,9 @@ int PL::Spatial::spatial_default_appearance(inference_subject *infs, parse_node instance *I = InstanceSubjects::to_object_instance(infs); if ((I) && (PL::Backdrops::object_is_scenery(I))) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); - if (((prn) && (World::Inferences::get_certainty(inf) > 0)) && + KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *prn = PropertyInferences::get_property(inf); + if (((prn) && (Inferences::get_certainty(inf) > 0)) && (prn == P_description)) { @; return TRUE; @@ -514,7 +555,7 @@ void PL::Spatial::infer_presence_here(instance *I) { inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, infs, PARENTAGE_HERE_INF) { StandardProblems::contradiction_problem(_p_(PM_DuplicateHere), - World::Inferences::where_inferred(inf), + Inferences::where_inferred(inf), current_sentence, I, "can only be said to be 'here' once", @@ -522,18 +563,18 @@ void PL::Spatial::infer_presence_here(instance *I) { "since 'here' can mean different things in different sentences."); } - World::Inferences::draw(PARENTAGE_HERE_INF, infs, CERTAIN_CE, + Inferences::draw(PARENTAGE_HERE_INF, infs, CERTAIN_CE, Anaphora::get_current_subject(), NULL); - World::Inferences::draw(IS_ROOM_INF, infs, IMPOSSIBLE_CE, NULL, NULL); + Inferences::draw(IS_ROOM_INF, infs, IMPOSSIBLE_CE, NULL, NULL); } @ Similarly: = void PL::Spatial::infer_presence_nowhere(instance *I) { - World::Inferences::draw(PARENTAGE_NOWHERE_INF, + Inferences::draw(PARENTAGE_NOWHERE_INF, Instances::as_subject(I), CERTAIN_CE, NULL, NULL); - World::Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), IMPOSSIBLE_CE, + Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), IMPOSSIBLE_CE, NULL, NULL); } @@ -639,16 +680,16 @@ probably suggested by inferences. @ = inference *inf; KNOWLEDGE_LOOP(inf, Instances::as_subject(I), CONTAINS_THINGS_INF) - if (World::Inferences::get_certainty(inf) > geography_certainty) { + if (Inferences::get_certainty(inf) > geography_certainty) { geography_choice = K_container; - geography_certainty = World::Inferences::get_certainty(inf); + geography_certainty = Inferences::get_certainty(inf); geography_inference = inf; } KNOWLEDGE_LOOP(inf, Instances::as_subject(I), IS_ROOM_INF) - if ((World::Inferences::get_certainty(inf) > UNKNOWN_CE) || - (World::Inferences::get_certainty(inf) > geography_certainty)) { + if ((Inferences::get_certainty(inf) > UNKNOWN_CE) || + (Inferences::get_certainty(inf) > geography_certainty)) { geography_choice = K_room; - geography_certainty = World::Inferences::get_certainty(inf); + geography_certainty = Inferences::get_certainty(inf); geography_inference = inf; } @@ -690,7 +731,7 @@ when it's legitimately a door. @ = StandardProblems::contradiction_problem(_p_(PM_PersonContaining), sentence_setting_kind, - World::Inferences::where_inferred(geography_inference), I, + Inferences::where_inferred(geography_inference), I, "cannot contain or support things like something inanimate", "which is what you are implying. Instead, people must carry or wear them: " "so 'The briefcase is in Daphne.' is disallowed, but 'The briefcase is " @@ -701,7 +742,7 @@ Inform spatial model: @ = StandardProblems::contradiction_problem(_p_(PM_CantContainAndSupport), - decider, World::Inferences::where_inferred(geography_inference), I, + decider, Inferences::where_inferred(geography_inference), I, "cannot both contain things and support things", "which is what you're implying here. If you need both, the easiest way is " "to make it either a supporter with a container attached or vice versa. " @@ -712,7 +753,7 @@ Inform spatial model: @ = StandardProblems::contradiction_problem(_p_(PM_BothRoomAndSupporter), decider, - World::Inferences::where_inferred(geography_inference), I, + Inferences::where_inferred(geography_inference), I, "would need to have two different and incompatible kinds to make both " "sentences true", "and this is a contradiction."); @@ -740,7 +781,7 @@ void PL::Spatial::set_progenitor(instance *of, instance *to, inference *reason) if (to == NULL) internal_error("set progenitor of nothing"); SPATIAL_DATA(of)->progenitor = to; SPATIAL_DATA(of)->progenitor_set_at = - (reason)?World::Inferences::where_inferred(reason):NULL; + (reason)?Inferences::where_inferred(reason):NULL; } @ This is used for error recovery only. @@ -812,7 +853,7 @@ object under investigation. @; if (parent_setting_inference) { instance *whereabouts = - World::Inferences::get_reference_as_object(parent_setting_inference); + Inferences::get_reference_as_object(parent_setting_inference); if (SPATIAL_DATA(I)->here_flag) @; if (whereabouts) { PL::Spatial::set_progenitor(I, whereabouts, parent_setting_inference); @@ -833,8 +874,8 @@ object under investigation. @ = if (parent_setting_inference) { StandardProblems::contradiction_problem(_p_(PM_DuplicateParentage), - World::Inferences::where_inferred(parent_setting_inference), - World::Inferences::where_inferred(inf), + Inferences::where_inferred(parent_setting_inference), + Inferences::where_inferred(inf), I, "can only be given its position once", "in a single assertion sentence."); @@ -845,7 +886,7 @@ object under investigation. if (PL::Spatial::object_is_a_room(whereabouts) == FALSE) whereabouts = NULL; if (whereabouts == NULL) { parse_node *here_sentence = - World::Inferences::where_inferred(parent_setting_inference); + Inferences::where_inferred(parent_setting_inference); @; if (whereabouts == NULL) { current_sentence = here_sentence; @@ -1150,8 +1191,8 @@ as a value for |description| from the room class. if (K_room) { inference *inf; int desc_seen = FALSE; - POSITIVE_KNOWLEDGE_LOOP(inf, KindSubjects::from_kind(K_room), PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_description) + POSITIVE_KNOWLEDGE_LOOP(inf, KindSubjects::from_kind(K_room), property_inf) + if (PropertyInferences::get_property(inf) == P_description) desc_seen = TRUE; if (desc_seen == FALSE) { TEMPORARY_TEXT(val) @@ -1299,8 +1340,8 @@ void PL::Spatial::index_spatial_relationship(OUTPUT_STREAM, instance *I) { if (Instances::of_kind(P, K_person)) rel = "carried"; if (SPATIAL_DATA(I)->part_flag) rel = "part"; inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_worn) + POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), property_inf) + if (PropertyInferences::get_property(inf) == P_worn) rel = "worn"; } if (rel) WRITE("%s ", rel); @@ -1362,8 +1403,8 @@ int PL::Spatial::spatial_add_to_World_index(OUTPUT_STREAM, instance *O) { if (Instances::of_kind(P, K_person)) rel = "carried by"; if (SPATIAL_DATA(O)->part_flag) rel = "part of"; inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(O), PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_worn) + POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(O), property_inf) + if (PropertyInferences::get_property(inf) == P_worn) rel = "worn by"; WRITE("%s ", rel); IXInstances::index_name(OUT, P); diff --git a/inform7/if-module/Chapter 3/Spatial Relations.w b/inform7/if-module/Chapter 3/Spatial Relations.w index 5dda4b535..81ddaca39 100644 --- a/inform7/if-module/Chapter 3/Spatial Relations.w +++ b/inform7/if-module/Chapter 3/Spatial Relations.w @@ -230,13 +230,13 @@ way which isn't symmetrical between the two, and this way round is cleanest. @ = inference_subject *item = Instances::as_subject(I1); inference_subject *loc = Instances::as_subject(I0); - World::Inferences::draw(PART_OF_INF, item, + Inferences::draw(PART_OF_INF, item, (bp == R_incorporation)?CERTAIN_CE:IMPOSSIBLE_CE, loc, NULL); if (bp == R_containment) - World::Inferences::draw(CONTAINS_THINGS_INF, loc, CERTAIN_CE, item, NULL); - World::Inferences::draw(PARENTAGE_INF, item, CERTAIN_CE, loc, NULL); - World::Inferences::draw(IS_ROOM_INF, item, IMPOSSIBLE_CE, NULL, NULL); + Inferences::draw(CONTAINS_THINGS_INF, loc, CERTAIN_CE, item, NULL); + Inferences::draw(PARENTAGE_INF, item, CERTAIN_CE, loc, NULL); + Inferences::draw(IS_ROOM_INF, item, IMPOSSIBLE_CE, NULL, NULL); @ If something is being worn, it needs to have the I7 either/or property "wearable" and also the I6-only attribute |worn|. (Arguably Clothing ought @@ -246,12 +246,12 @@ special to make it work, so this doesn't seem worth the trouble.) @ = inference_subject *item = Instances::as_subject(I1); if (P_wearable) - World::Inferences::draw_property(item, P_wearable, NULL); + PropertyInferences::draw(item, P_wearable, NULL); if (P_worn == NULL) { P_worn = Properties::EitherOr::new_nameless(L"worn"); Properties::EitherOr::implement_as_attribute(P_worn, TRUE); } - World::Inferences::draw_property(item, P_worn, NULL); + PropertyInferences::draw(item, P_worn, NULL); @h Compilation. We need do nothing special: these relations can be compiled from their schemas. diff --git a/inform7/if-module/Chapter 3/Temporal Map.w b/inform7/if-module/Chapter 3/Temporal Map.w index 0e8813fa3..4d3fabc04 100644 --- a/inform7/if-module/Chapter 3/Temporal Map.w +++ b/inform7/if-module/Chapter 3/Temporal Map.w @@ -124,7 +124,7 @@ fact, end. Index::anchor_numbered(OUT, sc->allocation_id); WRITE("The %+W scene", PL::Scenes::get_name(sc)); Index::link(OUT, Wordings::first_wn(Node::get_text(sc->scene_declared_at))); - if (World::Inferences::get_EO_state( + if (Inferences::get_EO_state( Instances::as_subject(sc->as_instance), P_recurring) > 0) WRITE("  recurring"); HTML_CLOSE("p"); @@ -271,7 +271,7 @@ void PL::Scenes::Index::index_from_scene(OUTPUT_STREAM, scene *sc, int depth, @ = inference_subject *subj = Instances::as_subject(sc->as_instance); - if (World::Inferences::get_EO_state(subj, P_recurring) > UNKNOWN_CE) + if (Inferences::get_EO_state(subj, P_recurring) > UNKNOWN_CE) PL::Scenes::Index::scene_icon_append(OUT, "Recurring"); @ And this is where the routine recurses, so that consequent scenes are diff --git a/inform7/if-module/Chapter 3/The Map.w b/inform7/if-module/Chapter 3/The Map.w index 6be4ddbfa..1220e2519 100644 --- a/inform7/if-module/Chapter 3/The Map.w +++ b/inform7/if-module/Chapter 3/The Map.w @@ -80,7 +80,8 @@ property *P_found_in = NULL; /* I6 only: needed for multiply-present objects */ in connection with the "mapped D of" relations, it's altogether easier and makes for more legible code if we use a special inference type of our own: -@d DIRECTION_INF 100 /* where do map connections from O lead? */ += (early code) +inference_family *DIRECTION_INF = NULL; /* 100; where do map connections from O lead? */ @ One useful constant: @@ -110,6 +111,9 @@ typedef struct door_to_notice { = void PL::Map::start(void) { + DIRECTION_INF = Inferences::new_family(I"DIRECTION_INF", CI_DIFFER_IN_INFS1); + + PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Map::create_inference_families); PLUGIN_REGISTER(PLUGIN_NEW_BASE_KIND_NOTIFY, PL::Map::map_new_base_kind_notify); PLUGIN_REGISTER(PLUGIN_NEW_SUBJECT_NOTIFY, PL::Map::map_new_subject_notify); PLUGIN_REGISTER(PLUGIN_SET_KIND_NOTIFY, PL::Map::map_set_kind_notify); @@ -120,6 +124,7 @@ void PL::Map::start(void) { PLUGIN_REGISTER(PLUGIN_ESTIMATE_PROPERTY_USAGE, PL::Map::map_estimate_property_usage); PLUGIN_REGISTER(PLUGIN_LOG_INFERENCE_TYPE, PL::Map::map_log_inference_type); PLUGIN_REGISTER(PLUGIN_INFERENCES_CONTRADICT, PL::Map::map_inferences_contradict); + PLUGIN_REGISTER(PLUGIN_CREATE_INFERENCE_FAMILIES, PL::Map::create_inference_families); PLUGIN_REGISTER(PLUGIN_COMPLETE_MODEL, PL::Map::map_complete_model); PLUGIN_REGISTER(PLUGIN_NEW_PROPERTY_NOTIFY, PL::Map::map_new_property_notify); PLUGIN_REGISTER(PLUGIN_PROPERTY_VALUE_NOTIFY, PL::Map::map_property_value_notify); @@ -128,6 +133,10 @@ void PL::Map::start(void) { PLUGIN_REGISTER(PLUGIN_ANNOTATE_IN_WORLD_INDEX, PL::Map::map_annotate_in_World_index); } +int PL::Map::create_inference_families(void) { + return FALSE; +} + @ = map_data *PL::Map::new_data(inference_subject *subj) { map_data *md = CREATE(map_data); @@ -150,9 +159,6 @@ map_data *PL::Map::new_data(inference_subject *subj) { = int PL::Map::map_log_inference_type(int it) { - switch(it) { - case DIRECTION_INF: LOG("DIRECTION_INF"); return TRUE; - } return FALSE; } @@ -163,11 +169,9 @@ direction -- this of course is a contradiction. = int PL::Map::map_inferences_contradict(inference *A, inference *B, int similarity) { - switch (World::Inferences::get_inference_type(A)) { - case DIRECTION_INF: - if (similarity == CI_DIFFER_IN_INFS1) return TRUE; - break; - } + if (Inferences::get_inference_type(A) == DIRECTION_INF) + if (similarity == CI_DIFFER_IN_INFS1) + return TRUE; return FALSE; } @@ -352,7 +356,7 @@ void PL::Map::build_exits_array(void) { inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) { inference_subject *infs1, *infs2; - World::Inferences::get_references(inf, &infs1, &infs2); + Inferences::get_references(inf, &infs1, &infs2); instance *to = NULL, *dir = NULL; if (infs1) to = InstanceSubjects::to_object_instance(infs1); if (infs2) dir = InstanceSubjects::to_object_instance(infs2); @@ -360,7 +364,7 @@ void PL::Map::build_exits_array(void) { int dn = MAP_DATA(dir)->direction_index; if ((dn >= 0) && (dn < MAX_DIRECTIONS)) { MAP_EXIT(I, dn) = to; - MAP_DATA(I)->exits_set_at[dn] = World::Inferences::where_inferred(inf); + MAP_DATA(I)->exits_set_at[dn] = Inferences::where_inferred(inf); } } } @@ -478,7 +482,7 @@ int PL::Map::map_property_value_notify(property *prn, parse_node *val) { if (prn == P_other_side) { instance *I = Rvalues::to_object_instance(val); if (I) { - World::Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, + Inferences::draw(IS_ROOM_INF, Instances::as_subject(I), CERTAIN_CE, NULL, NULL); } } @@ -496,7 +500,7 @@ void PL::Map::set_found_in(instance *I, inter_name *S) { if (P_found_in == NULL) P_found_in = Properties::Valued::new_nameless(I"found_in", K_value); - if (World::Inferences::get_prop_state( + if (Inferences::get_prop_state( Instances::as_subject(I), P_found_in)) internal_error("rival found_in interpretations"); Properties::Valued::assert(P_found_in, Instances::as_subject(I), @@ -510,7 +514,7 @@ and there seems little point in writing this any better. = instance *PL::Map::get_value_of_opposite_property(instance *I) { - parse_node *val = World::Inferences::get_prop_state( + parse_node *val = Inferences::get_prop_state( Instances::as_subject(I), P_opposite); if (val) return Rvalues::to_object_instance(val); return NULL; @@ -732,14 +736,14 @@ checks that various mapping impossibilities do not occur. inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) { inference_subject *infs1; - World::Inferences::get_references(inf, &infs1, NULL); + Inferences::get_references(inf, &infs1, NULL); instance *to = InstanceSubjects::to_object_instance(infs1); if ((PL::Spatial::object_is_a_room(I)) && (to) && (PL::Map::object_is_a_door(to) == FALSE) && (PL::Spatial::object_is_a_room(to) == FALSE)) StandardProblems::contradiction_problem(_p_(PM_BadMapCell), Instances::get_creating_sentence(to), - World::Inferences::where_inferred(inf), to, + Inferences::where_inferred(inf), to, "appears to be something which can be reached via a map " "connection, but it seems to be neither a room nor a door", "and these are the only possibilities allowed by Inform."); @@ -764,31 +768,30 @@ checks that various mapping impossibilities do not occur. inference *front_side_inf = NULL, *back_side_inf = NULL; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) { inference_subject *infs1, *infs2; - World::Inferences::get_references(inf, &infs1, &infs2); + Inferences::get_references(inf, &infs1, &infs2); instance *to = InstanceSubjects::to_object_instance(infs1); instance *dir = InstanceSubjects::to_object_instance(infs2); if (to) { if (connections_in == 0) { MAP_DATA(I)->map_connection_a = to; MAP_DATA(I)->map_direction_a = dir; - where[0] = World::Inferences::where_inferred(inf); + where[0] = Inferences::where_inferred(inf); front_side_inf = inf; } if (connections_in == 1) { MAP_DATA(I)->map_connection_b = to; MAP_DATA(I)->map_direction_b = dir; - where[1] = World::Inferences::where_inferred(inf); + where[1] = Inferences::where_inferred(inf); back_side_inf = inf; } if (connections_in == 2) { - where[2] = World::Inferences::where_inferred(inf); + where[2] = Inferences::where_inferred(inf); } connections_in++; } } if ((front_side_inf) && (back_side_inf)) { - if (World::Inferences::get_timestamp(front_side_inf) > - World::Inferences::get_timestamp(back_side_inf)) { + if (front_side_inf->allocation_id > back_side_inf->allocation_id) { instance *X = MAP_DATA(I)->map_connection_a; MAP_DATA(I)->map_connection_a = MAP_DATA(I)->map_connection_b; MAP_DATA(I)->map_connection_b = X; @@ -837,7 +840,7 @@ from which there's no way back.) inference *inf; POSITIVE_KNOWLEDGE_LOOP(inf, Instances::as_subject(I), DIRECTION_INF) { inference_subject *infs1; - World::Inferences::get_references(inf, &infs1, NULL); + Inferences::get_references(inf, &infs1, NULL); instance *to = InstanceSubjects::to_object_instance(infs1); if (PL::Map::object_is_a_door(to)) { instance *exit1 = MAP_DATA(to)->map_connection_a; @@ -876,7 +879,7 @@ from which there's no way back.) if ((PL::Map::object_is_a_door(I)) && (MAP_DATA(I)->map_connection_a) && (MAP_DATA(I)->map_connection_b) && - (World::Inferences::get_prop_state( + (Inferences::get_prop_state( Instances::as_subject(I), P_other_side))) StandardProblems::object_problem(_p_(PM_BothWaysDoor), I, "seems to be a door whose connections have been given in both " @@ -1132,7 +1135,7 @@ int PL::Map::map_annotate_in_World_index(OUTPUT_STREAM, instance *O) { instance *X = A; if (A == Data::Objects::room_being_indexed()) X = B; if (X == NULL) { - parse_node *S = World::Inferences::get_prop_state( + parse_node *S = Inferences::get_prop_state( Instances::as_subject(O), P_other_side); X = Rvalues::to_object_instance(S); } diff --git a/inform7/if-module/Chapter 3/The Naming Thicket.w b/inform7/if-module/Chapter 3/The Naming Thicket.w index c3f96828b..347acafb8 100644 --- a/inform7/if-module/Chapter 3/The Naming Thicket.w +++ b/inform7/if-module/Chapter 3/The Naming Thicket.w @@ -126,9 +126,9 @@ This is needed when assemblies name one new creation after another; for instance void PL::Naming::transfer_details(inference_subject *from, inference_subject *to) { instance *wto = InstanceSubjects::to_object_instance(to); if (wto) { - if (World::Inferences::get_EO_state(from, P_proper_named) > 0) + if (Inferences::get_EO_state(from, P_proper_named) > 0) PL::Naming::now_has_proper_name(to); - parse_node *art = World::Inferences::get_prop_state(from, P_article); + parse_node *art = Inferences::get_prop_state(from, P_article); if (art) Properties::Valued::assert(P_article, to, art, LIKELY_CE); } } @@ -145,7 +145,7 @@ we do here is provide its state on request. = int PL::Naming::object_is_privately_named(instance *I) { - int certainty = World::Inferences::get_EO_state(Instances::as_subject(I), P_privately_named); + int certainty = Inferences::get_EO_state(Instances::as_subject(I), P_privately_named); if (certainty > 0) return TRUE; if (certainty < 0) return FALSE; return NOT_APPLICABLE; @@ -157,7 +157,7 @@ to fill in the naming details for objects, so here goes. = int PL::Naming::naming_complete_model(int stage) { - if (stage == 3) @; + if (stage == WORLD_STAGE_III) @; return FALSE; } @@ -267,7 +267,7 @@ actually means it's rarely needed.) if (this_is_named_for_something_with_a_printed_name) { @ } else { - if ((World::Inferences::get_EO_state(subj, P_proper_named) > 0) + if ((Inferences::get_EO_state(subj, P_proper_named) > 0) && (begins_with_lower_case)) @ else set_csn = FALSE; @@ -331,7 +331,7 @@ together in lists. @ = if ((Kinds::Behaviour::is_object_of_kind(K, K_room) == FALSE) && (Kinds::eq(K, K_thing) == FALSE) && - (World::Inferences::get_prop_state_without_inheritance( + (Inferences::get_prop_state_without_inheritance( subj, P_printed_plural_name, NULL) == NULL)) { if (Wordings::nonempty(PW)) { text_stream *PROP = Str::new(); @@ -344,7 +344,7 @@ together in lists. @ The following isn't done in English. @ = - parse_node *spec = World::Inferences::get_prop_state(subj, P_grammatical_gender); + parse_node *spec = Inferences::get_prop_state(subj, P_grammatical_gender); if (spec) { int g = Annotations::read_int(spec, constant_enumeration_ANNOT); switch (g) { @@ -374,9 +374,9 @@ int PL::Naming::look_for_printed_name(inference_subject *subj) { inference_subject *check; for (check = subj; check; check = InferenceSubjects::narrowest_broader_subject(check)) { inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, check, PROPERTY_INF) - if (World::Inferences::added_in_construction(inf) == FALSE) - if (World::Inferences::get_property(inf) == P_printed_name) + POSITIVE_KNOWLEDGE_LOOP(inf, check, property_inf) + if (Inferences::during_stage(inf) == 0) + if (PropertyInferences::get_property(inf) == P_printed_name) return TRUE; } return FALSE; @@ -521,7 +521,7 @@ int PL::Naming::adaptive_combination(inform_language *L) { if (L->adaptive_person >= 0) return L->adaptive_person; if ((L->adaptive_person == -1) && (P_adaptive_text_viewpoint)) { instance *I = L->nl_instance; - parse_node *val = World::Inferences::get_prop_state( + parse_node *val = Inferences::get_prop_state( Instances::as_subject(I), P_adaptive_text_viewpoint); if (Node::is(val, CONSTANT_NT)) { instance *V = Node::get_constant_instance(val); diff --git a/inform7/if-module/Chapter 3/The Player.w b/inform7/if-module/Chapter 3/The Player.w index 89268d3d1..9a7030be7 100644 --- a/inform7/if-module/Chapter 3/The Player.w +++ b/inform7/if-module/Chapter 3/The Player.w @@ -260,12 +260,12 @@ we assume he is freestanding in the earliest defined room. = int PL::Player::player_complete_model(int stage) { - if ((stage == 3) && (I_yourself)) { + if ((stage == WORLD_STAGE_III) && (I_yourself)) { P_saved_short_name = Properties::Valued::new_nameless(I"saved_short_name", K_text); Properties::Valued::assert(P_saved_short_name, Instances::as_subject(I_yourself), Rvalues::from_unescaped_wording(Feeds::feed_text(I"yourself")), CERTAIN_CE); } - if (stage == 4) { + if (stage == WORLD_STAGE_IV) { @; @; @; diff --git a/inform7/if-module/Chapter 5/Grammar Properties.w b/inform7/if-module/Chapter 5/Grammar Properties.w index eea026eda..5a4916147 100644 --- a/inform7/if-module/Chapter 5/Grammar Properties.w +++ b/inform7/if-module/Chapter 5/Grammar Properties.w @@ -135,7 +135,7 @@ for parsing: = int PL::Parsing::Visibility::parsing_complete_model(int stage) { - if (stage == 5) { + if (stage == WORLD_STAGE_V) { instance *I; P_name = Properties::Valued::new_nameless(I"name", K_text); Hierarchy::make_available(Emit::tree(), PL::Parsing::Visibility::name_name()); diff --git a/inform7/index-module/Chapter 2/Index Physical World.w b/inform7/index-module/Chapter 2/Index Physical World.w index 413529bde..3bfa7c4ad 100644 --- a/inform7/index-module/Chapter 2/Index Physical World.w +++ b/inform7/index-module/Chapter 2/Index Physical World.w @@ -288,8 +288,8 @@ void Data::Objects::index(OUTPUT_STREAM, instance *I, kind *K, int depth, int de @ = HTML::open_indented_p(OUT, depth, "tight"); - if (I) World::Inferences::index(OUT, Instances::as_subject(I), TRUE); - else World::Inferences::index(OUT, KindSubjects::from_kind(K), TRUE); + if (I) Inferences::index(OUT, Instances::as_subject(I), TRUE); + else Inferences::index(OUT, KindSubjects::from_kind(K), TRUE); if (K) { HTML_CLOSE("p"); Data::Objects::index_instances(OUT, K, depth); @@ -319,7 +319,7 @@ void Data::Objects::index(OUTPUT_STREAM, instance *I, kind *K, int depth, int de HTML_CLOSE("p"); @ = - World::Inferences::index_specific(OUT, Instances::as_subject(I)); + Inferences::index_specific(OUT, Instances::as_subject(I)); @ = void Data::Objects::index_instances(OUTPUT_STREAM, kind *K, int depth) { diff --git a/inform7/index-module/Chapter 2/Kinds Index.w b/inform7/index-module/Chapter 2/Kinds Index.w index 3c96fc485..c48df80c9 100644 --- a/inform7/index-module/Chapter 2/Kinds Index.w +++ b/inform7/index-module/Chapter 2/Kinds Index.w @@ -248,7 +248,7 @@ is made, so that the following sentence can't have an empty list in it. WRITE("%S", explanation); HTML_TAG("br"); } - World::Inferences::index(OUT, KindSubjects::from_kind(K), FALSE); + Inferences::index(OUT, KindSubjects::from_kind(K), FALSE); @ = HTML_OPEN("p"); diff --git a/inform7/knowledge-module/Chapter 1/Knowledge Module.w b/inform7/knowledge-module/Chapter 1/Knowledge Module.w index 3b8e549b7..453921f93 100644 --- a/inform7/knowledge-module/Chapter 1/Knowledge Module.w +++ b/inform7/knowledge-module/Chapter 1/Knowledge Module.w @@ -12,11 +12,11 @@ which use this module: = COMPILE_WRITER(booking *, Rules::Bookings::log) -COMPILE_WRITER(inference *, World::Inferences::log) +COMPILE_WRITER(inference *, Inferences::log) COMPILE_WRITER(inference_subject *, InferenceSubjects::log) COMPILE_WRITER(property *, Properties::log) COMPILE_WRITER(rulebook *, Rulebooks::log) -COMPILE_WRITER_I(int, World::Inferences::log_kind) +COMPILE_WRITER(inference_family *, Inferences::log_kind) @ @@ -34,6 +34,9 @@ COMPILE_WRITER_I(int, World::Inferences::log_kind) = void KnowledgeModule::start(void) { + Inferences::start(); + PropertyInferences::start(); + RelationInferences::start(); InstanceAdjectives::start(); Properties::EitherOr::start(); Properties::Measurement::start(); @@ -42,10 +45,10 @@ void KnowledgeModule::start(void) { Properties::ComparativeRelations::start(); Properties::ProvisionRelation::start(); REGISTER_WRITER('b', Rules::Bookings::log); - REGISTER_WRITER('I', World::Inferences::log); + REGISTER_WRITER('I', Inferences::log); REGISTER_WRITER('j', InferenceSubjects::log); REGISTER_WRITER('K', Rulebooks::log); - REGISTER_WRITER_I('n', World::Inferences::log_kind) + REGISTER_WRITER('n', Inferences::log_kind) REGISTER_WRITER('Y', Properties::log); Log::declare_aspect(ACTIVITY_CREATIONS_DA, L"activity creations", FALSE, FALSE); Log::declare_aspect(INFERENCES_DA, L"inferences", FALSE, TRUE); diff --git a/inform7/knowledge-module/Chapter 2/Instances as Adjectives.w b/inform7/knowledge-module/Chapter 2/Instances as Adjectives.w index c22881f77..51162db58 100644 --- a/inform7/knowledge-module/Chapter 2/Instances as Adjectives.w +++ b/inform7/knowledge-module/Chapter 2/Instances as Adjectives.w @@ -91,6 +91,6 @@ int InstanceAdjectives::assert(adjective_meaning_family *f, adjective_meaning *a instance *I = RETRIEVE_POINTER_instance(am->family_specific_data); property *P = Properties::Conditions::get_coinciding_property(Instances::to_kind(I)); if (P == NULL) internal_error("enumerative adjective on non-property"); - World::Inferences::draw_property(infs_to_assert_on, P, Rvalues::from_instance(I)); + PropertyInferences::draw(infs_to_assert_on, P, Rvalues::from_instance(I)); return TRUE; } diff --git a/inform7/knowledge-module/Chapter 2/Instances.w b/inform7/knowledge-module/Chapter 2/Instances.w index 51c94489b..17fd11198 100644 --- a/inform7/knowledge-module/Chapter 2/Instances.w +++ b/inform7/knowledge-module/Chapter 2/Instances.w @@ -106,7 +106,7 @@ the same object may be thing number 17 but vehicle number 3 -- and secondly, because we won't know the exact kind of objects until much later on; for now the only thing we are sure of is that they are indeed objects. Enumeration for objects within kinds is certainly useful, but it's harder to do and will -be done later on: see //Instance Counting//. +be done later on: see //runtime: Instance Counting//. @ = if (!(Kinds::Behaviour::is_object(K))) { diff --git a/inform7/knowledge-module/Chapter 2/Nonlocal Variables.w b/inform7/knowledge-module/Chapter 2/Nonlocal Variables.w index d1b429bef..18ac02848 100644 --- a/inform7/knowledge-module/Chapter 2/Nonlocal Variables.w +++ b/inform7/knowledge-module/Chapter 2/Nonlocal Variables.w @@ -226,10 +226,10 @@ data variable (such as "story title") to be treated as text. wording NonlocalVariables::initial_value_as_plain_text(nonlocal_variable *nlv) { inference *inf; inference_subject *infs = NonlocalVariables::to_subject(nlv); - POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_variable_initial_value) + POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) + if (PropertyInferences::get_property(inf) == P_variable_initial_value) return Node::get_text( - World::Inferences::set_property_value_kind(inf, K_text)); + PropertyInferences::set_value_kind(inf, K_text)); return EMPTY_WORDING; } diff --git a/inform7/knowledge-module/Chapter 3/Either-Or Properties.w b/inform7/knowledge-module/Chapter 3/Either-Or Properties.w index 3d8ae5f6e..ceea4fe75 100644 --- a/inform7/knowledge-module/Chapter 3/Either-Or Properties.w +++ b/inform7/knowledge-module/Chapter 3/Either-Or Properties.w @@ -369,8 +369,8 @@ property. int Properties::EitherOr::assert_adj(adjective_meaning_family *f, adjective_meaning *am, inference_subject *infs_to_assert_on, int parity) { property *prn = RETRIEVE_POINTER_property(am->family_specific_data); - if (parity == FALSE) World::Inferences::draw_negated_property(infs_to_assert_on, prn, NULL); - else World::Inferences::draw_property(infs_to_assert_on, prn, NULL); + if (parity == FALSE) PropertyInferences::draw_negated(infs_to_assert_on, prn, NULL); + else PropertyInferences::draw(infs_to_assert_on, prn, NULL); return TRUE; } diff --git a/inform7/knowledge-module/Chapter 3/Emit Property Values.w b/inform7/knowledge-module/Chapter 3/Emit Property Values.w index de7aaff23..796d43e5b 100644 --- a/inform7/knowledge-module/Chapter 3/Emit Property Values.w +++ b/inform7/knowledge-module/Chapter 3/Emit Property Values.w @@ -26,17 +26,6 @@ void Properties::Emit::emit_subject(inference_subject *subj) { Produce::annotate_i(iname, DECLARATION_ORDER_IANN, cs_sequence_counter++); @; - if (K) { - World::Compile::set_rough_memory_usage(K, words_used); - int nw = 0; - for (inference_subject *infs = subj; - infs; infs = InferenceSubjects::narrowest_broader_subject(infs)) { - kind *K2 = KindSubjects::to_kind(infs); - if (K2) nw += World::Compile::get_rough_memory_usage(K2); - } - nw += 16; - LOGIF(OBJECT_COMPILATION, "Rough size estimate: %d words\n", nw); - } LOGIF(OBJECT_COMPILATION, "Compilation of $j complete\n", subj); } @@ -82,9 +71,9 @@ the class hierarchy at I6 level exactly match the kind hierarchy at I7 level. @ = inference *inf; - KNOWLEDGE_LOOP(inf, subj, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); - current_sentence = World::Inferences::where_inferred(inf); + KNOWLEDGE_LOOP(inf, subj, property_inf) { + property *prn = PropertyInferences::get_property(inf); + current_sentence = Inferences::where_inferred(inf); LOGIF(OBJECT_COMPILATION, "Compiling property $Y\n", prn); words_used += Properties::Emit::emit_propertyvalue(subj, prn); } diff --git a/inform7/knowledge-module/Chapter 3/Indefinite Appearance.w b/inform7/knowledge-module/Chapter 3/Indefinite Appearance.w index 07ff6aac2..abd2cf4c4 100644 --- a/inform7/knowledge-module/Chapter 3/Indefinite Appearance.w +++ b/inform7/knowledge-module/Chapter 3/Indefinite Appearance.w @@ -20,8 +20,8 @@ So as an interim measure the text is inferred into a pseudo-property called = void Properties::Appearance::infer(inference_subject *infs, parse_node *spec) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_indefinite_appearance_text) + KNOWLEDGE_LOOP(inf, infs, property_inf) + if (PropertyInferences::get_property(inf) == P_indefinite_appearance_text) @; prevailing_mood = CERTAIN_CE; @@ -36,7 +36,7 @@ ambiguously. @ = StandardProblems::infs_contradiction_problem(_p_(PM_TwoAppearances), - World::Inferences::where_inferred(inf), current_sentence, infs, + Inferences::where_inferred(inf), current_sentence, infs, "seems to have two different descriptions", "perhaps because you intended the second description to apply to something " "mentioned in between, but declared it in such a way that it was never the " @@ -60,10 +60,10 @@ available; = void Properties::Appearance::reallocate(inference_subject *infs) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - if (World::Inferences::get_property(inf) == P_indefinite_appearance_text) { - parse_node *txt = World::Inferences::get_property_value(inf); - current_sentence = World::Inferences::where_inferred(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) { + if (PropertyInferences::get_property(inf) == P_indefinite_appearance_text) { + parse_node *txt = PropertyInferences::get_value(inf); + current_sentence = Inferences::where_inferred(inf); if (Plugins::Call::default_appearance(infs, txt) == FALSE) { if ((P_description) && (World::Permissions::find(infs, P_description, TRUE))) { diff --git a/inform7/knowledge-module/Chapter 3/Measurement Adjectives.w b/inform7/knowledge-module/Chapter 3/Measurement Adjectives.w index 9760f230f..8f8093288 100644 --- a/inform7/knowledge-module/Chapter 3/Measurement Adjectives.w +++ b/inform7/knowledge-module/Chapter 3/Measurement Adjectives.w @@ -400,7 +400,7 @@ int Properties::Measurement::assert(adjective_meaning_family *f, parse_node *val = NULL; if ((mdef->region_threshold_text)) val = <>; else internal_error("literal unreadable"); - World::Inferences::draw_property(infs_to_assert_on, mdef->prop, val); + PropertyInferences::draw(infs_to_assert_on, mdef->prop, val); return TRUE; } return FALSE; diff --git a/inform7/knowledge-module/Chapter 3/Properties.w b/inform7/knowledge-module/Chapter 3/Properties.w index b72140791..63fc4913d 100644 --- a/inform7/knowledge-module/Chapter 3/Properties.w +++ b/inform7/knowledge-module/Chapter 3/Properties.w @@ -638,11 +638,11 @@ we find it, we compile it and return |TRUE|; if not we do nothing and return = int Properties::compile_property_value_inner(value_holster *VH, inference_subject *infs, property *prn) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - if (World::Inferences::get_inference_type(inf) == PROPERTY_INF) { - current_sentence = World::Inferences::where_inferred(inf); - int sense = (World::Inferences::get_certainty(inf) > 0)?TRUE:FALSE; - property *inferred_property = World::Inferences::get_property(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) { + if (Inferences::get_inference_type(inf) == property_inf) { + current_sentence = Inferences::where_inferred(inf); + int sense = (Inferences::get_certainty(inf) > 0)?TRUE:FALSE; + property *inferred_property = PropertyInferences::get_property(inf); if (Properties::is_either_or(prn)) { if (inferred_property == prn) { Properties::EitherOr::compile_value(VH, inferred_property, sense); @@ -655,7 +655,7 @@ int Properties::compile_property_value_inner(value_holster *VH, inference_subjec } else { if (inferred_property == prn) { if (sense) { - parse_node *val = World::Inferences::get_property_value(inf); + parse_node *val = PropertyInferences::get_value(inf); if (val == NULL) internal_error("malformed property inference"); Properties::Valued::compile_value(VH, inferred_property, val); return TRUE; diff --git a/inform7/knowledge-module/Chapter 3/Setting Property Relation.w b/inform7/knowledge-module/Chapter 3/Setting Property Relation.w index f46cb8ae0..4faf7279a 100644 --- a/inform7/knowledge-module/Chapter 3/Setting Property Relation.w +++ b/inform7/knowledge-module/Chapter 3/Setting Property Relation.w @@ -247,7 +247,7 @@ int Properties::SettingRelations::REL_assert(bp_family *self, binary_predicate * inference_subject *infs1, parse_node *spec1) { property_setting_bp_data *PSD = RETRIEVE_POINTER_property_setting_bp_data(bp->family_specific); - World::Inferences::draw_property(infs0, PSD->set_property, spec1); + PropertyInferences::draw(infs0, PSD->set_property, spec1); return TRUE; } diff --git a/inform7/knowledge-module/Chapter 4/Inference Subjects.w b/inform7/knowledge-module/Chapter 4/Inference Subjects.w index e8c6bacca..34db66ee4 100644 --- a/inform7/knowledge-module/Chapter 4/Inference Subjects.w +++ b/inform7/knowledge-module/Chapter 4/Inference Subjects.w @@ -116,8 +116,8 @@ typedef struct inference_subject { struct general_pointer represents; /* family-specific data */ void *additional_data_for_plugins[MAX_PLUGINS]; /* and managed by those plugins */ - struct inference *inf_list; /* contingently true: inferences drawn about this subject */ - struct implication *imp_list; /* necessarily true: implications applying to this */ + struct linked_list *inf_list; /* contingently true: each |inference| drawn about this */ + struct linked_list *imp_list; /* necessarily true: each |implication| applying to this */ struct linked_list *permissions_list; /* of |property_permission| */ struct assemblies_data assemblies; /* what generalisations have been made about this? */ @@ -154,8 +154,8 @@ void InferenceSubjects::infs_initialise(inference_subject *infs, infs->infs_created_at = current_sentence; infs->represents = gp; infs->infs_family = family; - infs->inf_list = NULL; - infs->imp_list = NULL; + infs->inf_list = NEW_LINKED_LIST(inference); + infs->imp_list = NEW_LINKED_LIST(implication); infs->broader_than = from; infs->permissions_list = NEW_LINKED_LIST(property_permission); infs->infs_name_in_log = log_name; @@ -241,23 +241,14 @@ assemblies_data *InferenceSubjects::get_assemblies_data(inference_subject *infs) return &(infs->assemblies); } -inference *InferenceSubjects::get_inferences(inference_subject *infs) { +linked_list *InferenceSubjects::get_inferences(inference_subject *infs) { return (infs)?(infs->inf_list):NULL; } -void InferenceSubjects::set_inferences(inference_subject *infs, inference *inf) { - if (infs == NULL) internal_error("null INFS"); - infs->inf_list = inf; -} - -implication *InferenceSubjects::get_implications(inference_subject *infs) { +linked_list *InferenceSubjects::get_implications(inference_subject *infs) { return infs->imp_list; } -void InferenceSubjects::set_implications(inference_subject *infs, implication *imp) { - infs->imp_list = imp; -} - linked_list *InferenceSubjects::get_permissions(inference_subject *infs) { return infs->permissions_list; } @@ -328,9 +319,10 @@ void InferenceSubjects::log(inference_subject *infs) { } void InferenceSubjects::log_knowledge_about(inference_subject *infs) { - inference *inf; LOG("Inferences drawn about $j:\n", infs); LOG_INDENT; - for (inf = InferenceSubjects::get_inferences(infs); inf; inf = inf->next) LOG("$I\n", inf); + inference *inf; + LOOP_OVER_LINKED_LIST(inf, inference, InferenceSubjects::get_inferences(infs)) + LOG("$I\n", inf); LOG_OUTDENT; } @@ -507,7 +499,7 @@ void InferenceSubjects::emit_all(void) { inference_subject *infs; LOOP_OVER(infs, inference_subject) - World::Inferences::verify_prop_states(infs); + Inferences::verify_prop_states(infs); inference_subject_family *family; LOOP_OVER(family, inference_subject_family) { diff --git a/inform7/knowledge-module/Chapter 4/Relation Subjects.w b/inform7/knowledge-module/Chapter 4/Relation Subjects.w index 924c19535..b7439f70d 100644 --- a/inform7/knowledge-module/Chapter 4/Relation Subjects.w +++ b/inform7/knowledge-module/Chapter 4/Relation Subjects.w @@ -56,10 +56,9 @@ void RelationSubjects::complete_model(inference_subject_family *family, (bp->right_way_round)) { RTRelations::equivalence_relation_make_singleton_partitions(bp, domain_size); inference *i; - POSITIVE_KNOWLEDGE_LOOP(i, World::Inferences::bp_as_subject(bp), - ARBITRARY_RELATION_INF) { + POSITIVE_KNOWLEDGE_LOOP(i, Inferences::bp_as_subject(bp), arbitrary_relation_inf) { inference_subject *infs0, *infs1; - World::Inferences::get_references(i, &infs0, &infs1); + Inferences::get_references(i, &infs0, &infs1); RTRelations::equivalence_relation_merge_classes(bp, domain_size, infs0->allocation_id, infs1->allocation_id); } @@ -102,10 +101,10 @@ void RelationSubjects::check_OtoO_relation(binary_predicate *bp) { inference *inf1 = NULL; int leftc = 0; inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - if ((World::Inferences::get_property(inf) == prn) && - (World::Inferences::get_certainty(inf) == CERTAIN_CE)) { - parse_node *val = World::Inferences::get_property_value(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) { + if ((PropertyInferences::get_property(inf) == prn) && + (Inferences::get_certainty(inf) == CERTAIN_CE)) { + parse_node *val = PropertyInferences::get_value(inf); inference_subject *infs2 = InferenceSubjects::from_specification(val); leftc++; if (infs2) { @@ -116,8 +115,8 @@ void RelationSubjects::check_OtoO_relation(binary_predicate *bp) { if (leftc == 1) inf1 = inf; if (leftc == 2) { StandardProblems::infs_contradiction_problem(_p_(BelievedImpossible), - World::Inferences::where_inferred(inf1), - World::Inferences::where_inferred(inf), + Inferences::where_inferred(inf1), + Inferences::where_inferred(inf), infs, "can only relate to one other thing in this way", "since the relation in question is one-to-one."); } @@ -127,8 +126,8 @@ void RelationSubjects::check_OtoO_relation(binary_predicate *bp) { LOOP_OVER(infs, inference_subject) { if (right_counts[infs->allocation_id] >= 2) { StandardProblems::infs_contradiction_problem(_p_(PM_Relation1to1Right), - World::Inferences::where_inferred(right_first[infs->allocation_id]), - World::Inferences::where_inferred(right_second[infs->allocation_id]), + Inferences::where_inferred(right_first[infs->allocation_id]), + Inferences::where_inferred(right_second[infs->allocation_id]), infs, "can only relate to one other thing in this way", "since the relation in question is one-to-one."); } @@ -158,11 +157,10 @@ void RelationSubjects::check_OtoV_relation(binary_predicate *bp) { LOOP_OVER(infs, inference_subject) right_counts[infs->allocation_id] = 0; inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, World::Inferences::bp_as_subject(bp), - ARBITRARY_RELATION_INF) { + POSITIVE_KNOWLEDGE_LOOP(inf, Inferences::bp_as_subject(bp), arbitrary_relation_inf) { parse_node *left_val = NULL; parse_node *right_val = NULL; - World::Inferences::get_references_spec(inf, &left_val, &right_val); + Inferences::get_references_spec(inf, &left_val, &right_val); inference_subject *left_infs = InferenceSubjects::from_specification(left_val); inference_subject *right_infs = InferenceSubjects::from_specification(right_val); int left_id = (left_infs)?(left_infs->allocation_id):(-1); @@ -186,8 +184,8 @@ void RelationSubjects::check_OtoV_relation(binary_predicate *bp) { if (left_counts[infs->allocation_id] >= 2) { StandardProblems::infs_contradiction_problem( _p_(PM_RelationVtoOContradiction), - World::Inferences::where_inferred(left_first[infs->allocation_id]), - World::Inferences::where_inferred(left_second[infs->allocation_id]), + Inferences::where_inferred(left_first[infs->allocation_id]), + Inferences::where_inferred(left_second[infs->allocation_id]), infs, "can only relate to one other thing in this way", "since the relation in question is various-to-one."); } @@ -197,8 +195,8 @@ void RelationSubjects::check_OtoV_relation(binary_predicate *bp) { if (right_counts[infs->allocation_id] >= 2) { StandardProblems::infs_contradiction_problem( _p_(PM_RelationOtoVContradiction), - World::Inferences::where_inferred(right_first[infs->allocation_id]), - World::Inferences::where_inferred(right_second[infs->allocation_id]), + Inferences::where_inferred(right_first[infs->allocation_id]), + Inferences::where_inferred(right_second[infs->allocation_id]), infs, "can only be related to by one other thing in this way", "since the relation in question is one-to-various."); } diff --git a/inform7/knowledge-module/Chapter 4/Variable Subjects.w b/inform7/knowledge-module/Chapter 4/Variable Subjects.w index 066c507b4..88ef2d7bb 100644 --- a/inform7/knowledge-module/Chapter 4/Variable Subjects.w +++ b/inform7/knowledge-module/Chapter 4/Variable Subjects.w @@ -52,8 +52,8 @@ inference *VariableSubjects::get_initial_value_inference(nonlocal_variable *nlv) if (nlv) { inference_subject *infs = NonlocalVariables::to_subject(nlv); inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_variable_initial_value) + POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) + if (PropertyInferences::get_property(inf) == P_variable_initial_value) return inf; } return NULL; @@ -61,13 +61,13 @@ inference *VariableSubjects::get_initial_value_inference(nonlocal_variable *nlv) parse_node *VariableSubjects::get_initial_value(nonlocal_variable *nlv) { inference *inf = VariableSubjects::get_initial_value_inference(nlv); - if (inf) return World::Inferences::get_property_value(inf); + if (inf) return PropertyInferences::get_value(inf); return Specifications::new_UNKNOWN(EMPTY_WORDING); } parse_node *VariableSubjects::origin_of_initial_value(nonlocal_variable *nlv) { inference *inf = VariableSubjects::get_initial_value_inference(nlv); - if (inf) return World::Inferences::where_inferred(inf); + if (inf) return Inferences::where_inferred(inf); return NULL; } diff --git a/inform7/knowledge-module/Chapter 5/Compile Model World.w b/inform7/knowledge-module/Chapter 5/Compile Model World.w deleted file mode 100644 index bd98d865c..000000000 --- a/inform7/knowledge-module/Chapter 5/Compile Model World.w +++ /dev/null @@ -1,39 +0,0 @@ -[World::Compile::] Compile Model World. - -To manage the compilation of the diverse run-time arrays and/or code -needed to set up the initial state of the model world. - -@ A modest temporary array is needed to tally up the memory cost of creating -objects of given kinds, for the sake of the index: - -= -int *rough_array_memory_used = NULL; /* in words, not bytes; for kinds only */ - -void World::Compile::set_rough_memory_usage(kind *K, int words_used) { - if (K == NULL) return; - if (rough_array_memory_used == NULL) - internal_error("rough_array_memory_used unallocated"); - rough_array_memory_used[Kinds::get_construct(K)->allocation_id] = words_used; -} - -int World::Compile::get_rough_memory_usage(kind *K) { - if (K == NULL) return 0; - if (rough_array_memory_used == NULL) - internal_error("rough_array_memory_used unallocated"); - return rough_array_memory_used[Kinds::get_construct(K)->allocation_id]; -} - -@ The actual compilation is entirely delegated: we ask if the plugins want -to write anything, then put the same question to the subjects. - -= -void World::Compile::compile(void) { - Plugins::Call::compile_model_tables(); - int nc = NUMBER_CREATED(kind_constructor), i; - rough_array_memory_used = (int *) - (Memory::calloc(nc, sizeof(int), COMPILATION_SIZE_MREASON)); - for (i=0; imethods = Methods::new_set(); + f->affinity_threshold = T; + f->log_name = Str::duplicate(name); + return f; +} + +@ + +@e LOG_INF_MTID + += +VOID_METHOD_TYPE(LOG_INF_MTID, inference_family *f, inference *inf) + +void Inferences::log_family_details(inference *inf) { + VOID_METHOD_CALL(inf->family, LOG_INF_MTID, inf); +} + +@ + +@e JOIN_INF_MTID + += +VOID_METHOD_TYPE(JOIN_INF_MTID, inference_family *f, inference *inf, inference_subject *infs) + +void Inferences::join_family(inference *inf, inference_subject *infs) { + VOID_METHOD_CALL(inf->family, JOIN_INF_MTID, inf, infs); +} + +@ + +@e COMPARE_INF_MTID + += +INT_METHOD_TYPE(COMPARE_INF_MTID, inference_family *f, inference *inf1, inference *inf2) + +int Inferences::family_specific_cmp(inference *inf1, inference *inf2) { + int rv = 0; + INT_METHOD_CALL(rv, inf1->family, COMPARE_INF_MTID, inf1, inf2); + return rv; +} + +@ + +@e EXPLAIN_CONTRADICTION_INF_MTID + += +INT_METHOD_TYPE(EXPLAIN_CONTRADICTION_INF_MTID, inference_family *f, + inference *A, inference *B, int similarity, inference_subject *subj) + +int Inferences::explain_contradiction(inference *A, inference *B, + int similarity, inference_subject *subj) { + int rv = 0; + INT_METHOD_CALL(rv, A->family, EXPLAIN_CONTRADICTION_INF_MTID, A, B, similarity, subj); + return rv; +} + +@ + += +void Inferences::start(void) { + Plugins::Call::create_inference_families(); +} + +@ = typedef struct inference { - int inference_type; /* see above */ + inference_family *family; /* see above */ int certainty; /* see above */ - struct parse_node *inferred_from; /* from what sentence was this drawn? */ - int added_in_construction; /* or was this drawn during the model completion stage? */ - int inference_timestamp; + general_pointer data; struct inference_subject *infs_ref1; /* from 0 to 2 other INFSs are connected by this inference */ struct inference_subject *infs_ref2; @@ -57,10 +120,8 @@ typedef struct inference { struct parse_node *spec_ref1; /* used by dynamic relations between non-subjects */ struct parse_node *spec_ref2; - struct property *inferred_property; /* property referred to, if any */ - struct parse_node *inferred_property_value; /* and its value, if any */ - - struct inference *next; /* next in list of inferences on same subject */ + struct parse_node *inferred_from; /* from what sentence was this drawn? */ + int drawn_during_stage; /* or was this drawn during the model completion stage? */ CLASS_DEFINITION } inference; @@ -70,52 +131,37 @@ to any subject: but it will not stay unattached for long. Note that if nothing has been said about likelihood, the sentence is assumed to be factually certain. = -int inference_timer = 0; - -inference *World::Inferences::create_inference(int type, int certitude) { +inference *Inferences::create_inference(inference_family *f, general_pointer data, + int certitude) { PROTECTED_MODEL_PROCEDURE; + if (f == NULL) internal_error("inference orphaned"); if (certitude == UNKNOWN_CE) certitude = CERTAIN_CE; inference *new_i; new_i = CREATE(inference); - new_i->inference_timestamp = inference_timer++; - new_i->inference_type = type; + new_i->family = f; + new_i->data = data; new_i->certainty = certitude; new_i->infs_ref1 = NULL; new_i->infs_ref2 = NULL; new_i->spec_ref1 = NULL; new_i->spec_ref2 = NULL; - new_i->inferred_property = NULL; - new_i->inferred_property_value = NULL; new_i->inferred_from = current_sentence; - new_i->added_in_construction = Task::is_during_stage(MODEL_COMPLETE_CSEQ); - new_i->next = NULL; + new_i->drawn_during_stage = World::current_building_stage(); return new_i; } @ Here are our two core inference types: = -inference *World::Inferences::create_property_inference(inference_subject *infs, - property *prn, parse_node *val) { +inference *Inferences::create_relation_inference(inference_subject *infs0, inference_subject *infs1) { PROTECTED_MODEL_PROCEDURE; - inference *i = World::Inferences::create_inference(PROPERTY_INF, prevailing_mood); - if (prevailing_mood == UNKNOWN_CE) - i->certainty = InferenceSubjects::get_default_certainty(infs); - i->inferred_property = prn; - i->inferred_property_value = val; - if (prn == NULL) internal_error("null property inference"); + inference *i = Inferences::create_inference(arbitrary_relation_inf, NULL_GENERAL_POINTER, prevailing_mood); + i->infs_ref1 = Inferences::divert_infs(infs0); + i->infs_ref2 = Inferences::divert_infs(infs1); return i; } -inference *World::Inferences::create_relation_inference(inference_subject *infs0, inference_subject *infs1) { +inference *Inferences::create_relation_inference_spec(parse_node *spec0, parse_node *spec1) { PROTECTED_MODEL_PROCEDURE; - inference *i = World::Inferences::create_inference(ARBITRARY_RELATION_INF, prevailing_mood); - i->infs_ref1 = World::Inferences::divert_infs(infs0); - i->infs_ref2 = World::Inferences::divert_infs(infs1); - return i; -} - -inference *World::Inferences::create_relation_inference_spec(parse_node *spec0, parse_node *spec1) { - PROTECTED_MODEL_PROCEDURE; - inference *i = World::Inferences::create_inference(ARBITRARY_RELATION_INF, prevailing_mood); + inference *i = Inferences::create_inference(arbitrary_relation_inf, NULL_GENERAL_POINTER, prevailing_mood); i->spec_ref1 = spec0; i->spec_ref2 = spec1; if ((spec0 == NULL) || (spec1 == NULL)) internal_error("malformed specified relation"); @@ -131,44 +177,31 @@ might not actually accept it; it might be redundant, or contradictory.) The two core inferences: = -void World::Inferences::draw_property(inference_subject *infs, - property *prn, parse_node *val) { - inference *i = World::Inferences::create_property_inference(infs, prn, val); - World::Inferences::join_inference(i, infs); -} - -void World::Inferences::draw_negated_property(inference_subject *infs, - property *prn, parse_node *val) { - inference *i = World::Inferences::create_property_inference(infs, prn, val); - i->certainty = -i->certainty; - World::Inferences::join_inference(i, infs); -} - -inference_subject *World::Inferences::bp_as_subject(binary_predicate *bp) { +inference_subject *Inferences::bp_as_subject(binary_predicate *bp) { return bp->knowledge_about_bp; } -void World::Inferences::draw_relation(binary_predicate *bp, +void Inferences::draw_relation(binary_predicate *bp, inference_subject *infs0, inference_subject *infs1) { - inference *i = World::Inferences::create_relation_inference(infs0, infs1); - World::Inferences::join_inference(i, World::Inferences::bp_as_subject(bp)); + inference *i = Inferences::create_relation_inference(infs0, infs1); + Inferences::join_inference(i, Inferences::bp_as_subject(bp)); } -void World::Inferences::draw_relation_spec(binary_predicate *bp, +void Inferences::draw_relation_spec(binary_predicate *bp, parse_node *spec0, parse_node *spec1) { - inference *i = World::Inferences::create_relation_inference_spec(spec0, spec1); - World::Inferences::join_inference(i, World::Inferences::bp_as_subject(bp)); + inference *i = Inferences::create_relation_inference_spec(spec0, spec1); + Inferences::join_inference(i, Inferences::bp_as_subject(bp)); } @ And an all-purpose routine provided for plugins to draw customised inferences of their own: = -void World::Inferences::draw(int type, inference_subject *about, +void Inferences::draw(inference_family *f, inference_subject *about, int certitude, inference_subject *infs0, inference_subject *infs1) { - inference *i = World::Inferences::create_inference(type, certitude); - i->infs_ref1 = World::Inferences::divert_infs(infs0); i->infs_ref2 = World::Inferences::divert_infs(infs1); - World::Inferences::join_inference(i, about); + inference *i = Inferences::create_inference(f, NULL_GENERAL_POINTER, certitude); + i->infs_ref1 = Inferences::divert_infs(infs0); i->infs_ref2 = Inferences::divert_infs(infs1); + Inferences::join_inference(i, about); } @h Reading inference data. @@ -176,41 +209,24 @@ Once drawn, inferences are read-only, and the following access routines allow them to be read. = -int World::Inferences::get_timestamp(inference *i) { - return i->inference_timestamp; +inference_family *Inferences::get_inference_type(inference *i) { + return i->family; } -int World::Inferences::get_inference_type(inference *i) { - return i->inference_type; -} - -parse_node *World::Inferences::where_inferred(inference *i) { +parse_node *Inferences::where_inferred(inference *i) { return i->inferred_from; } -int World::Inferences::get_certainty(inference *i) { +int Inferences::get_certainty(inference *i) { return i->certainty; } -void World::Inferences::set_certainty(inference *i, int ce) { +void Inferences::set_certainty(inference *i, int ce) { i->certainty = ce; } -int World::Inferences::added_in_construction(inference *i) { - return i->added_in_construction; -} - -property *World::Inferences::get_property(inference *i) { - return i->inferred_property; -} - -parse_node *World::Inferences::get_property_value(inference *i) { - return i->inferred_property_value; -} - -parse_node *World::Inferences::set_property_value_kind(inference *i, kind *K) { - Node::set_kind_of_value(i->inferred_property_value, K); - return i->inferred_property_value; +int Inferences::during_stage(inference *i) { + return i->drawn_during_stage; } @ Core Inform deals only in INFSs, but plugins often use inferences concerned @@ -218,17 +234,17 @@ only with objects (e.g., for the map), so we also provide a convenient abbreviat way to extract just reference 1 in object form. = -void World::Inferences::get_references(inference *i, +void Inferences::get_references(inference *i, inference_subject **infs1, inference_subject **infs2) { if (infs1) *infs1 = i->infs_ref1; if (infs2) *infs2 = i->infs_ref2; } -void World::Inferences::get_references_spec(inference *i, +void Inferences::get_references_spec(inference *i, parse_node **spec1, parse_node **spec2) { *spec1 = i->spec_ref1; *spec2 = i->spec_ref2; } -instance *World::Inferences::get_reference_as_object(inference *i) { +instance *Inferences::get_reference_as_object(inference *i) { return InstanceSubjects::to_object_instance(i->infs_ref1); } @@ -238,26 +254,28 @@ known concerning a given inference subject, and of a given type. "Positive" knowledge means that the inferences must have a certainty of likely or better. @d POSITIVE_KNOWLEDGE_LOOP(inf, infs, type) - for (inf = (infs)?(InferenceSubjects::get_inferences(World::Inferences::divert_infs(infs))):NULL; inf; inf = inf->next) - if ((inf->inference_type == type) && (inf->certainty > 0)) + LOOP_OVER_LINKED_LIST(inf, inference, + (infs)?(InferenceSubjects::get_inferences(Inferences::divert_infs(infs))):NULL) + if ((inf->family == type) && (inf->certainty > 0)) @d KNOWLEDGE_LOOP(inf, infs, type) - for (inf = (infs)?(InferenceSubjects::get_inferences(World::Inferences::divert_infs(infs))):NULL; inf; inf = inf->next) - if (inf->inference_type == type) + LOOP_OVER_LINKED_LIST(inf, inference, + (infs)?(InferenceSubjects::get_inferences(Inferences::divert_infs(infs))):NULL) + if (inf->family == type) @h Finding property states. = -int World::Inferences::get_EO_state(inference_subject *infs, property *prn) { +int Inferences::get_EO_state(inference_subject *infs, property *prn) { if ((prn == NULL) || (infs == NULL)) return UNKNOWN_CE; inference_subject *k; property *prnbar = NULL; if (Properties::is_either_or(prn)) prnbar = Properties::EitherOr::get_negation(prn); for (k = infs; k; k = InferenceSubjects::narrowest_broader_subject(k)) { inference *inf; - KNOWLEDGE_LOOP(inf, k, PROPERTY_INF) { - property *known = World::Inferences::get_property(inf); - int c = World::Inferences::get_certainty(inf); + KNOWLEDGE_LOOP(inf, k, property_inf) { + property *known = PropertyInferences::get_property(inf); + int c = Inferences::get_certainty(inf); if (known) { if ((prn == known) && (c != UNKNOWN_CE)) return c; if ((prnbar == known) && (c != UNKNOWN_CE)) return -c; @@ -267,21 +285,21 @@ int World::Inferences::get_EO_state(inference_subject *infs, property *prn) { return UNKNOWN_CE; } -int World::Inferences::get_EO_state_without_inheritance(inference_subject *infs, property *prn, parse_node **where) { +int Inferences::get_EO_state_without_inheritance(inference_subject *infs, property *prn, parse_node **where) { if ((prn == NULL) || (infs == NULL)) return UNKNOWN_CE; property *prnbar = NULL; if (Properties::is_either_or(prn)) prnbar = Properties::EitherOr::get_negation(prn); inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *known = World::Inferences::get_property(inf); - int c = World::Inferences::get_certainty(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *known = PropertyInferences::get_property(inf); + int c = Inferences::get_certainty(inf); if (known) { if ((prn == known) && (c != UNKNOWN_CE)) { - if (where) *where = World::Inferences::where_inferred(inf); + if (where) *where = Inferences::where_inferred(inf); return c; } if ((prnbar == known) && (c != UNKNOWN_CE)) { - if (where) *where = World::Inferences::where_inferred(inf); + if (where) *where = Inferences::where_inferred(inf); return -c; } } @@ -289,11 +307,11 @@ int World::Inferences::get_EO_state_without_inheritance(inference_subject *infs, return UNKNOWN_CE; } -void World::Inferences::verify_prop_states(inference_subject *infs) { +void Inferences::verify_prop_states(inference_subject *infs) { inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); - parse_node *val = World::Inferences::get_property_value(inf); + POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *prn = PropertyInferences::get_property(inf); + parse_node *val = PropertyInferences::get_value(inf); kind *PK = Properties::Valued::kind(prn); kind *VK = Specifications::to_kind(val); if (Kinds::compatible(VK, PK) != ALWAYS_MATCH) { @@ -313,45 +331,45 @@ void World::Inferences::verify_prop_states(inference_subject *infs) { } } -parse_node *World::Inferences::get_prop_state(inference_subject *infs, property *prn) { +parse_node *Inferences::get_prop_state(inference_subject *infs, property *prn) { if ((prn == NULL) || (infs == NULL)) return NULL; inference_subject *k; for (k = infs; k; k = InferenceSubjects::narrowest_broader_subject(k)) { inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, k, PROPERTY_INF) { - property *known = World::Inferences::get_property(inf); - if (known == prn) return World::Inferences::get_property_value(inf); + POSITIVE_KNOWLEDGE_LOOP(inf, k, property_inf) { + property *known = PropertyInferences::get_property(inf); + if (known == prn) return PropertyInferences::get_value(inf); } } return NULL; } -parse_node *World::Inferences::get_prop_state_at(inference_subject *infs, property *prn, +parse_node *Inferences::get_prop_state_at(inference_subject *infs, property *prn, parse_node **where) { if ((prn == NULL) || (infs == NULL)) return NULL; inference_subject *k; for (k = infs; k; k = InferenceSubjects::narrowest_broader_subject(k)) { inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, k, PROPERTY_INF) { - property *known = World::Inferences::get_property(inf); + POSITIVE_KNOWLEDGE_LOOP(inf, k, property_inf) { + property *known = PropertyInferences::get_property(inf); if (known == prn) { - if (where) *where = World::Inferences::where_inferred(inf); - return World::Inferences::get_property_value(inf); + if (where) *where = Inferences::where_inferred(inf); + return PropertyInferences::get_value(inf); } } } return NULL; } -parse_node *World::Inferences::get_prop_state_without_inheritance(inference_subject *infs, +parse_node *Inferences::get_prop_state_without_inheritance(inference_subject *infs, property *prn, parse_node **where) { if ((prn == NULL) || (infs == NULL)) return NULL; inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *known = World::Inferences::get_property(inf); + POSITIVE_KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *known = PropertyInferences::get_property(inf); if (known == prn) { - if (where) *where = World::Inferences::where_inferred(inf); - return World::Inferences::get_property_value(inf); + if (where) *where = Inferences::where_inferred(inf); + return PropertyInferences::get_value(inf); } } return NULL; @@ -362,11 +380,11 @@ This is where the detailed description of a given kind -- what properties it has, and so on -- is generated. = -void World::Inferences::index(OUTPUT_STREAM, inference_subject *infs, int brief) { +void Inferences::index(OUTPUT_STREAM, inference_subject *infs, int brief) { inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) - if (World::Inferences::get_property(inf) == P_specification) { - parse_node *spec = World::Inferences::get_property_value(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) + if (PropertyInferences::get_property(inf) == P_specification) { + parse_node *spec = PropertyInferences::get_value(inf); Index::dequote(OUT, Lexer::word_raw_text(Wordings::first_wn(Node::get_text(spec)))); HTML_TAG("br"); } @@ -385,18 +403,18 @@ void World::Inferences::index(OUTPUT_STREAM, inference_subject *infs, int brief) case IMPOSSIBLE_CE: cert = "Never"; break; case INITIALLY_CE: cert = "Initially"; break; } - World::Inferences::index_provided(OUT, infs, TRUE, c, cert, brief); + Inferences::index_provided(OUT, infs, TRUE, c, cert, brief); } - World::Inferences::index_provided(OUT, infs, FALSE, LIKELY_CE, "Can have", brief); + Inferences::index_provided(OUT, infs, FALSE, LIKELY_CE, "Can have", brief); } @ The following lists off the properties of the kind, with the given state of being boolean, and the given certainty levels: = -int World::Inferences::has_or_can_have(inference_subject *infs, property *prn) { +int Inferences::has_or_can_have(inference_subject *infs, property *prn) { if (Properties::is_either_or(prn)) { - int has = World::Inferences::get_EO_state(infs, prn); + int has = Inferences::get_EO_state(infs, prn); if ((has == UNKNOWN_CE) && (World::Permissions::find(infs, prn, TRUE))) { if (Properties::EitherOr::stored_in_negation(prn)) return LIKELY_CE; @@ -409,7 +427,7 @@ int World::Inferences::has_or_can_have(inference_subject *infs, property *prn) { return UNKNOWN_CE; } -void World::Inferences::index_provided(OUTPUT_STREAM, inference_subject *infs, int bool, int c, char *cert, int brief) { +void Inferences::index_provided(OUTPUT_STREAM, inference_subject *infs, int bool, int c, char *cert, int brief) { int f = TRUE; property *prn; LOOP_OVER(prn, property) { @@ -417,9 +435,9 @@ void World::Inferences::index_provided(OUTPUT_STREAM, inference_subject *infs, i if (Properties::get_indexed_already_flag(prn)) continue; if (Properties::is_either_or(prn) != bool) continue; - int state = World::Inferences::has_or_can_have(infs, prn); + int state = Inferences::has_or_can_have(infs, prn); if (state != c) continue; - int inherited_state = World::Inferences::has_or_can_have( + int inherited_state = Inferences::has_or_can_have( InferenceSubjects::narrowest_broader_subject(infs), prn); if ((state == inherited_state) && (brief)) continue; @@ -451,14 +469,14 @@ void World::Inferences::index_provided(OUTPUT_STREAM, inference_subject *infs, i This only tells about specific property settings for a given instance. = -void World::Inferences::index_specific(OUTPUT_STREAM, inference_subject *infs) { +void Inferences::index_specific(OUTPUT_STREAM, inference_subject *infs) { property *prn; int k = 0; LOOP_OVER(prn, property) if (Properties::is_shown_in_index(prn)) if (Properties::is_either_or(prn)) { if (World::Permissions::find(infs, prn, TRUE)) { parse_node *P = NULL; - int S = World::Inferences::get_EO_state_without_inheritance(infs, prn, &P); + int S = Inferences::get_EO_state_without_inheritance(infs, prn, &P); property *prnbar = Properties::EitherOr::get_negation(prn); if ((prnbar) && (S < 0)) continue; if (S != UNKNOWN_CE) { @@ -477,7 +495,7 @@ void World::Inferences::index_specific(OUTPUT_STREAM, inference_subject *infs) { if (Properties::is_either_or(prn) == FALSE) if (World::Permissions::find(infs, prn, TRUE)) { parse_node *P = NULL; - parse_node *S = World::Inferences::get_prop_state_without_inheritance(infs, prn, &P); + parse_node *S = Inferences::get_prop_state_without_inheritance(infs, prn, &P); if ((S) && (Wordings::nonempty(Node::get_text(S)))) { HTML::open_indented_p(OUT, 1, "hanging"); WRITE("%+W: ", prn->name); @@ -496,7 +514,7 @@ for comparing strings, in that it compares two inferences and returns a value useful for sorting algorithms: 0 if equal, positive if |i1 < i2|, negative if |i2 < i1|. This is a stable trichotomy; in particular, = (text as code) - World::Inferences::compare_inferences(I, J) == -World::Inferences::compare_inferences(J, I) + Inferences::compare_inferences(I, J) == -Inferences::compare_inferences(J, I) = for all pairs of inference pointers |I| and |J|. @@ -537,66 +555,61 @@ Pointer subtraction is, in any case, frowned on in all the best houses, so this was probably a good thing. = -int World::Inferences::compare_inferences(inference *i1, inference *i2) { +int Inferences::compare_inferences(inference *i1, inference *i2) { +// PRINT("%S %S on %d %d\n", i1->family->log_name, i2->family->log_name, i1->allocation_id, i2->allocation_id); + int c = Inferences::compare_inferencesi(i1, i2); +// PRINT("= %d\n", c); + return c; +} +int Inferences::compare_inferencesi(inference *i1, inference *i2) { if (i1 == i2) return CI_IDENTICAL; if (i1 == NULL) return CI_DIFFER_IN_EXISTENCE; if (i2 == NULL) return -CI_DIFFER_IN_EXISTENCE; - int c = i1->inference_type - i2->inference_type; + int c = i1->family->allocation_id - i2->family->allocation_id; if (c > 0) return CI_DIFFER_IN_TYPE; if (c < 0) return -CI_DIFFER_IN_TYPE; - property *pr1 = i1->inferred_property; - property *pr2 = i2->inferred_property; - if ((pr1) && (Properties::is_either_or(pr1)) && - (pr2) && (Properties::is_either_or(pr2)) && - ((pr1 == Properties::EitherOr::get_negation(pr2)) || - (pr2 == Properties::EitherOr::get_negation(pr1)))) pr2 = pr1; - c = World::Inferences::measure_property(pr1) - World::Inferences::measure_property(pr2); - if (c > 0) return CI_DIFFER_IN_PROPERTY; if (c < 0) return -CI_DIFFER_IN_PROPERTY; - c = World::Inferences::measure_infs(i1->infs_ref2) - World::Inferences::measure_infs(i2->infs_ref2); + + c = Inferences::family_specific_cmp(i1, i2); if (c != 0) return c; + + c = Inferences::measure_infs(i1->infs_ref2) - Inferences::measure_infs(i2->infs_ref2); if (c > 0) return CI_DIFFER_IN_INFS2; if (c < 0) return -CI_DIFFER_IN_INFS2; - c = World::Inferences::measure_infs(i1->infs_ref1) - World::Inferences::measure_infs(i2->infs_ref1); + c = Inferences::measure_infs(i1->infs_ref1) - Inferences::measure_infs(i2->infs_ref1); if (c > 0) return CI_DIFFER_IN_INFS1; if (c < 0) return -CI_DIFFER_IN_INFS1; - c = World::Inferences::measure_pn(i1->spec_ref2) - World::Inferences::measure_pn(i2->spec_ref2); + c = Inferences::measure_pn(i1->spec_ref2) - Inferences::measure_pn(i2->spec_ref2); if (c > 0) return CI_DIFFER_IN_INFS2; if (c < 0) return -CI_DIFFER_IN_INFS2; - c = World::Inferences::measure_pn(i1->spec_ref1) - World::Inferences::measure_pn(i2->spec_ref1); + c = Inferences::measure_pn(i1->spec_ref1) - Inferences::measure_pn(i2->spec_ref1); if (c > 0) return CI_DIFFER_IN_INFS1; if (c < 0) return -CI_DIFFER_IN_INFS1; - c = World::Inferences::measure_inf(i1) - World::Inferences::measure_inf(i2); - parse_node *val1 = i1->inferred_property_value; - parse_node *val2 = i2->inferred_property_value; - if ((i1->inferred_property != i2->inferred_property) || - ((val1) && (val2) && (Rvalues::compare_CONSTANT(val1, val2) == FALSE))) { - if (c > 0) return CI_DIFFER_IN_PROPERTY_VALUE; - if (c < 0) return -CI_DIFFER_IN_PROPERTY_VALUE; - } + c = Inferences::measure_inf(i1) - Inferences::measure_inf(i2); + if (c > 0) return CI_DIFFER_IN_COPY_ONLY; if (c < 0) return -CI_DIFFER_IN_COPY_ONLY; return CI_IDENTICAL; } -int World::Inferences::measure_property(property *P) { +int Inferences::measure_property(property *P) { if (P) return 1 + P->allocation_id; return 0; } -int World::Inferences::measure_inf(inference *I) { +int Inferences::measure_inf(inference *I) { if (I) return 1 + I->allocation_id; return 0; } -int World::Inferences::measure_infs(inference_subject *IS) { +int Inferences::measure_infs(inference_subject *IS) { if (IS) return 1 + IS->allocation_id; return 0; } -int World::Inferences::measure_pn(parse_node *N) { +int Inferences::measure_pn(parse_node *N) { if (N) return 1 + N->allocation_id; return 0; } int infs_diversion = TRUE; -void World::Inferences::diversion_on(void) { +void Inferences::diversion_on(void) { infs_diversion = TRUE; } -void World::Inferences::diversion_off(void) { +void Inferences::diversion_off(void) { infs_diversion = FALSE; } -inference_subject *World::Inferences::divert_infs(inference_subject *infs) { +inference_subject *Inferences::divert_infs(inference_subject *infs) { #ifdef IF_MODULE if (infs_diversion) if ((I_yourself) && (player_VAR) && @@ -620,47 +633,47 @@ list; that is, if it is found to contradict or duplicate existing knowledge, then the routine exits without completing the loop. = -void World::Inferences::join_inference(inference *i, inference_subject *infs) { +void Inferences::join_inference(inference *i, inference_subject *infs) { PROTECTED_MODEL_PROCEDURE; if (i == NULL) internal_error("joining null inference"); if (infs == NULL) internal_error("joining to null inference subject"); - infs = World::Inferences::divert_infs(infs); + infs = Inferences::divert_infs(infs); int inserted = FALSE; - inference *list, *prev; - for (prev = NULL, list = InferenceSubjects::get_inferences(infs); - (list) && (inserted == FALSE); prev = list, list = list->next) { + linked_list *SL = InferenceSubjects::get_inferences(infs); + inference *list, *prev = NULL; + int pos = 0; + LOOP_OVER_LINKED_LIST(list, inference, SL) + if (inserted == FALSE) { + int c = Inferences::compare_inferences(i, list); + int d = c; if (d < 0) d = -d; + int icl = i->certainty; if (icl < 0) icl = -icl; + int lcl = list->certainty; if (lcl < 0) lcl = -lcl; - int c = World::Inferences::compare_inferences(i, list); - int d = c; if (d < 0) d = -d; - int icl = i->certainty; if (icl < 0) icl = -icl; - int lcl = list->certainty; if (lcl < 0) lcl = -lcl; + int affinity_threshold; + @; + if (d >= affinity_threshold) { + @; + return; + } - int affinity_threshold; - @; - if (d >= affinity_threshold) { - @; - return; + if (c<0) @; + pos++; prev = list; } - - if (c<0) @; - } if (inserted == FALSE) @; - World::Inferences::report_inference(i, infs, "drawn"); - if (i->inference_type == PROPERTY_INF) - Plugins::Call::property_value_notify( - i->inferred_property, i->inferred_property_value); + Inferences::report_inference(i, infs, "drawn"); + Inferences::join_family(i, infs); } @ = - if (prev == NULL) InferenceSubjects::set_inferences(infs, i); else prev->next = i; - i->next = list; inserted = TRUE; + LinkedLists::insert(SL, pos, i); + inserted = TRUE; @ The first question we must answer is when our two inferences are talking about what is basically the same fact. We do this by requiring that the -absolute value of the |World::Inferences::compare_inferences| score -- which will always be +absolute value of the |Inferences::compare_inferences| score -- which will always be one of the |CI_*| constants enumerated above -- must exceed some threshold. (Recall that higher scores mean greater similarity; the perfect |CI_IDENTICAL| is not possible here.) @@ -668,7 +681,7 @@ is not possible here.) The threshold depends on what type of inference we're looking at, but it's always at least half-way down the list, so we can be certain that = (text as InC) - i->inference_type == list->inference_type + i->family == list->family = (and therefore it's unambiguous what we mean by the type of inference being looked at). For two property inferences to be talking about the same fact, @@ -682,11 +695,7 @@ We set the affinity threshold purposely low for customised inferences belonging to plugins (at present, anyway). @ = - switch (list->inference_type) { - case PROPERTY_INF: affinity_threshold = CI_DIFFER_IN_PROPERTY_VALUE; break; - case ARBITRARY_RELATION_INF: affinity_threshold = CI_DIFFER_IN_COPY_ONLY; break; - default: affinity_threshold = CI_DIFFER_IN_INFS1; break; - } + affinity_threshold = list->family->affinity_threshold; @ So, let's suppose our new inference |i| is sufficiently close to the our existing one, |list|. What then? @@ -701,18 +710,17 @@ existing one, |list|. What then? if ((icl == LIKELY_CE) && (InferenceSubjects::get_default_certainty(infs) == LIKELY_CE)) @; } - World::Inferences::report_inference(i, infs, "redundant"); + Inferences::report_inference(i, infs, "redundant"); } @ Where: @ = if (lcl > icl) { - World::Inferences::report_inference(i, infs, "discarded (we already know better)"); + Inferences::report_inference(i, infs, "discarded (we already know better)"); } else { - i->next = list->next; - if (prev == NULL) InferenceSubjects::set_inferences(infs, i); else prev->next = i; - World::Inferences::report_inference(i, infs, "replaced existing less certain one"); + LinkedLists::set_entry(pos, SL, i); + Inferences::report_inference(i, infs, "replaced existing less certain one"); } @ Note that certainties opposite in sign reverse the issue of whether a @@ -728,89 +736,27 @@ are always required to be positive in sense, i.e., with positive certainty, and so clashed are impossible.) @ = - switch (list->inference_type) { - case PROPERTY_INF: - if (d == CI_DIFFER_IN_PROPERTY_VALUE) contradiction_flag = TRUE; - break; - default: - if (Plugins::Call::inferences_contradict(list, i, d)) contradiction_flag = TRUE; - break; + if (list->family == property_inf) { + if (d == CI_DIFFER_IN_PROPERTY_VALUE) contradiction_flag = TRUE; + } else { + if (Plugins::Call::inferences_contradict(list, i, d)) contradiction_flag = TRUE; } if (list->certainty == -i->certainty) contradiction_flag = (contradiction_flag)?FALSE:TRUE; @ = - World::Inferences::report_inference(i, infs, "contradiction"); - World::Inferences::report_inference(list, infs, "with"); - if ((list->inference_type != PROPERTY_INF) && - (list->inference_type != ARBITRARY_RELATION_INF) && + Inferences::report_inference(i, infs, "contradiction"); + Inferences::report_inference(list, infs, "with"); +/* if ((list->family != property_inf) && + (list->family != arbitrary_relation_inf) && (Plugins::Call::explain_contradiction(list, i, d, infs))) return; - if (i->inference_type == PROPERTY_INF) { - if (i->inferred_property == P_variable_initial_value) - StandardProblems::two_sentences_problem(_p_(PM_VariableContradiction), - list->inferred_from, - "this looks like a contradiction", - "because the initial value of this variable seems to be being set " - "in each of these sentences, but with a different outcome."); - else { - if (Properties::is_value_property(i->inferred_property)) { - binary_predicate *bp = - Properties::Valued::get_stored_relation(i->inferred_property); - if (bp) { - if (Wordings::match(Node::get_text(current_sentence), Node::get_text(list->inferred_from))) { - Problems::quote_source(1, current_sentence); - Problems::quote_relation(3, bp); - Problems::quote_subject(4, infs); - Problems::quote_spec(5, i->inferred_property_value); - Problems::quote_spec(6, list->inferred_property_value); - StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_RelationContradiction2)); - Problems::issue_problem_segment( - "I'm finding a contradiction at the sentence %1, " - "because it means I can't set up %3. " - "On the one hand, %4 should relate to %5, but on the other " - "hand to %6, and this is a relation which doesn't allow " - "such clashes."); - Problems::issue_problem_end(); - } else { - Problems::quote_source(1, current_sentence); - Problems::quote_source(2, list->inferred_from); - Problems::quote_relation(3, bp); - Problems::quote_subject(4, infs); - Problems::quote_spec(5, i->inferred_property_value); - Problems::quote_spec(6, list->inferred_property_value); - StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_RelationContradiction)); - Problems::issue_problem_segment( - "I'm finding a contradiction at the sentences %1 and %2, " - "because between them they set up rival versions of %3. " - "On the one hand, %4 should relate to %5, but on the other " - "hand to %6, and this is a relation which doesn't allow " - "such clashes."); - Problems::issue_problem_end(); - } - return; - } - } - StandardProblems::two_sentences_problem(_p_(PM_PropertyContradiction), - list->inferred_from, - "this looks like a contradiction", - "because the same property seems to be being set in each of these sentences, " - "but with a different outcome."); - } - } else - #ifdef IF_MODULE - if (i->inference_type == IS_ROOM_INF) { - StandardProblems::two_sentences_problem(_p_(PM_WhenIsARoomNotARoom), - list->inferred_from, - "this looks like a contradiction", - "because apparently something would have to be both a room and not a " - "room at the same time."); - } else - #endif - StandardProblems::two_sentences_problem(_p_(PM_Contradiction), - list->inferred_from, - "this looks like a contradiction", - "which might be because I have misunderstood what was meant to be the subject " - "of one or both of those sentences."); +*/ + if (Inferences::explain_contradiction(list, i, d, infs)) return; + StandardProblems::two_sentences_problem(_p_(PM_Contradiction), + list->inferred_from, + "this looks like a contradiction", + "which might be because I have misunderstood what was meant to be the subject " + "of one or both of those sentences."); return; @ When talking about kinds or kinds of value, we allow new merely likely @@ -820,9 +766,8 @@ people to change the effect of extensions which create kinds and specify their likely properties.) @ = - i->next = list->next; - if (prev == NULL) InferenceSubjects::set_inferences(infs, i); else prev->next = i; - World::Inferences::report_inference(i, infs, "replaced existing also only likely one"); + LinkedLists::set_entry(pos, SL, i); + Inferences::report_inference(i, infs, "replaced existing also only likely one"); return; @h Logging inferences. @@ -831,24 +776,21 @@ goes on with inferences, as there is obviously great potential for mystifying bugs if inferences are incorrectly ignored. = -void World::Inferences::report_inference(inference *i, inference_subject *infs, char *what_happened) { +void Inferences::report_inference(inference *i, inference_subject *infs, char *what_happened) { LOGIF(INFERENCES, ":::: %s: $j - $I\n", what_happened, infs, i); } @ And more generally: = -void World::Inferences::log_kind(int it) { - switch(it) { - case ARBITRARY_RELATION_INF: LOG("ARBITRARY_RELATION_INF"); break; - case PROPERTY_INF: LOG("PROPERTY_INF"); break; - default: Plugins::Call::log_inference_type(it); break; - } +void Inferences::log_kind(inference_family *f) { + if (f == NULL) LOG(""); + else LOG("%S", f->log_name); } -void World::Inferences::log(inference *in) { +void Inferences::log(inference *in) { if (in == NULL) { LOG(""); return; } - World::Inferences::log_kind(in->inference_type); + Inferences::log_kind(in->family); LOG("-"); switch(in->certainty) { case IMPOSSIBLE_CE: LOG("Impossible "); break; @@ -858,8 +800,7 @@ void World::Inferences::log(inference *in) { case CERTAIN_CE: LOG("Certain "); break; default: LOG(""); break; } - if (in->inferred_property) LOG("(%W)", in->inferred_property->name); - if (in->inferred_property_value) LOG("-1:$P", in->inferred_property_value); + Inferences::log_family_details(in); if (in->infs_ref1) LOG("-1:$j", in->infs_ref1); if (in->infs_ref2) LOG("-2:$j", in->infs_ref2); if (in->spec_ref1) LOG("-s1:$P", in->spec_ref1); diff --git a/inform7/knowledge-module/Chapter 5/Property Inferences.w b/inform7/knowledge-module/Chapter 5/Property Inferences.w new file mode 100644 index 000000000..d21af0c7b --- /dev/null +++ b/inform7/knowledge-module/Chapter 5/Property Inferences.w @@ -0,0 +1,165 @@ +[PropertyInferences::] Property Inferences. + +Inferences that a property of something is true, or has a particular value. + +@ We will make: + += (early code) +inference_family *property_inf = NULL; + +@ + += +void PropertyInferences::start(void) { + property_inf = Inferences::new_family(I"property_inf", CI_DIFFER_IN_PROPERTY_VALUE); + METHOD_ADD(property_inf, LOG_INF_MTID, PropertyInferences::log); + METHOD_ADD(property_inf, COMPARE_INF_MTID, PropertyInferences::cmp); + METHOD_ADD(property_inf, JOIN_INF_MTID, PropertyInferences::join); + METHOD_ADD(property_inf, EXPLAIN_CONTRADICTION_INF_MTID, PropertyInferences::explain_contradiction); +} + +void PropertyInferences::join(inference_family *f, inference *inf, inference_subject *infs) { + property_inference_data *data = RETRIEVE_POINTER_property_inference_data(inf->data); + Plugins::Call::property_value_notify( + data->inferred_property, data->inferred_property_value); +} + +int PropertyInferences::cmp(inference_family *f, inference *i1, inference *i2) { + property_inference_data *data1 = RETRIEVE_POINTER_property_inference_data(i1->data); + property_inference_data *data2 = RETRIEVE_POINTER_property_inference_data(i2->data); + property *pr1 = data1->inferred_property; + property *pr2 = data2->inferred_property; + if ((pr1) && (Properties::is_either_or(pr1)) && + (pr2) && (Properties::is_either_or(pr2)) && + ((pr1 == Properties::EitherOr::get_negation(pr2)) || + (pr2 == Properties::EitherOr::get_negation(pr1)))) pr2 = pr1; + int c = Inferences::measure_property(pr1) - Inferences::measure_property(pr2); + if (c > 0) return CI_DIFFER_IN_PROPERTY; if (c < 0) return -CI_DIFFER_IN_PROPERTY; + + c = Inferences::measure_inf(i1) - Inferences::measure_inf(i2); + + parse_node *val1 = data1->inferred_property_value; + parse_node *val2 = data2->inferred_property_value; + if ((data1->inferred_property != data2->inferred_property) || /* in case they are an either-or pair */ + ((val1) && (val2) && (Rvalues::compare_CONSTANT(val1, val2) == FALSE))) { + if (c > 0) return CI_DIFFER_IN_PROPERTY_VALUE; + if (c < 0) return -CI_DIFFER_IN_PROPERTY_VALUE; + } + + if (c > 0) return CI_DIFFER_IN_COPY_ONLY; if (c < 0) return -CI_DIFFER_IN_COPY_ONLY; + return CI_IDENTICAL; +} + +int PropertyInferences::explain_contradiction(inference_family *f, inference *A, + inference *B, int similarity, inference_subject *subj) { + property_inference_data *A_data = RETRIEVE_POINTER_property_inference_data(A->data); + property_inference_data *B_data = RETRIEVE_POINTER_property_inference_data(B->data); + if (B_data->inferred_property == P_variable_initial_value) { + StandardProblems::two_sentences_problem(_p_(PM_VariableContradiction), + A->inferred_from, + "this looks like a contradiction", + "because the initial value of this variable seems to be being set " + "in each of these sentences, but with a different outcome."); + } else { + if (Properties::is_value_property(B_data->inferred_property)) { + binary_predicate *bp = + Properties::Valued::get_stored_relation(B_data->inferred_property); + if (bp) { + if (Wordings::match(Node::get_text(current_sentence), + Node::get_text(A->inferred_from))) { + Problems::quote_source(1, current_sentence); + Problems::quote_relation(3, bp); + Problems::quote_subject(4, subj); + Problems::quote_spec(5, B_data->inferred_property_value); + Problems::quote_spec(6, A_data->inferred_property_value); + StandardProblems::handmade_problem(Task::syntax_tree(), + _p_(PM_RelationContradiction2)); + Problems::issue_problem_segment( + "I'm finding a contradiction at the sentence %1, " + "because it means I can't set up %3. " + "On the one hand, %4 should relate to %5, but on the other " + "hand to %6, and this is a relation which doesn't allow " + "such clashes."); + Problems::issue_problem_end(); + } else { + Problems::quote_source(1, current_sentence); + Problems::quote_source(2, A->inferred_from); + Problems::quote_relation(3, bp); + Problems::quote_subject(4, subj); + Problems::quote_spec(5, B_data->inferred_property_value); + Problems::quote_spec(6, A_data->inferred_property_value); + StandardProblems::handmade_problem(Task::syntax_tree(), + _p_(PM_RelationContradiction)); + Problems::issue_problem_segment( + "I'm finding a contradiction at the sentences %1 and %2, " + "because between them they set up rival versions of %3. " + "On the one hand, %4 should relate to %5, but on the other " + "hand to %6, and this is a relation which doesn't allow " + "such clashes."); + Problems::issue_problem_end(); + } + return TRUE; + } + } + StandardProblems::two_sentences_problem(_p_(PM_PropertyContradiction), + A->inferred_from, + "this looks like a contradiction", + "because the same property seems to be being set in each of these sentences, " + "but with a different outcome."); + } + return TRUE; +} + +void PropertyInferences::log(inference_family *f, inference *inf) { + property_inference_data *data = RETRIEVE_POINTER_property_inference_data(inf->data); + LOG("(%W)", data->inferred_property->name); + if (data->inferred_property_value) LOG(":=$P", data->inferred_property_value); +} + +typedef struct property_inference_data { + struct property *inferred_property; /* property referred to, if any */ + struct parse_node *inferred_property_value; /* and its value, if any */ + CLASS_DEFINITION +} property_inference_data; + +inference *PropertyInferences::new(inference_subject *infs, + property *prn, parse_node *val) { + PROTECTED_MODEL_PROCEDURE; + if (prn == NULL) internal_error("null property inference"); + + property_inference_data *data = CREATE(property_inference_data); + data->inferred_property = prn; + data->inferred_property_value = val; + int c = prevailing_mood; + if (c == UNKNOWN_CE) c = InferenceSubjects::get_default_certainty(infs); + inference *i = Inferences::create_inference(property_inf, + STORE_POINTER_property_inference_data(data), c); + return i; +} + +void PropertyInferences::draw(inference_subject *infs, property *prn, parse_node *val) { + inference *i = PropertyInferences::new(infs, prn, val); + Inferences::join_inference(i, infs); +} + +void PropertyInferences::draw_negated(inference_subject *infs, property *prn, parse_node *val) { + inference *i = PropertyInferences::new(infs, prn, val); + i->certainty = -i->certainty; + Inferences::join_inference(i, infs); +} + +property *PropertyInferences::get_property(inference *i) { + property_inference_data *data = RETRIEVE_POINTER_property_inference_data(i->data); + return data->inferred_property; +} + +parse_node *PropertyInferences::get_value(inference *i) { + property_inference_data *data = RETRIEVE_POINTER_property_inference_data(i->data); + return data->inferred_property_value; +} + +parse_node *PropertyInferences::set_value_kind(inference *i, kind *K) { + property_inference_data *data = RETRIEVE_POINTER_property_inference_data(i->data); + Node::set_kind_of_value(data->inferred_property_value, K); + return data->inferred_property_value; +} diff --git a/inform7/knowledge-module/Chapter 5/Relation Inferences.w b/inform7/knowledge-module/Chapter 5/Relation Inferences.w new file mode 100644 index 000000000..dde89951d --- /dev/null +++ b/inform7/knowledge-module/Chapter 5/Relation Inferences.w @@ -0,0 +1,15 @@ +[RelationInferences::] Relation Inferences. + +Inferences that a relation holds between two subjects or values. + +@ We will make: + += (early code) +inference_family *arbitrary_relation_inf = NULL; + +@ + += +void RelationInferences::start(void) { + arbitrary_relation_inf = Inferences::new_family(I"arbitrary_relation_inf", CI_DIFFER_IN_COPY_ONLY); +} diff --git a/inform7/knowledge-module/Chapter 5/Complete Model World.w b/inform7/knowledge-module/Chapter 5/The Model World.w similarity index 50% rename from inform7/knowledge-module/Chapter 5/Complete Model World.w rename to inform7/knowledge-module/Chapter 5/The Model World.w index bce0d148c..4d2a326e1 100644 --- a/inform7/knowledge-module/Chapter 5/Complete Model World.w +++ b/inform7/knowledge-module/Chapter 5/The Model World.w @@ -1,61 +1,62 @@ -[World::] Complete Model World. +[World::] The Model World. Once the assertions have all been read and reduced to inferences, -and all the creations have been made, we take stock; sometimes we spot -inconsistencies, sometimes we make deductions, and we try to complete our -picture of the model world. +we try to complete our model world. -@h Stages II to IV. -The process of using existing facts to infer new ones is vulnerable -to timing bugs, so we organise the "making" process into five numbered -stages, given the Roman numerals I to V. Much of the work is done by plugins, -which can take a hand at any or all of the stages, using their contextual -knowledge to fill in missing properties. +@h Introduction. +World-building has five stages, written with Roman numerals I to V in this +source code. The logic in this section is all quite simple, but plugins are +allowed to intervene at each of the five stages, bringing domain-specific +wisdom to the process. -(I) Deducing the kind of any object whose kind is not known. Because this -can result in a change of kind, which can result in further creations by -assembly sentences like "A handle is part of every door", Stage I takes -place at the end of traverse 2 of the source text and, uniquely, gets the -opportunity to add fresh sentences to the source -- thus extending the -traverse. By the end of Stage I, all kinds are fixed. - -(II) Stages II and III are for adding further properties or relationships, -which aren't explicit in the source text but which plugins can add on the -basis of contextual understanding. (Two stages are provided here to avoid -timing issues where one plugin has to act earlier than another.) - -(III) See (II). If a plugin is going to change the compilation order of -the objects (as the spatial-model plugin does), it must do so during -Stage III. - -(IV) A stage for consistency checks or to store away useful data, but where -nothing in the model may be changed -- no properties or relationships -may be added. (Except that the instance-counting plugin is allowed to -add the linked-lists-of-instances properties, used to optimise loops -at run-time; they aren't visible at the I7 level so aren't properly -part of the model world.) - -(V) A final chance to add properties which will assist the run-time -implementation of, for instance, the command grammar, but again aren't -really part of the model world. (This can't be done earlier since the -command grammar isn't parsed until after |World::complete|; and we -aren't allowed to add I7-accessible properties.) - -The following routine, then, carries out stages II, III and IV. +@d WORLD_STAGE_I 1 /* Deduce kinds for object instances */ +@d WORLD_STAGE_II 2 /* First chance to add further properties or relationships */ +@d WORLD_STAGE_III 3 /* Second chance to add further properties or relationships */ +@d WORLD_STAGE_IV 4 /* Perform mutual consistency checks */ +@d WORLD_STAGE_V 5 /* Post-game: only implementation details can be added */ = -void World::complete(void) { - @; - @; +int current_model_world_stage = 0; /* not yet building the world model */ + +void World::ask_plugins_at_stage(int S) { + if (S != current_model_world_stage + 1) internal_error("Stage mistimed"); + current_model_world_stage = S; + Plugins::Call::complete_model(S); } -@ The model world is a broth with many cooks. On the one hand, we have the -various different INFSs, with their different needs -- a various-to-various -relation, a global variable, and so on -- and on the other hand we also -have the plugins, each of which takes its own global view of the situation. -We give everyone a turn. +int World::current_building_stage(void) { + return current_model_world_stage; +} -@ = +@h Stage I. +Deducing the kind of any object whose kind is not known. The core compiler +has already done the best it can, but then it lacks domain-specific +understanding. So the only business done is by plugins, which understand +certain kinds and relationships better. + +Some instances change their kinds in Stage I, and this can result in further +creations by assembly sentences like "A handle is part of every door". Because +of that, Stage I takes place at the end of traverse 2 of the source text and, +uniquely, gets the opportunity to add fresh sentences to the source -- thus +extending the traverse. But by the end of Stage I, all kinds are fixed, and +no further instances can be created. + += +void World::deduce_object_instance_kinds(void) { + World::ask_plugins_at_stage(WORLD_STAGE_I); +} + +@h Stages II and III. +This is an opportunity for plugins to add further properties or relationships +on the basis of contextual understanding. Two stages, and thus two opportunities, +are provided here to avoid timing issues where one plugin has to act earlier +than another. + +If a plugin is going to change the compilation order of the objects (as the +spatial-model plugin does), it must do so during Stage III, not Stage II. + += +void World::stages_II_and_III(void) { inference_subject *infs; LOOP_OVER(infs, inference_subject) { InferenceSubjects::complete_model(infs); @@ -63,20 +64,25 @@ We give everyone a turn. } LOOP_OVER(infs, inference_subject) Assertions::Implications::consider_all(infs); - Plugins::Call::complete_model(2); - Plugins::Call::complete_model(3); + World::ask_plugins_at_stage(WORLD_STAGE_II); + World::ask_plugins_at_stage(WORLD_STAGE_III); +} -@ Checking what we have, then. Once again each INFS is given an opportunity -to check itself, and then the plugins have a turn. +@h Stage IV. +This is for consistency checks or to store away useful data, but where +nothing in the model may be changed -- no properties or relationships +may be added. -@ = += +void World::stage_IV(void) { inference_subject *infs; LOOP_OVER(infs, inference_subject) { InferenceSubjects::check_model(infs); @; @; } - Plugins::Call::complete_model(4); + World::ask_plugins_at_stage(WORLD_STAGE_IV); +} @ These two checks may seem a little odd. After all, we've been throwing out impossible inferences with problem messages all along, while reading the @@ -101,8 +107,8 @@ A nameless property added in Stages II and III does not need permission. @ = inference *inf; - KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) { - property *prn = World::Inferences::get_property(inf); + KNOWLEDGE_LOOP(inf, infs, property_inf) { + property *prn = PropertyInferences::get_property(inf); if (Wordings::nonempty(prn->name)) if (World::Permissions::find(infs, prn, TRUE) == NULL) StandardProblems::inference_problem(_p_(PM_PropertyNotPermitted), @@ -113,18 +119,19 @@ A nameless property added in Stages II and III does not need permission. } @ The following contradiction checks do not apply to properties added -in Stages II and III, since those are often I6 hacks added for run-time +in Stages II and III, since those are often Inter hacks added for run-time convenience, and don't have to follow the I7 rules. @ = inference *narrow; - KNOWLEDGE_LOOP(narrow, infs, PROPERTY_INF) { - if (World::Inferences::added_in_construction(narrow) == FALSE) { - property *prn = World::Inferences::get_property(narrow); + KNOWLEDGE_LOOP(narrow, infs, property_inf) { + if (Inferences::during_stage(narrow) == 0) { + property *prn = PropertyInferences::get_property(narrow); int sign = 1; - if (World::Inferences::get_certainty(narrow) < 0) sign = -1; + if (Inferences::get_certainty(narrow) < 0) sign = -1; @; - if ((Properties::is_either_or(prn)) && (Properties::EitherOr::get_negation(prn))) { + if ((Properties::is_either_or(prn)) && + (Properties::EitherOr::get_negation(prn))) { prn = Properties::EitherOr::get_negation(prn); sign = -sign; @; @@ -136,9 +143,9 @@ convenience, and don't have to follow the I7 rules. inference_subject *boss = InferenceSubjects::narrowest_broader_subject(infs); while (boss) { inference *wide; - KNOWLEDGE_LOOP(wide, boss, PROPERTY_INF) - if (World::Inferences::added_in_construction(wide) == FALSE) - if (prn == World::Inferences::get_property(wide)) + KNOWLEDGE_LOOP(wide, boss, property_inf) + if (Inferences::during_stage(wide) == 0) + if (prn == PropertyInferences::get_property(wide)) @; boss = InferenceSubjects::narrowest_broader_subject(boss); } @@ -153,13 +160,13 @@ rather than |LIKELY_CE|, and so we can't allow the "narrow" inference, about the Portal, to stand. @ = - int abcw = World::Inferences::get_certainty(wide); if (abcw < 0) abcw = -abcw; + int abcw = Inferences::get_certainty(wide); if (abcw < 0) abcw = -abcw; if (abcw == CERTAIN_CE) { int clash = FALSE; - int wide_sign = 1; if (World::Inferences::get_certainty(wide) < 0) wide_sign = -1; + int wide_sign = 1; if (Inferences::get_certainty(wide) < 0) wide_sign = -1; if (Properties::is_either_or(prn) == FALSE) { - parse_node *narrow_val = World::Inferences::get_property_value(narrow); - parse_node *wide_val = World::Inferences::get_property_value(wide); + parse_node *narrow_val = PropertyInferences::get_value(narrow); + parse_node *wide_val = PropertyInferences::get_value(wide); if (Rvalues::compare_CONSTANT(narrow_val, wide_val) == FALSE) { LOG("Clash of $P and $P\n $I\n $I\n", narrow_val, wide_val, narrow, wide); @@ -168,11 +175,11 @@ about the Portal, to stand. } if (sign != wide_sign) clash = (clash)?FALSE:TRUE; if (clash) { - int abcn = World::Inferences::get_certainty(narrow); if (abcn < 0) abcn = -abcn; + int abcn = Inferences::get_certainty(narrow); if (abcn < 0) abcn = -abcn; if (abcn == CERTAIN_CE) @ else - World::Inferences::set_certainty(narrow, IMPOSSIBLE_CE); + Inferences::set_certainty(narrow, IMPOSSIBLE_CE); } } @@ -180,15 +187,21 @@ about the Portal, to stand. LOG("Checking infs $j compatible with infs $j for property $Y:\n $I\n $I\n", infs, boss, prn, narrow, wide); StandardProblems::infs_contradiction_problem(_p_(PM_InstanceContradiction), - World::Inferences::where_inferred(narrow), World::Inferences::where_inferred(wide), infs, + Inferences::where_inferred(narrow), Inferences::where_inferred(wide), infs, "therefore has to have two contradictory states of the same property at once", "which is impossible. When a kind's definition says that something is 'always' " "true, there is no way to override that for particular things of the kind."); @h Stage V. -See above. This is for the use of plugins only. +A final chance to add properties which may assist the run-time implementation +of whatever a plugin is concerned with, but which is not allowed to make +changes to the model as it would be understood by the author. + +For example, the //runtime: Instance Counting// plugin adds low-level properties +to improve run-time performance, but they have no names and cannot be referred +to or accessed by code written in Inform 7; they exist at the level of Inter only. = -void World::complete_additions(void) { - Plugins::Call::complete_model(5); +void World::stage_V(void) { + World::ask_plugins_at_stage(WORLD_STAGE_V); } diff --git a/inform7/knowledge-module/Contents.w b/inform7/knowledge-module/Contents.w index 34a25e27a..04aaa72d9 100644 --- a/inform7/knowledge-module/Contents.w +++ b/inform7/knowledge-module/Contents.w @@ -40,9 +40,9 @@ Chapter 4: Subjects Kind Subjects Relation Subjects -Chapter 5: Model +Chapter 5: Modelling Inferences + Property Inferences + Relation Inferences Property Permissions - Complete Model World - Compile Model World - Instance Counting + The Model World diff --git a/inform7/knowledge-module/Preliminaries/What This Module Does.w b/inform7/knowledge-module/Preliminaries/What This Module Does.w index 8729e39f6..9aee937e0 100644 --- a/inform7/knowledge-module/Preliminaries/What This Module Does.w +++ b/inform7/knowledge-module/Preliminaries/What This Module Does.w @@ -64,12 +64,6 @@ type is called //inference_subject//. Each subject has its own list of known facts: we call such a fact an //inference// because it has (usually) been inferred from a proposition. -//Chapter 2// gives a general API for dealing with //Inference Subjects//, -and then works systematically through the various categories of these. -Kinds and binary predicates already exist from other modules (see -//kinds: Chapter 2: Kinds// and //calculus: Chapter 3: Binary Predicates// -respectively), but //Instances// and //Nonlocal Variables// are new. - //Chapter 3// implements our system of properties: each different value or either-or property is a //property// object. There might be a puritan case for abolishing this type in favour of regarding either-or properties @@ -77,4 +71,12 @@ as special cases of |unary_predicate| and value properties as special cases of |binary_predicate| (by identifying a predicate with its setting relation), but I do not think this would clarify anything. -Finally, //Chapter 4// builds the actual model. +//Chapter 4// gives a general API for dealing with //Inference Subjects//, +and then works systematically through the various categories of these. +Kinds and binary predicates already exist from other modules (see +//kinds: Chapter 2: Kinds// and //calculus: Chapter 3: Binary Predicates// +respectively), but //Instances// and //Nonlocal Variables// are new. + +Finally, //Chapter 5// deals with the actual inferences, and with how the +model world is constructed. The core of Inform does nothing very interesting +here, but plugins from the //if// module add some domain-specific savvy. diff --git a/inform7/knowledge-module/Chapter 5/Instance Counting.w b/inform7/runtime-module/Chapter 4/Instance Counting.w similarity index 99% rename from inform7/knowledge-module/Chapter 5/Instance Counting.w rename to inform7/runtime-module/Chapter 4/Instance Counting.w index 31134986b..620fe1b09 100644 --- a/inform7/knowledge-module/Chapter 5/Instance Counting.w +++ b/inform7/runtime-module/Chapter 4/Instance Counting.w @@ -239,10 +239,10 @@ of model completion: = int PL::Counting::counting_complete_model(int stage) { - if (stage == 1) { + if (stage == WORLD_STAGE_I) { @; } - if (stage == 4) { + if (stage == WORLD_STAGE_V) { @; PL::Counting::make_instance_counts(); @; diff --git a/inform7/runtime-module/Chapter 4/Plugin Calls.w b/inform7/runtime-module/Chapter 4/Plugin Calls.w index a957d35eb..5c9381979 100644 --- a/inform7/runtime-module/Chapter 4/Plugin Calls.w +++ b/inform7/runtime-module/Chapter 4/Plugin Calls.w @@ -9,6 +9,7 @@ To place calls to the plugins. @d PLUGIN_NEW_VARIABLE_NOTIFY 1 @d PLUGIN_IRREGULAR_GENITIVE 4 @d PLUGIN_SET_KIND_NOTIFY 6 +@d PLUGIN_CREATE_INFERENCE_FAMILIES 10 @d PLUGIN_COMPLETE_MODEL 11 @d PLUGIN_PARSE_COMPOSITE_NQS 12 @d PLUGIN_REFINE_IMPLICIT_NOUN 14 @@ -154,8 +155,12 @@ int Plugins::Call::set_subkind_notify(kind *sub, kind *super) { PLUGINS_CALL(PLUGIN_SET_SUBKIND_NOTIFY, sub, super); } +int Plugins::Call::create_inference_families(void) { + PLUGINS_CALLV(PLUGIN_CREATE_INFERENCE_FAMILIES); +} + int Plugins::Call::complete_model(int stage) { - World::Inferences::diversion_off(); + Inferences::diversion_off(); PLUGINS_CALL(PLUGIN_COMPLETE_MODEL, stage); } diff --git a/inform7/runtime-module/Chapter 4/Relations at Run Time.w b/inform7/runtime-module/Chapter 4/Relations at Run Time.w index 48a80f48b..b8ffb9766 100644 --- a/inform7/runtime-module/Chapter 4/Relations at Run Time.w +++ b/inform7/runtime-module/Chapter 4/Relations at Run Time.w @@ -1210,9 +1210,9 @@ to send the pairs in that row in any order. @ = inference *inf; - POSITIVE_KNOWLEDGE_LOOP(inf, World::Inferences::bp_as_subject(bp), ARBITRARY_RELATION_INF) { + POSITIVE_KNOWLEDGE_LOOP(inf, Inferences::bp_as_subject(bp), arbitrary_relation_inf) { inference_subject *left_infs, *right_infs; - World::Inferences::get_references(inf, &left_infs, &right_infs); + Inferences::get_references(inf, &left_infs, &right_infs); if (infs == left_infs) row_flags[RTRelations::get_relation_index(right_infs, 1)] = 1; } @@ -1868,9 +1868,9 @@ void RTRelations::emit_one(inference_subject_family *f, inference_subject *infs) packaging_state save = Routines::begin(RTRelations::initialiser_iname(bp)); inference *i; inter_name *rtiname = Hierarchy::find(RELATIONTEST_HL); - POSITIVE_KNOWLEDGE_LOOP(i, World::Inferences::bp_as_subject(bp), ARBITRARY_RELATION_INF) { + POSITIVE_KNOWLEDGE_LOOP(i, Inferences::bp_as_subject(bp), arbitrary_relation_inf) { parse_node *spec0, *spec1; - World::Inferences::get_references_spec(i, &spec0, &spec1); + Inferences::get_references_spec(i, &spec0, &spec1); RTRelations::mark_as_needed(bp); Produce::inv_call_iname(Emit::tree(), rtiname); Produce::down(Emit::tree()); diff --git a/inform7/runtime-module/Contents.w b/inform7/runtime-module/Contents.w index c48a434e8..6d3483a5b 100644 --- a/inform7/runtime-module/Contents.w +++ b/inform7/runtime-module/Contents.w @@ -47,6 +47,7 @@ Chapter 4: Compilation Utilities Temporary Variables Variables Instances + Instance Counting Adjectives Runtime Support for Kinds Extension Files at Run Time