From 8531afdb4d07f2e43f9e48f57c1583e914b4a2d1 Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Tue, 23 Feb 2021 00:25:10 +0000 Subject: [PATCH] Improved separation of plugins from main compiler --- README.md | 2 +- build.txt | 4 +- docs/building-module/2-eis.html | 3 - docs/codegen-module/2-res.html | 5 +- docs/core-module/1-cm.html | 20 ++--- docs/core-module/1-htc.html | 74 ++++++---------- docs/core-module/1-wtc.html | 4 +- docs/core-module/3-pc.html | 15 +++- docs/core-module/3-pm.html | 64 ++++++++------ docs/if-module/1-im.html | 69 ++++++++------- docs/if-module/2-bd.html | 2 +- docs/if-module/2-ri.html | 2 +- docs/if-module/3-bck.html | 7 +- docs/if-module/3-dvc.html | 2 +- docs/if-module/3-enah.html | 2 +- docs/if-module/3-mcr.html | 2 +- docs/if-module/3-prs.html | 2 +- docs/if-module/3-rgn.html | 9 +- docs/if-module/3-sc.html | 2 +- docs/if-module/3-scn.html | 20 +++-- docs/if-module/3-sm.html | 2 +- docs/if-module/3-sr.html | 2 +- docs/if-module/3-tm.html | 20 +++-- docs/if-module/3-tp.html | 2 +- docs/if-module/3-ts.html | 7 +- docs/if-module/4-act.html | 35 +++++--- docs/if-module/4-anl.html | 2 +- docs/if-module/4-ap.html | 4 +- docs/if-module/4-nap.html | 2 +- docs/if-module/5-gl.html | 41 ++++----- docs/if-module/5-gp.html | 32 ++++++- docs/if-module/5-gpr.html | 34 ++++---- docs/if-module/5-gv.html | 28 +++--- docs/if-module/5-nft.html | 2 +- docs/if-module/5-tpv.html | 8 +- docs/imperative-module/4-chr.html | 86 +++++++++++-------- docs/multimedia-module/1-mm.html | 15 ++-- docs/runtime-module/1-rm.html | 32 ++++++- docs/runtime-module/4-ic.html | 3 +- docs/runtime-module/5-bd.html | 8 +- docs/runtime-module/5-ef.html | 3 +- docs/runtime-module/5-fgr.html | 3 +- docs/runtime-module/5-se.html | 3 +- docs/supervisor-module/5-ps2.html | 3 +- .../Chapter 5/Project Services.w | 3 +- inform7/Figures/memory-diagnostics.txt | 32 +++---- inform7/Figures/timings-diagnostics.txt | 34 ++++---- inform7/core-module/Chapter 1/Core Module.w | 14 +-- .../core-module/Chapter 1/How To Compile.w | 72 +++++----------- inform7/core-module/Chapter 3/Plugin Calls.w | 12 ++- .../core-module/Chapter 3/Plugin Manager.w | 42 ++++++--- inform7/if-module/Chapter 1/IF Module.w | 15 +++- inform7/if-module/Chapter 3/Backdrops.w | 5 +- inform7/if-module/Chapter 3/Regions.w | 5 +- inform7/if-module/Chapter 3/Scenes.w | 8 ++ inform7/if-module/Chapter 3/The Map.w | 10 ++- inform7/if-module/Chapter 3/The Score.w | 5 +- inform7/if-module/Chapter 4/Actions.w | 11 +++ inform7/if-module/Chapter 5/Grammar Lines.w | 1 + .../if-module/Chapter 5/Grammar Properties.w | 30 +++++++ .../imperative-module/Chapter 4/Chronology.w | 78 ++++++++++------- .../Chapter 1/Multimedia Module.w | 13 ++- .../runtime-module/Chapter 1/Runtime Module.w | 32 ++++++- .../Chapter 4/Instance Counting.w | 3 +- .../Chapter 5/Bibliographic Data.w | 4 +- .../runtime-module/Chapter 5/External Files.w | 3 +- inform7/runtime-module/Chapter 5/Figures.w | 3 +- .../runtime-module/Chapter 5/Sound Effects.w | 3 +- .../Chapter 2/Emitting Inter Schemas.w | 3 - .../Chapter 2/Resolve External Symbols.w | 5 +- 70 files changed, 680 insertions(+), 453 deletions(-) diff --git a/README.md b/README.md index f1aa591de..a748be9c2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -v10.1.0-alpha.1+6R31 'Krypton' (21 February 2021) +v10.1.0-alpha.1+6R32 'Krypton' (23 February 2021) ## About Inform 7 diff --git a/build.txt b/build.txt index 3d6eccf3e..b6da3fd4b 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: alpha.1 -Build Date: 21 February 2021 -Build Number: 6R31 +Build Date: 23 February 2021 +Build Number: 6R32 diff --git a/docs/building-module/2-eis.html b/docs/building-module/2-eis.html index a5d778c97..304887001 100644 --- a/docs/building-module/2-eis.html +++ b/docs/building-module/2-eis.html @@ -518,9 +518,6 @@ function togglePopup(material_id) { #endif #ifndef CORE_MODULE Produce::val_symbol(I, K_value, Site::veneer_symbol(I, OBJECT_VSYMB)); - inter_symbol *plug = Inter::Connectors::find_plug(I, I"Object"); - if (plug == NULL) plug = Inter::Connectors::plug(I, I"Object"); - Produce::val_symbol(I, K_value, plug); #endif } else internal_error("objectloop without visible variable"); } diff --git a/docs/codegen-module/2-res.html b/docs/codegen-module/2-res.html index 0e90b94eb..efabc40d6 100644 --- a/docs/codegen-module/2-res.html +++ b/docs/codegen-module/2-res.html @@ -110,7 +110,10 @@ function togglePopup(material_id) { if (!Inter::Symbols::is_defined(D)) { if (Inter::Symbols::get_scope(D) != PLUG_ISYMS) { LOG("$3 == $3 which is undefined\n", S, D); - WRITE_TO(STDERR, "Failed to resolve symbol: %S\n", D->symbol_name); + WRITE_TO(STDERR, "Failed to resolve symbol: %S = %S (in ", + S->symbol_name, D->symbol_name); + Inter::Packages::write_url_name(STDERR, Q); + WRITE_TO(STDERR, ")\n"); if (fail_flag) *fail_flag = TRUE; } } diff --git a/docs/core-module/1-cm.html b/docs/core-module/1-cm.html index 6001bb70e..3c80302b6 100644 --- a/docs/core-module/1-cm.html +++ b/docs/core-module/1-cm.html @@ -77,30 +77,30 @@ function togglePopup(material_id) {
define CORE_MODULE TRUE
 
-

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

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

+ +

Note that the "core" plugin itself does nothihg except to be a parent to the +other two; it doesn't even have an activation function.

+plugin *core_plugin, *naming_plugin, *counting_plugin;
+
 void CoreModule::start(void) {
     core_plugin = PluginManager::new(NULL, I"core", NULL);
+    PluginManager::make_permanently_active(core_plugin);
     naming_plugin = PluginManager::new(&PL::Naming::start, I"naming", core_plugin);
     counting_plugin = PluginManager::new(&PL::Counting::start, I"instance counting", core_plugin);
 
-    Writers::register_writer_I('B', &CoreModule::writer);
+    Writers::register_writer_I('B', &CoreModule::writer);
     CorePreform::set_core_internal_NTIs();
     CoreSyntax::declare_annotations();
 }
 void CoreModule::end(void) {
 }
 
-

§3. The main part of Inform contains only three plugins, and one of those ("core") -is compulsory anyway: -

- -
-plugin *core_plugin, *naming_plugin, *counting_plugin;
-
-

§4. The %B string escape prints the build number, lying about it when we +

§3. The %B string escape prints the build number, lying about it when we want to produce predictable output for easier testing.

diff --git a/docs/core-module/1-htc.html b/docs/core-module/1-htc.html index 45a277e20..2d8cfd0a7 100644 --- a/docs/core-module/1-htc.html +++ b/docs/core-module/1-htc.html @@ -158,23 +158,6 @@ as possible. if (cs > 0) LOG(".... " #routine "() took %dcs\n", cs); } } -define BENCH_IF(plugin, routine) { - if ((problem_count == 0) && (PluginManager::active(plugin))) { - TEMPORARY_TEXT(name) - WRITE_TO(name, "//"); - WRITE_TO(name, #routine); - WRITE_TO(name, "//"); - for (int i=0; i<Str::len(name)-1; i++) - if ((Str::get_at(name, i) == '_') && (Str::get_at(name, i+1) == '_')) { - Str::put_at(name, i, ':'); Str::put_at(name, i+1, ':'); - } - stopwatch_timer *st = Time::start_stopwatch(sequence_timer, name); - DISCARD_TEXT(name) - routine(); - int cs = Time::stop_stopwatch(st); - if (cs > 0) LOG(".... " #routine "() took %dcs\n", cs); - } -}

§2.2. Here, then, are the steps in the production line, presented without commentary. For what they do, see the relevant sections. Note that although @@ -281,7 +264,10 @@ so on. Those absolute basics are made here. BENCH(RTKinds::compile_instance_counts)

-

§2.8. Generate inter2.8 = +

§2.8. This proceeds in stages. +

+ +

Generate inter2.8 =

@@ -290,7 +276,6 @@ so on. Those absolute basics are made here.
     BENCH(FundamentalConstants::emit_build_number)
     BENCH(RTExtensions::ShowExtensionVersions_routine)
     BENCH(Kinds::Constructors::emit_constants)
-    BENCH_IF(scoring_plugin, PL::Score::compile_max_score)
     BENCH(RTUseOptions::TestUseOption_routine)
     BENCH(Activities::compile_activity_constants)
     BENCH(Activities::Activity_before_rulebooks_array)
@@ -300,47 +285,30 @@ 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(RuntimeModule::compile_runtime_data)
+    if (debugging) {
+        BENCH(RuntimeModule::compile_debugging_runtime_data_1)
+    } else {
+        BENCH(RuntimeModule::compile_runtime_data_1)
+    }
     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)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::General::write_parse_name_routines)
-    BENCH_IF(regions_plugin, PL::Regions::write_regional_found_in_routines)
     BENCH(Tables::complete)
     BENCH(RTTables::compile)
     BENCH(RTEquations::compile_identifiers)
-    BENCH_IF(actions_plugin, PL::Actions::Patterns::Named::compile)
-    BENCH_IF(actions_plugin, PL::Actions::ActionData)
-    BENCH_IF(actions_plugin, PL::Actions::ActionCoding_array)
-    BENCH_IF(actions_plugin, PL::Actions::ActionHappened)
-    BENCH_IF(actions_plugin, PL::Actions::compile_action_routines)
-    BENCH_IF(parsing_plugin, PL::Parsing::Lines::MistakeActionSub_routine)
     BENCH(Phrases::Manager::compile_first_block)
     BENCH(Phrases::Manager::compile_rulebooks)
     BENCH(Phrases::Manager::rulebooks_array)
-    BENCH_IF(scenes_plugin, PL::Scenes::DetectSceneChange_routine)
-    BENCH_IF(scenes_plugin, PL::Scenes::ShowSceneStatus_routine)
     BENCH(Rulebooks::rulebook_var_creators)
     BENCH(Activities::activity_var_creators)
     BENCH(RTRelations::IterateRelations)
     BENCH(Phrases::Manager::RulebookNames_array)
     BENCH(Phrases::Manager::RulePrintingRule_routine)
-    BENCH_IF(parsing_plugin, PL::Parsing::Verbs::prepare)
-    BENCH_IF(parsing_plugin, PL::Parsing::Verbs::compile_conditions)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::Values::number)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::Values::truth_state)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::Values::time)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::Values::compile_type_gprs)
     BENCH(RTVerbs::ConjugateVerb)
     BENCH(RTAdjectives::agreements)
-
     if (debugging) {
-        BENCH_IF(parsing_plugin, PL::Parsing::TestScripts::write_text)
-        BENCH_IF(parsing_plugin, PL::Parsing::TestScripts::TestScriptSub_routine)
+        BENCH(RuntimeModule::compile_debugging_runtime_data_2)
         BENCH(InternalTests::InternalTestCases_routine)
     } else {
-        BENCH_IF(parsing_plugin, PL::Parsing::TestScripts::TestScriptSub_stub_routine)
+        BENCH(RuntimeModule::compile_runtime_data_2)
     }
 
     BENCH(Lists::check)
@@ -353,13 +321,18 @@ so on. Those absolute basics are made here.
     BENCH(RTRelations::compile_defined_relations)
     BENCH(Phrases::Manager::compile_as_needed)
     BENCH(Strings::TextSubstitutions::allow_no_further_text_subs)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::Filters::compile)
-    BENCH_IF(actions_plugin, Chronology::past_actions_i6_routines)
-    BENCH_IF(chronology_plugin, Chronology::chronology_extents_i6_escape)
-    BENCH_IF(chronology_plugin, Chronology::past_tenses_i6_escape)
-    BENCH_IF(chronology_plugin, Chronology::allow_no_further_past_tenses)
-    BENCH_IF(parsing_plugin, PL::Parsing::Verbs::compile_all)
-    BENCH_IF(parsing_plugin, PL::Parsing::Tokens::Filters::compile)
+    if (debugging) {
+        BENCH(RuntimeModule::compile_debugging_runtime_data_3)
+    } else {
+        BENCH(RuntimeModule::compile_runtime_data_3)
+    }
+    BENCH(Chronology::past_actions_i6_routines)
+    BENCH(Chronology::compile_runtime)
+    if (debugging) {
+        BENCH(RuntimeModule::compile_debugging_runtime_data_4)
+    } else {
+        BENCH(RuntimeModule::compile_runtime_data_4)
+    }
     BENCH(RTMeasurements::compile_test_functions)
     BENCH(Propositions::Deferred::compile_remaining_deferred)
     BENCH(Calculus::Deferrals::allow_no_further_deferrals)
@@ -377,6 +350,7 @@ so on. Those absolute basics are made here.
     BENCH(Phrases::Timed::TimedEventTimesTable)
     BENCH(PL::Naming::compile_cap_short_name)
     BENCH(RTUseOptions::configure_template)
+    BENCH(RTBibliographicData::IFID_text);
 

§2.9. Generate index and bibliographic file2.9 = diff --git a/docs/core-module/1-wtc.html b/docs/core-module/1-wtc.html index 9a0a2c8d4..4ee15b25a 100644 --- a/docs/core-module/1-wtc.html +++ b/docs/core-module/1-wtc.html @@ -142,7 +142,7 @@ thing which is being compiled when it is. Index::DocReferences::read_xrefs(); Task::issue_problems_arising(project->as_copy->vertex); - PluginManager::start_plugins(); + PluginManager::start_plugins(); if (problem_count > 0) return FALSE; @@ -237,7 +237,7 @@ rough stages. Twenty is plenty. return inform7_task->project->as_copy->edition; } -parse_node_tree *Task::syntax_tree(void) { +parse_node_tree *Task::syntax_tree(void) { return latest_syntax_tree; } diff --git a/docs/core-module/3-pc.html b/docs/core-module/3-pc.html index 78c941b50..4aba8f672 100644 --- a/docs/core-module/3-pc.html +++ b/docs/core-module/3-pc.html @@ -77,7 +77,7 @@ function togglePopup(material_id) {

§1. The following set of functions is an API for the main compiler to consult with the plugins; put another way, it is also an API for the plugins to influence the main compiler. They do so by adding plugs to the relevant rulebooks: -see PluginManager::plug. +see PluginManager::plug.

Nothing can prevent this from being a big old miscellany, so we take them by @@ -439,14 +439,21 @@ regions plugin does with the "region" kind.

§28. Influencing runtime. Called from Runtime Module (in runtime). This tells a plugin to compile any static data it will need. For example, the mapping plugin compiles an array to -hold the map. +hold the map. debugging is TRUE if this is a debugging run, and allows +a plugin to generate diagnostic features. +

+ +

There are two stages of this, happening earlier and later in the process of +emitting Inter code, because this allows for timing issues to be taken care of. +That is, if a plugin wants to generate code which might depend on something +another plugin did earlier, it should wait until round two.

enum COMPILE_RUNTIME_DATA_PLUG
 
-int PluginCalls::compile_runtime_data(void) {
-    PLUGINS_CALLV(COMPILE_RUNTIME_DATA_PLUG);
+int PluginCalls::compile_runtime_data(int stage, int debugging) {
+    PLUGINS_CALL(COMPILE_RUNTIME_DATA_PLUG, stage, debugging);
 }
 

§29. Influencing if. Called from Action Patterns (in if) to validate optional parameters on the diff --git a/docs/core-module/3-pm.html b/docs/core-module/3-pm.html index d3e490e6b..f98ef9d08 100644 --- a/docs/core-module/3-pm.html +++ b/docs/core-module/3-pm.html @@ -97,6 +97,7 @@ author can create in source text; we know exactly how many there are. struct plugin *parent_plugin; void (*activation_function)(void); int active; + int permanently_active; CLASS_DEFINITION } plugin; @@ -117,7 +118,7 @@ the compiler at all.

-int PluginManager::active(plugin *P) {
+int PluginManager::active(plugin *P) {
     return P->active;
 }
 
@@ -135,59 +136,72 @@ the compiler at all.
 }
 

§3. In the code above, plugins are set up as inactive by default — even "core", -which the compiler absolutely cannot live without. See Project Services (in supervisor) -for how the set of active plugins for a compilation is determined in practice; -note, in particularly, that it wisely chooses to activate the core. +which the compiler absolutely cannot live without. So Project Services (in supervisor) +calls the following before switching on optional things that it wants.

-

Most plugins are subordinate to a parent plugin: for example, a dozen more +

+void PluginManager::activate_bare_minimum(void) {
+    plugin *P;
+    LOOP_OVER(P, plugin)
+        if ((P->permanently_active) && (P->active == FALSE))
+            PluginManager::activate(P);
+}
+
+void PluginManager::make_permanently_active(plugin *P) {
+    if (P == NULL) internal_error("no plugin");
+    P->permanently_active = TRUE;
+}
+
+

§4. Most plugins are subordinate to a parent plugin: for example, a dozen more specific IF-related plugins are subordinate to the "interactive fiction" one. Activating or deactivating a parent like that automatically activates or deactivates its children.

-void PluginManager::activate(plugin *P) {
+void PluginManager::activate(plugin *P) {
     if (P) {
         P->active = TRUE;
         plugin *Q;
         LOOP_OVER(Q, plugin)
             if (Q->parent_plugin == P)
-                Q->active = TRUE;
+                PluginManager::activate(Q);
     }
 }
 
 void PluginManager::deactivate(plugin *P) {
     if (P) {
-        P->active = FALSE;
+        if (P->permanently_active)
+            Issue problem for trying to remove the core4.1
+        else
+            P->active = FALSE;
         plugin *Q;
         LOOP_OVER(Q, plugin)
-            if (Q->parent_plugin == P) {
-                if (Q == core_plugin)
-                    Issue problem for trying to remove the core3.1
-                else Q->active = FALSE;
-        }
+            if (Q->parent_plugin == P)
+                PluginManager::deactivate(Q);
     }
 }
 
-

§3.1. Issue problem for trying to remove the core3.1 = +

§4.1. Issue problem for trying to remove the core4.1 =

-    StandardProblems::sentence_problem(Task::syntax_tree(), _p_(Untestable),
-        "the core of the Inform language cannot be removed",
-        "because then what should we do? What should we ever do?");
+    if (problem_count == 0)
+        StandardProblems::sentence_problem(Task::syntax_tree(), _p_(Untestable),
+            "the core of the Inform language cannot be removed",
+            "because then what should we do? What should we ever do?");
     return;
 
- -

§4. Every active plugin gets to run its start function, if it provides one. +

+

§5. Every active plugin gets to run its start function, if it provides one.

It's kind of incredible that C's grammar for round brackets is unambiguous.

-void PluginManager::start_plugins(void) {
+void PluginManager::start_plugins(void) {
     plugin *P;
     LOOP_OVER(P, plugin)
         if (P->active) {
@@ -196,7 +210,7 @@ or deactivates its children.
         }
 }
 
-

§5. The names of the great plugins are hard-wired into the compiler rather +

§6. The names of the great plugins are hard-wired into the compiler rather than being stored in Preform grammar, and they therefore cannot be translated out of English. But this is intentional, for now at least. Authors are not intended to be aware of plugins; it is really kits of Inter code which choose @@ -224,7 +238,7 @@ Preform nonterminal to parse them, and here it is. }

-

§6. It's convenient also to provide: +

§7. It's convenient also to provide:

@@ -236,7 +250,7 @@ Preform nonterminal to parse them, and here it is.
     return NULL;
 }
 
-

§7. Plugins affect the running of the compiler by inserting functions called plugs +

§8. Plugins affect the running of the compiler by inserting functions called plugs into the following "plugin rulebooks" — there's a mixed metaphor here, but the idea is that they behave like Inform rulebooks. When a rulebook is called, the compiler works through each plug until one of them returns something other @@ -244,7 +258,7 @@ than FALSE.

Plugins should add plugs in their activation functions, by calling -PluginManager::plug, which has an interestingly vague type. The next +PluginManager::plug, which has an interestingly vague type. The next screenful of code looks like something of a workout for the C typechecker, but it compiles under clang without even the -Wpedantic warning, and honestly you're barely living as a C programmer if you never generate that one. @@ -264,7 +278,7 @@ you're barely living as a C programmer if you never generate that one. ADD_TO_LINKED_LIST(vR, void, plugin_rulebooks[code]); } -

§8. The functions in Plugin Calls then make use of these macros, which are +

§9. The functions in Plugin Calls then make use of these macros, which are the easiest way to persuade the C typechecker to allow variable arguments to be passed in a portable way. Similarly, there are two macros not one because C does not allow a void variable argument list. diff --git a/docs/if-module/1-im.html b/docs/if-module/1-im.html index 237eb35b9..def27f543 100644 --- a/docs/if-module/1-im.html +++ b/docs/if-module/1-im.html @@ -64,7 +64,7 @@

Setting up the use of this module.

-
+

§1. This section simoly sets up the module in ways expected by foundation, and contains no code of interest. The following constant exists only in tools @@ -154,17 +154,24 @@ which use this module: DECLARE_CLASS_ALLOCATED_IN_ARRAYS(understanding_item, 100) DECLARE_CLASS_ALLOCATED_IN_ARRAYS(understanding_reference, 100) -

§3. Plugins.

+

§3. Plugins. Note that the "if" plugin itself does nothihg except to be a parent +to all these others; it doesn't even have an activation function. +

-plugin *if_plugin, *parsing_plugin, *actions_plugin,
+plugin *if_plugin,
     *spatial_plugin, *map_plugin, *persons_plugin,
     *player_plugin, *regions_plugin, *backdrops_plugin,
     *devices_plugin, *showme_plugin,
     *times_plugin, *scenes_plugin, *scoring_plugin,
-    *bibliographic_plugin, *chronology_plugin;
+    *bibliographic_plugin;
 
-

§4. The beginning. (The client doesn't need to call the start and end routines, because the +

§4.

+ +
+    plugin *parsing_plugin, *chronology_plugin, *actions_plugin;
+
+

§5. The beginning. (The client doesn't need to call the start and end routines, because the foundation module does that automatically.)

@@ -176,9 +183,9 @@ foundation module does that automatically.) COMPILE_WRITER(action_name *, PL::Actions::log) void IFModule::start(void) { - Create this module's plugins4.1; - Register this module's debugging log aspects4.3; - Register this module's debugging log writers4.4; + Create this module's plugins5.1; + Register this module's debugging log aspects5.3; + Register this module's debugging log writers5.4; ReleaseInstructions::start(); WherePredicates::start(); PL::SpatialRelations::start(); @@ -187,7 +194,7 @@ foundation module does that automatically.) void IFModule::end(void) { } -

§4.1. Create this module's plugins4.1 = +

§5.1. Create this module's plugins5.1 =

@@ -206,10 +213,10 @@ foundation module does that automatically.)
     times_plugin = PluginManager::new(TimesOfDay::start, I"times of day", if_plugin);
     scenes_plugin = PluginManager::new(&PL::Scenes::start, I"scenes", if_plugin);
     bibliographic_plugin = PluginManager::new(&BibliographicData::start, I"bibliographic data", if_plugin);
-    chronology_plugin = PluginManager::new(NULL, I"chronology", if_plugin);
+    chronology_plugin = PluginManager::new(&Chronology::start_plugin, I"chronology", if_plugin);
 
- -

§4.2.

+ +

§5.2.

enum ACTION_CREATIONS_DA
 enum ACTION_PATTERN_COMPILATION_DA
@@ -220,7 +227,7 @@ foundation module does that automatically.)
 enum SPATIAL_MAP_DA
 enum SPATIAL_MAP_WORKINGS_DA
 
-

§4.3. Register this module's debugging log aspects4.3 = +

§5.3. Register this module's debugging log aspects5.3 =

@@ -233,8 +240,8 @@ foundation module does that automatically.)
     Log::declare_aspect(SPATIAL_MAP_DA, L"spatial map", FALSE, FALSE);
     Log::declare_aspect(SPATIAL_MAP_WORKINGS_DA, L"spatial map workings", FALSE, FALSE);
 
- -

§4.4. Register this module's debugging log writers4.4 = +

+

§5.4. Register this module's debugging log writers5.4 =

@@ -244,8 +251,8 @@ foundation module does that automatically.)
     REGISTER_WRITER('L', PL::Actions::ConstantLists::log);
     REGISTER_WRITER('l', PL::Actions::log);
 
- -

§5. This module uses syntax, and adds two node types to the syntax tree: +

+

§6. This module uses syntax, and adds two node types to the syntax tree:

enum ACTION_NT   "taking something closed"
@@ -257,7 +264,7 @@ foundation module does that automatically.)
     NodeType::new(TOKEN_NT, I"TOKEN_NT",   0, INFTY, L3_NCAT, 0);
 }
 
-

§6. And these annotations to the syntax tree: +

§7. And these annotations to the syntax tree:

enum action_meaning_ANNOT  action_pattern: meaning in parse tree when used as noun
@@ -280,7 +287,7 @@ foundation module does that automatically.)
 DECLARE_ANNOTATION_FUNCTIONS(constant_named_action_pattern, named_action_pattern)
 DECLARE_ANNOTATION_FUNCTIONS(constant_scene, scene)
 
-

§7.

+

§8.

 MAKE_ANNOTATION_FUNCTIONS(action_meaning, action_pattern)
@@ -290,21 +297,21 @@ foundation module does that automatically.)
 MAKE_ANNOTATION_FUNCTIONS(constant_named_action_pattern, named_action_pattern)
 MAKE_ANNOTATION_FUNCTIONS(constant_scene, scene)
 
-

§8.

+

§9.

 void IFModule::declare_annotations(void) {
-    Annotations::declare_type(action_meaning_ANNOT, IFModule::write_action_meaning_ANNOT);
-    Annotations::declare_type(constant_action_name_ANNOT, IFModule::write_constant_action_name_ANNOT);
-    Annotations::declare_type(constant_action_pattern_ANNOT, IFModule::write_constant_action_pattern_ANNOT);
-    Annotations::declare_type(constant_grammar_verb_ANNOT, IFModule::write_constant_grammar_verb_ANNOT);
-    Annotations::declare_type(constant_named_action_pattern_ANNOT, IFModule::write_constant_named_action_pattern_ANNOT);
-    Annotations::declare_type(constant_scene_ANNOT, IFModule::write_constant_scene_ANNOT);
-    Annotations::declare_type(grammar_token_literal_ANNOT, IFModule::write_grammar_token_literal_ANNOT);
-    Annotations::declare_type(grammar_token_relation_ANNOT, IFModule::write_grammar_token_relation_ANNOT);
-    Annotations::declare_type(grammar_value_ANNOT, IFModule::write_grammar_value_ANNOT);
-    Annotations::declare_type(slash_class_ANNOT, IFModule::write_slash_class_ANNOT);
-    Annotations::declare_type(slash_dash_dash_ANNOT, IFModule::write_slash_dash_dash_ANNOT);
+    Annotations::declare_type(action_meaning_ANNOT, IFModule::write_action_meaning_ANNOT);
+    Annotations::declare_type(constant_action_name_ANNOT, IFModule::write_constant_action_name_ANNOT);
+    Annotations::declare_type(constant_action_pattern_ANNOT, IFModule::write_constant_action_pattern_ANNOT);
+    Annotations::declare_type(constant_grammar_verb_ANNOT, IFModule::write_constant_grammar_verb_ANNOT);
+    Annotations::declare_type(constant_named_action_pattern_ANNOT, IFModule::write_constant_named_action_pattern_ANNOT);
+    Annotations::declare_type(constant_scene_ANNOT, IFModule::write_constant_scene_ANNOT);
+    Annotations::declare_type(grammar_token_literal_ANNOT, IFModule::write_grammar_token_literal_ANNOT);
+    Annotations::declare_type(grammar_token_relation_ANNOT, IFModule::write_grammar_token_relation_ANNOT);
+    Annotations::declare_type(grammar_value_ANNOT, IFModule::write_grammar_value_ANNOT);
+    Annotations::declare_type(slash_class_ANNOT, IFModule::write_slash_class_ANNOT);
+    Annotations::declare_type(slash_dash_dash_ANNOT, IFModule::write_slash_dash_dash_ANNOT);
 }
 void IFModule::write_action_meaning_ANNOT(text_stream *OUT, parse_node *p) {
     if (Node::get_action_meaning(p)) {
diff --git a/docs/if-module/2-bd.html b/docs/if-module/2-bd.html
index d1d00670b..859f3df1b 100644
--- a/docs/if-module/2-bd.html
+++ b/docs/if-module/2-bd.html
@@ -86,7 +86,7 @@ fully with the Treaty and the code below should be maintained as such.
 

-void BibliographicData::start(void) {
+void BibliographicData::start(void) {
     PluginManager::plug(MAKE_SPECIAL_MEANINGS_PLUG,
         BibliographicData::make_special_meanings);
     PluginManager::plug(NEW_VARIABLE_NOTIFY_PLUG,
diff --git a/docs/if-module/2-ri.html b/docs/if-module/2-ri.html
index 43cd10b1f..9640bc3d5 100644
--- a/docs/if-module/2-ri.html
+++ b/docs/if-module/2-ri.html
@@ -149,7 +149,7 @@ everything to do with a release into a singleton instance of the following.
 
 release_instructions *my_instructions = NULL;
 
-void ReleaseInstructions::start(void) {
+void ReleaseInstructions::start(void) {
     my_instructions = ReleaseInstructions::new_set();
 }
 
diff --git a/docs/if-module/3-bck.html b/docs/if-module/3-bck.html index 83bb100b8..4a86750e5 100644 --- a/docs/if-module/3-bck.html +++ b/docs/if-module/3-bck.html @@ -104,7 +104,7 @@ inferences to avoid piling up bogus inconsistencies.

§3. Initialisation.

-void PL::Backdrops::start(void) {
+void PL::Backdrops::start(void) {
     FOUND_IN_INF = Inferences::new_family(I"FOUND_IN_INF");
     METHOD_ADD(FOUND_IN_INF, LOG_DETAILS_INF_MTID, PL::Backdrops::log);
     METHOD_ADD(FOUND_IN_INF, COMPARE_INF_MTID, PL::Backdrops::cmp);
@@ -115,6 +115,7 @@ inferences to avoid piling up bogus inconsistencies.
     PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, PL::Backdrops::backdrops_new_property_notify);
     PluginManager::plug(COMPLETE_MODEL_PLUG, PL::Backdrops::backdrops_complete_model);
     PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, PL::Backdrops::backdrops_intervene_in_assertion);
+    PluginManager::plug(COMPILE_RUNTIME_DATA_PLUG,  PL::Backdrops::write_found_in_routines);
 }
 
 typedef struct found_in_inference_data {
@@ -452,7 +453,8 @@ code, derived from the old I6 library, requires §16.  

-void PL::Backdrops::write_found_in_routines(void) {
+int PL::Backdrops::write_found_in_routines(int stage, int debugging) {
+    if (stage != 1) return FALSE;
     backdrop_found_in_notice *notice;
     LOOP_OVER(notice, backdrop_found_in_notice) {
         instance *I = notice->backdrop;
@@ -461,6 +463,7 @@ code, derived from the old I6 library, requires         else
             The object is found nowhere16.2;
     }
+    return FALSE;
 }
 

§16.1. The object is found in many rooms or in whole regions16.1 = diff --git a/docs/if-module/3-dvc.html b/docs/if-module/3-dvc.html index d6478a1b6..9bdd5446a 100644 --- a/docs/if-module/3-dvc.html +++ b/docs/if-module/3-dvc.html @@ -86,7 +86,7 @@ age of Inter we want to avoid that sort of tomfoolery.

§2.

-void PL::Devices::start(void) {
+void PL::Devices::start(void) {
     PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, PL::Devices::devices_new_base_kind_notify);
     PluginManager::plug(COMPLETE_MODEL_PLUG, PL::Devices::IF_complete_model);
 }
diff --git a/docs/if-module/3-enah.html b/docs/if-module/3-enah.html
index bcb03293d..54f578283 100644
--- a/docs/if-module/3-enah.html
+++ b/docs/if-module/3-enah.html
@@ -88,7 +88,7 @@ function togglePopup(material_id) {
 

§2. Start.

-void WherePredicates::start(void) {
+void WherePredicates::start(void) {
     everywhere_up_family = UnaryPredicateFamilies::new();
     METHOD_ADD(everywhere_up_family, STOCK_UPF_MTID, WherePredicates::stock_everywhere);
     METHOD_ADD(everywhere_up_family, LOG_UPF_MTID, WherePredicates::log_everywhere);
diff --git a/docs/if-module/3-mcr.html b/docs/if-module/3-mcr.html
index ec41e00bd..d91486127 100644
--- a/docs/if-module/3-mcr.html
+++ b/docs/if-module/3-mcr.html
@@ -80,7 +80,7 @@ function togglePopup(material_id) {
 
 bp_family *map_connecting_bp_family = NULL;
 
-void PL::MapDirections::start(void) {
+void PL::MapDirections::start(void) {
     map_connecting_bp_family = BinaryPredicateFamilies::new();
     METHOD_ADD(map_connecting_bp_family, TYPECHECK_BPF_MTID, PL::MapDirections::typecheck);
     METHOD_ADD(map_connecting_bp_family, ASSERT_BPF_MTID, PL::MapDirections::assert);
diff --git a/docs/if-module/3-prs.html b/docs/if-module/3-prs.html
index 35187cee4..430dff3cf 100644
--- a/docs/if-module/3-prs.html
+++ b/docs/if-module/3-prs.html
@@ -86,7 +86,7 @@ sort of tomfoolery.
 

§2.

-void PL::Persons::start(void) {
+void PL::Persons::start(void) {
     PluginManager::plug(COMPLETE_MODEL_PLUG, PL::Persons::IF_complete_model);
 }
 
diff --git a/docs/if-module/3-rgn.html b/docs/if-module/3-rgn.html index 45346cf0b..b0a97ff1c 100644 --- a/docs/if-module/3-rgn.html +++ b/docs/if-module/3-rgn.html @@ -111,7 +111,7 @@ following minimal structure, though it will only be relevant for instances of

§4. Initialising.

-void PL::Regions::start(void) {
+void PL::Regions::start(void) {
     PluginManager::plug(CREATE_INFERENCE_SUBJECTS_PLUG, PL::Regions::create_inference_subjects);
     PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, PL::Regions::regions_new_base_kind_notify);
     PluginManager::plug(SET_SUBKIND_NOTIFY_PLUG, PL::Regions::regions_set_subkind_notify);
@@ -122,6 +122,7 @@ following minimal structure, though it will only be relevant for instances of
     PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, PL::Regions::regions_intervene_in_assertion);
     PluginManager::plug(NAME_TO_EARLY_INFS_PLUG, PL::Regions::regions_name_to_early_infs);
     PluginManager::plug(ADD_TO_WORLD_INDEX_PLUG, PL::Regions::regions_add_to_World_index);
+    PluginManager::plug(COMPILE_RUNTIME_DATA_PLUG, PL::Regions::write_regional_found_in_routines);
 }
 
 int PL::Regions::create_inference_subjects(void) {
@@ -448,7 +449,8 @@ region is either the next broadest region containing it, or else §18.  

-void PL::Regions::write_regional_found_in_routines(void) {
+int PL::Regions::write_regional_found_in_routines(int stage, int debugging) {
+    if (stage != 1) return FALSE;
     instance *I;
     LOOP_OVER_INSTANCES(I, K_object)
         if (Instances::of_kind(I, K_region)) {
@@ -469,12 +471,13 @@ region is either the next broadest region containing it, or else             Produce::rfalse(Emit::tree());
             Routines::end(save);
         }
+    return FALSE;
 }
 

§19.

-int PL::Regions::regions_add_to_World_index(OUTPUT_STREAM, instance *O) {
+int PL::Regions::regions_add_to_World_index(OUTPUT_STREAM, instance *O) {
     if ((O) && (Instances::of_kind(O, K_room))) {
         instance *R = PL::Regions::enclosing(O);
         if (R) PL::HTMLMap::colour_chip(OUT, O, R, REGIONS_DATA(O)->in_region_set_at);
diff --git a/docs/if-module/3-sc.html b/docs/if-module/3-sc.html
index 6cece9803..09d5d1af2 100644
--- a/docs/if-module/3-sc.html
+++ b/docs/if-module/3-sc.html
@@ -79,7 +79,7 @@ plugged in.
 

-void PL::Showme::start(void) {
+void PL::Showme::start(void) {
 }
 

§2. Support for the SHOWME command. And here is the one service. We must compile I6 code which looks at the diff --git a/docs/if-module/3-scn.html b/docs/if-module/3-scn.html index 9c738a354..baddec749 100644 --- a/docs/if-module/3-scn.html +++ b/docs/if-module/3-scn.html @@ -170,11 +170,19 @@ including bit 1 which records whether the scene has started.

§7. Plugin calls.

-void PL::Scenes::start(void) {
+void PL::Scenes::start(void) {
     PluginManager::plug(MAKE_SPECIAL_MEANINGS_PLUG, PL::Scenes::make_special_meanings);
     PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, PL::Scenes::scenes_new_property_notify);
     PluginManager::plug(NEW_INSTANCE_NOTIFY_PLUG, PL::Scenes::scenes_new_named_instance_notify);
     PluginManager::plug(NEW_BASE_KIND_NOTIFY_PLUG, PL::Scenes::scenes_new_base_kind_notify);
+    PluginManager::plug(COMPILE_RUNTIME_DATA_PLUG, PL::Scenes::compile_runtime);
+}
+
+int PL::Scenes::compile_runtime(int stage, int debugging) {
+    if (stage != 1) return FALSE;
+    PL::Scenes::DetectSceneChange_routine();
+    PL::Scenes::ShowSceneStatus_routine();
+    return FALSE;
 }
 
 int PL::Scenes::make_special_meanings(void) {
@@ -754,7 +762,7 @@ whether any change in status has or has not occurred.
 
define MAX_SCENE_CHANGE_ITERATION 20
 
-void PL::Scenes::DetectSceneChange_routine(void) {
+void PL::Scenes::DetectSceneChange_routine(void) {
     inter_name *iname = Hierarchy::find(DETECTSCENECHANGE_HL);
     packaging_state save = Routines::begin(iname);
     inter_symbol *chs_s = LocalVariables::add_internal_local_c_as_symbol(I"chs", "count of changes made");
@@ -868,7 +876,7 @@ below.
 

-void PL::Scenes::test_scene_end(scene *sc, int end, inter_symbol *ch_s, inter_symbol *CScene_l) {
+void PL::Scenes::test_scene_end(scene *sc, int end, inter_symbol *ch_s, inter_symbol *CScene_l) {
     if ((end == 0) && (sc->start_of_play)) {
         Produce::inv_primitive(Emit::tree(), IF_BIP);
         Produce::down(Emit::tree());
@@ -961,7 +969,7 @@ for this purpose.
 

-void PL::Scenes::compile_scene_end(scene *sc, int end) {
+void PL::Scenes::compile_scene_end(scene *sc, int end) {
     scene *sc2;
     LOOP_OVER(sc2, scene) sc2->marker = 0;
     PL::Scenes::compile_scene_end_dash(sc, end);
@@ -977,7 +985,7 @@ take effect first.
 

-void PL::Scenes::compile_scene_end_dash(scene *sc, int end) {
+void PL::Scenes::compile_scene_end_dash(scene *sc, int end) {
     int ix = sc->allocation_id;
     sc->marker++;
     if (end >= 2) {
@@ -1214,7 +1222,7 @@ what handles this.
 

-void PL::Scenes::ShowSceneStatus_routine(void) {
+void PL::Scenes::ShowSceneStatus_routine(void) {
     inter_name *iname = Hierarchy::find(SHOWSCENESTATUS_HL);
     packaging_state save = Routines::begin(iname);
     Produce::inv_primitive(Emit::tree(), IFDEBUG_BIP);
diff --git a/docs/if-module/3-sm.html b/docs/if-module/3-sm.html
index 415425790..4b9bae86b 100644
--- a/docs/if-module/3-sm.html
+++ b/docs/if-module/3-sm.html
@@ -275,7 +275,7 @@ timing issue to get around (see below).
 

§7. Initialisation.

-void PL::Spatial::start(void) {
+void PL::Spatial::start(void) {
     IS_ROOM_INF = Inferences::new_family(I"IS_ROOM_INF");
     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");
diff --git a/docs/if-module/3-sr.html b/docs/if-module/3-sr.html
index 460571b1b..6c33fc5e4 100644
--- a/docs/if-module/3-sr.html
+++ b/docs/if-module/3-sr.html
@@ -111,7 +111,7 @@ MathJax = {
 

-void PL::SpatialRelations::start(void) {
+void PL::SpatialRelations::start(void) {
     METHOD_ADD(spatial_bp_family, STOCK_BPF_MTID, PL::SpatialRelations::stock);
     METHOD_ADD(spatial_bp_family, TYPECHECK_BPF_MTID, PL::SpatialRelations::typecheck);
     METHOD_ADD(spatial_bp_family, ASSERT_BPF_MTID, PL::SpatialRelations::assert);
diff --git a/docs/if-module/3-tm.html b/docs/if-module/3-tm.html
index 622c49536..f0a19b6c1 100644
--- a/docs/if-module/3-tm.html
+++ b/docs/if-module/3-tm.html
@@ -258,7 +258,7 @@ makes for more legible code if we use a special inference type of our own:
 

§8. Initialisation.

-void PL::Map::start(void) {
+void PL::Map::start(void) {
     DIRECTION_INF = Inferences::new_family(I"DIRECTION_INF");
     METHOD_ADD(DIRECTION_INF, LOG_DETAILS_INF_MTID, PL::Map::log_direction_inf);
     METHOD_ADD(DIRECTION_INF, COMPARE_INF_MTID, PL::Map::cmp_direction_inf);
@@ -270,13 +270,21 @@ makes for more legible code if we use a special inference type of our own:
     PluginManager::plug(SET_SUBKIND_NOTIFY_PLUG, PL::Map::map_set_subkind_notify);
     PluginManager::plug(ACT_ON_SPECIAL_NPS_PLUG, PL::Map::map_act_on_special_NPs);
     PluginManager::plug(CHECK_GOING_PLUG, PL::Map::map_check_going);
-    PluginManager::plug(COMPILE_RUNTIME_DATA_PLUG, PL::Map::map_compile_model_tables);
     PluginManager::plug(COMPLETE_MODEL_PLUG, PL::Map::map_complete_model);
     PluginManager::plug(NEW_PROPERTY_NOTIFY_PLUG, PL::Map::map_new_property_notify);
     PluginManager::plug(INFERENCE_DRAWN_NOTIFY_PLUG, PL::Map::map_inference_drawn);
     PluginManager::plug(INTERVENE_IN_ASSERTION_PLUG, PL::Map::map_intervene_in_assertion);
     PluginManager::plug(ADD_TO_WORLD_INDEX_PLUG, PL::Map::map_add_to_World_index);
     PluginManager::plug(ANNOTATE_IN_WORLD_INDEX_PLUG, PL::Map::map_annotate_in_World_index);
+    PluginManager::plug(COMPILE_RUNTIME_DATA_PLUG, PL::Map::compile_runtime);
+}
+
+int PL::Map::compile_runtime(int stage, int debugging) {
+    if (stage != 1) return FALSE;
+    PL::Map::map_compile_model_tables();
+    PL::Map::write_door_dir_routines();
+    PL::Map::write_door_to_routines();
+    return FALSE;
 }
 
 int PL::Map::make_special_meanings(void) {
@@ -1250,7 +1258,7 @@ why we don't need to compile 
 

§35. Redeeming those notices.

-void PL::Map::write_door_dir_routines(void) {
+void PL::Map::write_door_dir_routines(void) {
     door_dir_notice *notice;
     LOOP_OVER(notice, door_dir_notice) {
         packaging_state save = Routines::begin(notice->ddn_iname);
@@ -1306,7 +1314,7 @@ why we don't need to compile 
     }
 }
 
-void PL::Map::write_door_to_routines(void) {
+void PL::Map::write_door_to_routines(void) {
     door_to_notice *notice;
     LOOP_OVER(notice, door_to_notice) {
         packaging_state save = Routines::begin(notice->dtn_iname);
@@ -1363,14 +1371,14 @@ why we don't need to compile 
 

§36. Indexing.

-int PL::Map::map_add_to_World_index(OUTPUT_STREAM, instance *O) {
+int PL::Map::map_add_to_World_index(OUTPUT_STREAM, instance *O) {
     if ((O) && (Instances::of_kind(O, K_room))) {
         PL::SpatialMap::index_room_connections(OUT, O);
     }
     return FALSE;
 }
 
-int PL::Map::map_annotate_in_World_index(OUTPUT_STREAM, instance *O) {
+int PL::Map::map_annotate_in_World_index(OUTPUT_STREAM, instance *O) {
     if ((O) && (Instances::of_kind(O, K_door))) {
         instance *A = NULL, *B = NULL;
         PL::Map::get_door_data(O, &A, &B);
diff --git a/docs/if-module/3-tp.html b/docs/if-module/3-tp.html
index 83234e74f..0de854a90 100644
--- a/docs/if-module/3-tp.html
+++ b/docs/if-module/3-tp.html
@@ -101,7 +101,7 @@ to this plugin, but the idea is to position the player in both space and time.
 

§3. Initialisation.

-void PL::Player::start(void) {
+void PL::Player::start(void) {
     PluginManager::plug(NEW_VARIABLE_NOTIFY_PLUG, PL::Player::player_new_quantity_notify);
     PluginManager::plug(VARIABLE_VALUE_NOTIFY_PLUG, PL::Player::player_variable_set_warning);
     PluginManager::plug(NEW_INSTANCE_NOTIFY_PLUG, PL::Player::player_new_instance_notify);
diff --git a/docs/if-module/3-ts.html b/docs/if-module/3-ts.html
index 2d36ffdd0..741e8c6ce 100644
--- a/docs/if-module/3-ts.html
+++ b/docs/if-module/3-ts.html
@@ -85,7 +85,8 @@ reports asking why it wouldn't change in play.
 

§2. Initialisation.

-void PL::Score::start(void) {
+void PL::Score::start(void) {
+    PluginManager::plug(COMPILE_RUNTIME_DATA_PLUG, PL::Score::compile_max_score);
 }
 

§3. The maximum score and rankings table. A special rule is that if a table is called "Rankings" and contains a column @@ -107,7 +108,8 @@ score corresponding to successful completion and the highest rank.

-void PL::Score::compile_max_score(void) {
+int PL::Score::compile_max_score(int stage, int debugging) {
+    if (stage != 1) return FALSE;
     int rt_made = FALSE;
     table *t;
     LOOP_OVER(t, table) {
@@ -143,6 +145,7 @@ score corresponding to successful completion and the highest rank.
     } else {
         Emit::named_numeric_constant(iname, 0);
     }
+    return FALSE;
 }