From f0ed01994d4c56ea82f6a22aeba6aecae825d5bd Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Fri, 21 Jul 2023 11:49:36 +0100 Subject: [PATCH] More on extension documentation examples --- README.md | 2 +- build.txt | 4 +- docs/supervisor-module/1-ic.html | 2 +- docs/supervisor-module/1-sm.html | 2 + docs/supervisor-module/2-nst.html | 2 +- docs/supervisor-module/2-rqr.html | 2 +- docs/supervisor-module/4-ebm.html | 6 +- docs/supervisor-module/4-em.html | 2 +- docs/supervisor-module/5-es.html | 76 ++-- docs/supervisor-module/5-ks.html | 2 +- docs/supervisor-module/5-ps2.html | 4 +- docs/supervisor-module/6-hdn.html | 2 +- docs/supervisor-module/6-inc.html | 6 +- docs/supervisor-module/6-st.html | 4 +- docs/supervisor-module/7-dc.html | 429 +++++++++++++----- docs/supervisor-module/7-dr.html | 12 +- docs/supervisor-module/7-dt.html | 51 ++- docs/supervisor-module/7-eip.html | 25 +- docs/supervisor-module/7-ti.html | 4 +- docs/supervisor-module/7-tm.html | 17 + .../Chapter 1/Supervisor Module.w | 2 + .../Chapter 4/Extension Bundle Manager.w | 2 +- .../Chapter 5/Extension Services.w | 26 +- .../Chapter 7/Documentation Compiler.w | 212 ++++++++- .../Chapter 7/Documentation Renderer.w | 10 +- .../Chapter 7/Documentation Tree.w | 33 +- .../Chapter 7/Extensions Index Page.w | 19 +- .../Chapter 7/The Mini-Website.w | 16 + inform7/Figures/memory-diagnostics.txt | 104 ++--- inform7/Figures/timings-diagnostics.txt | 26 +- .../Inter/Architecture16Kit/kit_metadata.json | 2 +- .../Inter/Architecture32Kit/kit_metadata.json | 2 +- .../Inter/BasicInformKit/kit_metadata.json | 2 +- .../Inter/CommandParserKit/kit_metadata.json | 2 +- .../EnglishLanguageKit/kit_metadata.json | 2 +- .../Inter/WorldModelKit/kit_metadata.json | 2 +- 36 files changed, 810 insertions(+), 306 deletions(-) diff --git a/README.md b/README.md index 87de481f9..7c6d78cd7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -[Version](notes/versioning.md): 10.2.0-beta+6W86 'Krypton' (19 July 2023) +[Version](notes/versioning.md): 10.2.0-beta+6W87 'Krypton' (21 July 2023) ## About Inform diff --git a/build.txt b/build.txt index 0004bcb53..a31679250 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: beta -Build Date: 19 July 2023 -Build Number: 6W86 +Build Date: 21 July 2023 +Build Number: 6W87 diff --git a/docs/supervisor-module/1-ic.html b/docs/supervisor-module/1-ic.html index 04dd3a93d..344725e08 100644 --- a/docs/supervisor-module/1-ic.html +++ b/docs/supervisor-module/1-ic.html @@ -638,7 +638,7 @@ nests, respectively. return shared_nest_list; } -inbuild_nest *Supervisor::internal(void) { +inbuild_nest *Supervisor::internal(void) { RUN_ONLY_FROM_PHASE(NESTED_INBUILD_PHASE) return shared_internal_nest; } diff --git a/docs/supervisor-module/1-sm.html b/docs/supervisor-module/1-sm.html index 321f16fa0..97dc0368d 100644 --- a/docs/supervisor-module/1-sm.html +++ b/docs/supervisor-module/1-sm.html @@ -106,6 +106,7 @@ which use this module: enum inform_template_CLASS enum kit_configuration_CLASS enum kit_dependency_CLASS +enum satellite_test_case_CLASS
 DECLARE_CLASS(build_methodology)
@@ -145,6 +146,7 @@ which use this module:
 DECLARE_CLASS(inform_template)
 DECLARE_CLASS(kit_configuration)
 DECLARE_CLASS(kit_dependency)
+DECLARE_CLASS(satellite_test_case)
 

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

diff --git a/docs/supervisor-module/2-nst.html b/docs/supervisor-module/2-nst.html index 84f406fdb..051c281fe 100644 --- a/docs/supervisor-module/2-nst.html +++ b/docs/supervisor-module/2-nst.html @@ -151,7 +151,7 @@ can't install to a read-only nest.

§5.

-pathname *Nests::get_location(inbuild_nest *N) {
+pathname *Nests::get_location(inbuild_nest *N) {
     if (N == NULL) return NULL;
     return N->location;
 }
diff --git a/docs/supervisor-module/2-rqr.html b/docs/supervisor-module/2-rqr.html
index 027b6babc..38bd32101 100644
--- a/docs/supervisor-module/2-rqr.html
+++ b/docs/supervisor-module/2-rqr.html
@@ -243,7 +243,7 @@ a requirement, then so will all other copies of it.
 

-int Requirements::meets(inbuild_edition *edition, inbuild_requirement *req) {
+int Requirements::meets(inbuild_edition *edition, inbuild_requirement *req) {
     if (req == NULL) return TRUE;
     if (req->work) {
         if (req->work->genre)
diff --git a/docs/supervisor-module/4-ebm.html b/docs/supervisor-module/4-ebm.html
index 79f9cae93..746aa76e7 100644
--- a/docs/supervisor-module/4-ebm.html
+++ b/docs/supervisor-module/4-ebm.html
@@ -135,7 +135,7 @@ which stores data about extensions used by the Inform compiler.
                 if (Str::get(pos) == '.')
                     Str::put(pos, '_');
             WRITE_TO(new_name, "%S-v%S.i7xd", C->edition->work->title, new_version);
-            if (Extensions::rename_directory(P, new_name)) {
+            if (Extensions::rename_directory(P, new_name)) {
                 Str::clear(key);
                 WRITE_TO(key, "%p", P);
                 apparent_V = C->edition->version;
@@ -408,7 +408,7 @@ copy name.
             Str::delete_last_character(subdir);
             if (Str::eq(subdir, I"Examples")) {
                 ;
-            } else if (Str::eq(subdir, I"Images")) {
+            } else if (Str::eq(subdir, I"Tests")) {
                 ;
             } else {
                 TEMPORARY_TEXT(error_text)
@@ -549,7 +549,7 @@ directory, we need to rsync
 void ExtensionBundleManager::document(inbuild_genre *gen, inbuild_copy *C, pathname *dest) {
-    Extensions::document(Extensions::from_copy(C), dest);
+    Extensions::document(Extensions::from_copy(C), dest);
 }
 
-

§17. The optional extra credit line is used to acknowledge I6 sources, +

§16. The optional extra credit line is used to acknowledge I6 sources, collaborators, translators and so on.

@@ -1131,7 +1117,7 @@ collaborators, translators and so on. LOGIF(EXTENSIONS_CENSUS, "Extension extra credit: %S\n", E->extra_credit_as_lexed); } -

§18. The use option "authorial modesty" is unusual in applying to the extension +

§17. The use option "authorial modesty" is unusual in applying to the extension it is found in, not the whole source text. When we read it, we call one of the following routines, depending on whether it was in an extension or in the main source text: @@ -1147,21 +1133,21 @@ the main source text: general_authorial_modesty = TRUE; } -

§19. The inclusion sentence for an extension is where it was Included in a +

§18. The inclusion sentence for an extension is where it was Included in a project's syntax tree (if it was). It isn't used in compilation, only for problem messages and the index.

-void Extensions::set_inclusion_sentence(inform_extension *E, parse_node *N) {
+void Extensions::set_inclusion_sentence(inform_extension *E, parse_node *N) {
     E->inclusion_sentence = N;
 }
-parse_node *Extensions::get_inclusion_sentence(inform_extension *E) {
+parse_node *Extensions::get_inclusion_sentence(inform_extension *E) {
     if (E == NULL) return NULL;
     return E->inclusion_sentence;
 }
 
-

§20. An extension is "standard" if it's either the Standard Rules or Basic Inform. +

§19. An extension is "standard" if it's either the Standard Rules or Basic Inform.

@@ -1170,33 +1156,33 @@ problem messages and the index.
     return E->standard;
 }
 
-

§21. Version requirements. When it's known that an extension must satisfy a given version requirement — +

§20. Version requirements. When it's known that an extension must satisfy a given version requirement — say, being version 7.2.1 or better — the following is called. Note that if incompatible requirements are placed on it, the range in E->must_satisfy becomes empty and stays that way.

-void Extensions::must_satisfy(inform_extension *E, inbuild_requirement *req) {
+void Extensions::must_satisfy(inform_extension *E, inbuild_requirement *req) {
     if (E->must_satisfy == NULL) E->must_satisfy = req;
     else VersionNumberRanges::intersect_range(E->must_satisfy->version_range, req->version_range);
 }
 
-

§22. And it is certainly possible, if an extension is loaded for multiple +

§21. And it is certainly possible, if an extension is loaded for multiple reasons with different versioning needs, that the extension no longer meets its requirements (even though it did when first loaded). This tests for that:

-int Extensions::satisfies(inform_extension *E) {
+int Extensions::satisfies(inform_extension *E) {
     if (E == NULL) return FALSE;
     return Requirements::meets(E->as_copy->edition, E->must_satisfy);
 }
 
-

§23. File hierarchy tidying.

+

§22. File hierarchy tidying.

-int Extensions::rename_directory(pathname *P, text_stream *new_name) {
+int Extensions::rename_directory(pathname *P, text_stream *new_name) {
     TEMPORARY_TEXT(task)
     WRITE_TO(task, "(Changing directory name '%p' to '%S')\n", P, new_name);
     int rv = Directories::rename(P, new_name);
@@ -1204,7 +1190,7 @@ its requirements (even though it did when first loaded). This tests for that:
     return rv;
 }
 
-int Extensions::rename_file(filename *F, text_stream *new_name) {
+int Extensions::rename_file(filename *F, text_stream *new_name) {
     TEMPORARY_TEXT(task)
     WRITE_TO(task, "(Changing file name '%f' to '%S')\n", F, new_name);
     int rv = Filenames::rename(F, new_name);
diff --git a/docs/supervisor-module/5-ks.html b/docs/supervisor-module/5-ks.html
index 13985d30a..d98ba141b 100644
--- a/docs/supervisor-module/5-ks.html
+++ b/docs/supervisor-module/5-ks.html
@@ -140,7 +140,7 @@ use options.
     CLASS_DEFINITION
 } kit_configuration;
 
- +

§5. Here goes, then:

diff --git a/docs/supervisor-module/5-ps2.html b/docs/supervisor-module/5-ps2.html index 524ba6dab..0520a03a9 100644 --- a/docs/supervisor-module/5-ps2.html +++ b/docs/supervisor-module/5-ps2.html @@ -1165,10 +1165,10 @@ each extension against the intersection of all requirements put on it: void Projects::check_extension_versions_d(inform_project *proj, build_vertex *V) { if ((V->as_copy) && (V->as_copy->edition->work->genre == extension_genre)) { inform_extension *E = Extensions::from_copy(V->as_copy); - if (Extensions::satisfies(E) == FALSE) { + if (Extensions::satisfies(E) == FALSE) { copy_error *CE = CopyErrors::new_T(SYNTAX_CE, ExtVersionTooLow_SYNERROR, I"two incompatible versions"); - CopyErrors::supply_node(CE, Extensions::get_inclusion_sentence(E)); + CopyErrors::supply_node(CE, Extensions::get_inclusion_sentence(E)); Copies::attach_error(proj->as_copy, CE); } } diff --git a/docs/supervisor-module/6-hdn.html b/docs/supervisor-module/6-hdn.html index 29cf57491..49359043d 100644 --- a/docs/supervisor-module/6-hdn.html +++ b/docs/supervisor-module/6-hdn.html @@ -789,7 +789,7 @@ file and a line number of at least 1). inform_extension *Headings::get_extension_containing(heading *h) { if ((h == NULL) || (h->start_location.file_of_origin == NULL)) return NULL; - return Extensions::corresponding_to(h->start_location.file_of_origin); + return Extensions::corresponding_to(h->start_location.file_of_origin); }

§19. Although Implied (0) headings do have text, contrary to the implication of diff --git a/docs/supervisor-module/6-inc.html b/docs/supervisor-module/6-inc.html index f9ea69a3a..24e1fbdbc 100644 --- a/docs/supervisor-module/6-inc.html +++ b/docs/supervisor-module/6-inc.html @@ -325,7 +325,7 @@ Sausages by Mr Punch, and loaded it, but then read the sentence LOOP_OVER(E, inform_extension) if ((Requirements::meets(E->as_copy->edition, req)) && (Copies::source_text_has_been_read(E->as_copy))) { - Extensions::must_satisfy(E, req); + Extensions::must_satisfy(E, req); return E; } Read the extension file into the lexer, and break it into body and documentation6.1; @@ -343,7 +343,7 @@ Sausages by Mr Punch, and loaded it, but then read the sentence Nests::search_for_best(req, Projects::nest_list(for_project)); if (search_result) { E = Extensions::from_copy(search_result->copy); - Extensions::set_inclusion_sentence(E, at); + Extensions::set_inclusion_sentence(E, at); Extensions::set_associated_project(E, for_project); if (Nests::get_tag(search_result->nest) == INTERNAL_NEST_TAG) E->loaded_from_built_in_area = TRUE; @@ -378,7 +378,7 @@ report this problem at the inclusion line.

     copy_error *CE = CopyErrors::new_T(SYNTAX_CE, ExtInadequateVM_SYNERROR, C->parsed_from);
-    CopyErrors::supply_node(CE, Extensions::get_inclusion_sentence(E));
+    CopyErrors::supply_node(CE, Extensions::get_inclusion_sentence(E));
     Copies::attach_error(inclusions_errors_to, CE);
 
diff --git a/docs/supervisor-module/6-st.html b/docs/supervisor-module/6-st.html index 655d96935..09c541471 100644 --- a/docs/supervisor-module/6-st.html +++ b/docs/supervisor-module/6-st.html @@ -171,7 +171,7 @@ source files. paraphrase = I"source text"; inform_extension *E = NULL; if (referred) { - E = Extensions::corresponding_to(referred); + E = Extensions::corresponding_to(referred); } else { TEMPORARY_TEXT(matched_filename) inform_extension *F; @@ -202,7 +202,7 @@ source files.
 void SourceText::gloss_extension(text_stream *OUT, source_file *referred) {
-    inform_extension *E = Extensions::corresponding_to(referred);
+    inform_extension *E = Extensions::corresponding_to(referred);
     if (E) WRITE(" in the extension %X", E->as_copy->edition->work);
 }
 
diff --git a/docs/supervisor-module/7-dc.html b/docs/supervisor-module/7-dc.html index e12a9e559..9a0f6e13f 100644 --- a/docs/supervisor-module/7-dc.html +++ b/docs/supervisor-module/7-dc.html @@ -72,10 +72,11 @@ it's really not much more than the tree produced by int total_headings[3]; int total_examples; int empty; + struct linked_list *cases; of satellite_test_case CLASS_DEFINITION } compiled_documentation; -compiled_documentation *DocumentationCompiler::new_wrapper(text_stream *source) { +compiled_documentation *DocumentationCompiler::new_wrapper(text_stream *source) { compiled_documentation *cd = CREATE(compiled_documentation); cd->title = Str::new(); cd->original = Str::duplicate(source); @@ -86,21 +87,223 @@ it's really not much more than the tree produced by cd->total_headings[1] = 0; cd->total_headings[2] = 0; cd->empty = FALSE; + cd->cases = NEW_LINKED_LIST(satellite_test_case); return cd; } + +typedef struct satellite_test_case { + int is_example; + struct text_stream *owning_heading; + struct tree_node *owning_node; + struct compiled_documentation *owner; + struct text_stream *short_name; + struct filename *test_file; + struct filename *ideal_transcript; + CLASS_DEFINITION +} satellite_test_case; - +

§2. We can compile either from a file...

-compiled_documentation *DocumentationCompiler::compile_from_file(filename *F,
+compiled_documentation *DocumentationCompiler::compile_from_path(pathname *P,
+    inform_extension *associated_extension) {
+    filename *F = Filenames::in(P, I"Documentation.txt");
+    if (TextFiles::exists(F) == FALSE) return NULL;
+    compiled_documentation *cd =
+        DocumentationCompiler::compile_from_file(F, associated_extension);
+    if (cd == NULL) return NULL;
+    pathname *EP = Pathnames::down(P, I"Examples");
+    int egs = TRUE;
+    Scan EP directory for examples2.1;
+    egs = FALSE;
+    EP = Pathnames::down(P, I"Tests");
+    Scan EP directory for examples2.1;
+    return cd;
+}
+
+

§2.1. Scan EP directory for examples2.1 = +

+ +
+    scan_directory *D = Directories::open(EP);
+    TEMPORARY_TEXT(leafname)
+    while (Directories::next(D, leafname)) {
+        wchar_t first = Str::get_first_char(leafname), last = Str::get_last_char(leafname);
+        if (Platform::is_folder_separator(last)) continue;
+        if (first == '.') continue;
+        if (first == '(') continue;
+        text_stream *short_name = Str::new();
+        filename *F = Filenames::in(EP, leafname);
+        Filenames::write_unextended_leafname(short_name, F);
+        if ((Str::get_at(short_name, Str::len(short_name)-2) == '-') &&
+            ((Str::get_at(short_name, Str::len(short_name)-1) == 'I')
+                || (Str::get_at(short_name, Str::len(short_name)-1) == 'i')))
+            continue;
+        satellite_test_case *stc = CREATE(satellite_test_case);
+        stc->is_example = egs;
+        stc->owning_heading = NULL;
+        stc->owning_node = NULL;
+        stc->owner = cd;
+        stc->short_name = short_name;
+        stc->test_file = F;
+        stc->ideal_transcript = NULL;
+        TEMPORARY_TEXT(ideal_leafname)
+        WRITE_TO(ideal_leafname, "%S-I.txt", stc->short_name);
+        filename *IF = Filenames::in(EP, ideal_leafname);
+        if (TextFiles::exists(IF)) stc->ideal_transcript = IF;
+        DISCARD_TEXT(ideal_leafname)
+        if (stc->is_example) {
+            Scan the example for its header and content2.1.2;
+        }
+        ADD_TO_LINKED_LIST(stc, satellite_test_case, cd->cases);
+    }
+    DISCARD_TEXT(leafname)
+    Directories::close(D);
+
+ +

§2.1.1.

+ +
+typedef struct example_scanning_state {
+    int star_count;
+    struct text_stream *long_title;
+    struct text_stream *body_text;
+    struct text_stream *placement;
+    struct text_stream *desc;
+    struct linked_list *errors;
+    struct heterogeneous_tree *tree;
+    struct text_stream *scanning;
+    int past_header;
+} example_scanning_state;
+
+ +

§2.1.2. Scan the example for its header and content2.1.2 = +

+ +
+    example_scanning_state ess;
+    ess.star_count = 1;
+    ess.long_title = NULL;
+    ess.body_text = Str::new();
+    ess.placement = NULL;
+    ess.desc = NULL;
+    ess.errors = NEW_LINKED_LIST(tree_node);
+    ess.tree = cd->tree;
+    ess.past_header = FALSE;
+    ess.scanning = Str::new(); WRITE_TO(ess.scanning, "%S", Filenames::get_leafname(stc->test_file));
+    TextFiles::read(stc->test_file, FALSE, "unable to read file of example", TRUE,
+        &DocumentationCompiler::read_example_helper, NULL, &ess);
+
+    tree_node *placement_node = NULL;
+    if (Str::len(ess.placement) == 0) {
+        DocumentationCompiler::example_error(&ess,
+            I"example does not give its Location");
+    } else {
+        placement_node = DocumentationTree::find_section(cd->tree, ess.placement);
+        if (placement_node == NULL) {
+            DocumentationCompiler::example_error(&ess,
+                I"example gives a Location which is not the name of any section");
+        }
+    }
+    if (Str::len(ess.desc) == 0) {
+        DocumentationCompiler::example_error(&ess,
+            I"example does not give its Description");
+    }
+    tree_node *content_node = NULL;
+    if (Str::len(ess.body_text) == 0) {
+        DocumentationCompiler::example_error(&ess,
+            I"example does not give any actual content");
+    } else {
+        compiled_documentation *ecd =
+            DocumentationCompiler::compile(ess.body_text, associated_extension);
+        if ((ecd) && (ecd->tree) && (ecd->tree->root) &&
+            (ecd->tree->root->child) &&
+            (ecd->tree->root->child->type == passage_TNT))
+            content_node = ecd->tree->root->child;
+        else {
+            DocumentationCompiler::example_error(&ess,
+                I"example file content is missing or wrongly set out");
+        }
+    }
+    tree_node *example_node = DocumentationTree::new_example(cd->tree,
+        ess.long_title, ess.desc, ess.star_count, ++(cd->total_examples));
+    if (placement_node) Trees::make_child(example_node, placement_node);
+    if (content_node) Trees::make_child(content_node, example_node);
+
+    tree_node *E;
+    LOOP_OVER_LINKED_LIST(E, tree_node, ess.errors)
+        Trees::make_child(E, cd->tree->root);
+
+ +

§3.

+ +
+void DocumentationCompiler::example_error(example_scanning_state *ess, text_stream *text) {
+    text_stream *err = Str::new();
+    WRITE_TO(err, "Example file '%S': %S", ess->scanning, text);
+    tree_node *E = DocumentationTree::new_source_error(ess->tree, err);
+    ADD_TO_LINKED_LIST(E, tree_node, ess->errors);
+}
+
+

§4.

+ +
+void DocumentationCompiler::read_example_helper(text_stream *text, text_file_position *tfp,
+    void *v_state) {
+    example_scanning_state *ess = (example_scanning_state *) v_state;
+    if (tfp->line_count == 1) {
+        match_results mr = Regexp::create_mr();
+        if ((Regexp::match(&mr, text, L"Example *: *(%**) *(%c+?)")) ||
+            (Regexp::match(&mr, text, L"Example *- *(%**) *(%c+?)"))) {
+            ess->star_count = Str::len(mr.exp[0]);
+            if (ess->star_count == 0) {
+                DocumentationCompiler::example_error(ess,
+                    I"this example should be marked (before the title) '*', '**', '***' or '****' for difficulty");
+                ess->star_count = 1;
+            }
+            if (ess->star_count > 4) {
+                DocumentationCompiler::example_error(ess,
+                    I"four stars '****' is the maximum difficulty rating allowed");
+                ess->star_count = 4;
+            }
+            ess->long_title = Str::duplicate(mr.exp[1]);
+        } else {
+            DocumentationCompiler::example_error(ess,
+                I"titling line of example file is malformed");
+        }
+        Regexp::dispose_of(&mr);
+    } else if (ess->past_header == FALSE) {
+        if (Str::is_whitespace(text)) { ess->past_header = TRUE; return; }
+        match_results mr = Regexp::create_mr();
+        if (Regexp::match(&mr, text, L"(%C+?) *: *(%c+?)")) {
+            if (Str::eq(mr.exp[0], I"Location")) ess->placement = Str::duplicate(mr.exp[1]);
+            else if (Str::eq(mr.exp[0], I"Description")) ess->desc = Str::duplicate(mr.exp[1]);
+            else {
+                DocumentationCompiler::example_error(ess,
+                    I"unknown datum in header line of example file");
+            }
+        } else {
+            DocumentationCompiler::example_error(ess,
+                I"header line of example file is malformed");
+        }
+        Regexp::dispose_of(&mr);
+    } else {
+        WRITE_TO(ess->body_text, "%S\n", text);
+    }
+}
+
+

§5.

+ +
+compiled_documentation *DocumentationCompiler::compile_from_file(filename *F,
     inform_extension *associated_extension) {
     TEMPORARY_TEXT(temp)
     TextFiles::read(F, FALSE, "unable to read file of documentation", TRUE,
-        &DocumentationCompiler::read_file_helper, NULL, temp);
+        &DocumentationCompiler::read_file_helper, NULL, temp);
     compiled_documentation *cd =
-        DocumentationCompiler::compile(temp, associated_extension);
+        DocumentationCompiler::compile(temp, associated_extension);
     DISCARD_TEXT(temp)
     return cd;
 }
@@ -111,11 +314,11 @@ it's really not much more than the tree produced by     WRITE_TO(contents, "%S\n", text);
 }
 
-

§3. ...or from text: +

§6. ...or from text:

-compiled_documentation *DocumentationCompiler::compile(text_stream *source,
+compiled_documentation *DocumentationCompiler::compile(text_stream *source,
     inform_extension *associated_extension) {
     SVEXPLAIN(1, "(compiling documentation: %d chars)\n", Str::len(source));
     compiled_documentation *cd = DocumentationCompiler::new_wrapper(source);
@@ -123,7 +326,7 @@ it's really not much more than the tree produced by     if (cd->associated_extension)
         WRITE_TO(cd->title, "%X", cd->associated_extension->as_copy->edition->work);
     if (Str::is_whitespace(source)) cd->empty = TRUE;
-    else Parse the source3.1;
+    else Parse the source6.1;
     if (cd->empty) {
         SVEXPLAIN(1, "(resulting tree is empty)\n");
     } else {
@@ -133,12 +336,12 @@ it's really not much more than the tree produced by     return cd;
 }
 
-

§3.1. The source material is line-based, with semantic content sometimes spreading +

§6.1. The source material is line-based, with semantic content sometimes spreading across multiple lines, so we'll need to keep track of some state as we read one line at a time:

-

Parse the source3.1 = +

Parse the source6.1 =

@@ -157,18 +360,18 @@ one line at a time:
               *last_paste_code = NULL;      last code sample with a paste button
 
     int pending_code_sample_blanks = 0, code_is_tabular = FALSE;  used only when assembling code samples
-    programming_language *default_language = DocumentationCompiler::get_language(I"Inform");
+    programming_language *default_language = DocumentationCompiler::get_language(I"Inform");
     programming_language *language = default_language;
 
-    Parse the source linewise3.1.1;
+    Parse the source linewise6.1.1;
 
- -

§3.1.1. Leading space on a line is removed but not ignored: it is converted into an +

+

§6.1.1. Leading space on a line is removed but not ignored: it is converted into an indentation level, measured as a tab count, using the exchange rate 4 spaces to 1 tab.

-

Parse the source linewise3.1.1 = +

Parse the source linewise6.1.1 =

@@ -177,7 +380,7 @@ to 1 tab.
     for (int i=0; i<Str::len(source); i++) {
         wchar_t c = Str::get_at(source, i);
         if (c == '\n') {
-            Line read3.1.1.1;
+            Line read6.1.1.1;
             Str::clear(line);
             indentation = 0; space_count = 0;
         } else if ((Str::len(line) == 0) && (Characters::is_whitespace(c))) {
@@ -188,13 +391,13 @@ to 1 tab.
             PUT_TO(line, c);
         }
     }
-    if (Str::len(line) > 0) Line read3.1.1.1;
-    Check for runaway phrase definitions3.1.1.2;
-    Complete passage if in one3.1.1.3;
+    if (Str::len(line) > 0) Line read6.1.1.1;
+    Check for runaway phrase definitions6.1.1.2;
+    Complete passage if in one6.1.1.3;
     DISCARD_TEXT(line)
 
- -

§3.1.1.1. Trailing space is ignored and removed. +

+

§6.1.1.1. Trailing space is ignored and removed.

Lines which are unindented and take the following shapes are headings: @@ -214,33 +417,33 @@ may either end or continue code samples; unindented lines, which are always part of paragraphs; or indented ones, which are always part of code samples.

-

Line read3.1.1.1 = +

Line read6.1.1.1 =

     Str::trim_white_space(line);
     if (Str::len(line) == 0) {
-        if (current_paragraph) Complete paragraph or code3.1.1.1.7;
-        if (current_code) Insert line break in code3.1.1.1.12;
+        if (current_paragraph) Complete paragraph or code6.1.1.1.7;
+        if (current_code) Insert line break in code6.1.1.1.12;
     } else if (indentation == 0) {
         match_results mr = Regexp::create_mr();
         if ((Regexp::match(&mr, line, L"Section *: *(%c+?)")) ||
             (Regexp::match(&mr, line, L"Section *- *(%c+?)"))) {
-            Insert a section heading3.1.1.1.2;
+            Insert a section heading6.1.1.1.2;
         } else if ((Regexp::match(&mr, line, L"Chapter *: *(%c+?)")) ||
             (Regexp::match(&mr, line, L"Chapter *- *(%c+?)"))) {
-            Insert a chapter heading3.1.1.1.1;
+            Insert a chapter heading6.1.1.1.1;
         } else if ((Regexp::match(&mr, line, L"Example *: *(%**) *(%c+?)")) ||
             (Regexp::match(&mr, line, L"Example *- *(%**) *(%c+?)"))) {
-            Insert an example heading3.1.1.1.3;
+            Insert an example heading6.1.1.1.3;
         } else if (Regexp::match(&mr, line, L"{defn *(%c*?)} *(%c+)")) {
-            Begin a phrase definition3.1.1.1.4;
+            Begin a phrase definition6.1.1.1.4;
         } else if (Regexp::match(&mr, line, L"{end}")) {
-            End a phrase definition3.1.1.1.5;
+            End a phrase definition6.1.1.1.5;
         } else {
-            if (current_paragraph == NULL) Begin paragraph3.1.1.1.8;
-            Insert space in paragraph3.1.1.1.9;
-            Insert line in paragraph3.1.1.1.10;
+            if (current_paragraph == NULL) Begin paragraph6.1.1.1.8;
+            Insert space in paragraph6.1.1.1.9;
+            Insert line in paragraph6.1.1.1.10;
         }
         Regexp::dispose_of(&mr);
     } else {
@@ -251,10 +454,10 @@ part of paragraphs; or indented ones, which are always part of code samples.
                 Str::delete_n_characters(line, 4);
                 Str::delete_last_character(line);
                 Str::trim_white_space(line);
-                language = DocumentationCompiler::get_language(line);
+                language = DocumentationCompiler::get_language(line);
                 if (language == NULL) {
-                    Complete paragraph or code3.1.1.1.7;
-                    Begin passage if not already in one3.1.1.1.6;
+                    Complete paragraph or code6.1.1.1.7;
+                    Begin passage if not already in one6.1.1.1.6;
                     TEMPORARY_TEXT(err)
                     WRITE_TO(err, "cannot find a language called '%S'", line);
                     tree_node *E = DocumentationTree::new_source_error(cd->tree, err);
@@ -262,102 +465,102 @@ part of paragraphs; or indented ones, which are always part of code samples.
                     DISCARD_TEXT(err)
                 }
             } else {
-                Begin code3.1.1.1.11;
-                Insert line in code sample3.1.1.1.13;
+                Begin code6.1.1.1.11;
+                Insert line in code sample6.1.1.1.13;
             }
         } else {
-            Insert line in code sample3.1.1.1.13;
+            Insert line in code sample6.1.1.1.13;
         }
     }
 
- -

§3.1.1.1.1. Insert a chapter heading3.1.1.1.1 = +

+

§6.1.1.1.1. Insert a chapter heading6.1.1.1.1 =

-    Complete passage if in one3.1.1.3;
+    Complete passage if in one6.1.1.3;
     chapter_number++;
     section_number = 0;
     int level = 1, id = cd->total_headings[0] + cd->total_headings[1] + cd->total_headings[2];
     cd->total_headings[1]++;
-    tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], level,
+    tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], mr.exp[0], level,
         id, chapter_number, section_number);
-    Place this new structural node in the tree3.1.1.1.1.1;
+    Place this new structural node in the tree6.1.1.1.1.1;
 
- -

§3.1.1.1.2. Insert a section heading3.1.1.1.2 = +

+

§6.1.1.1.2. Insert a section heading6.1.1.1.2 =

-    Complete passage if in one3.1.1.3;
+    Complete passage if in one6.1.1.3;
     section_number++;
     int level = 2, id = cd->total_headings[0] + cd->total_headings[1] + cd->total_headings[2];
     cd->total_headings[2]++;
-    tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], level,
+    tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], mr.exp[0], level,
         id, chapter_number, section_number);
-    Place this new structural node in the tree3.1.1.1.1.1;
+    Place this new structural node in the tree6.1.1.1.1.1;
 
- -

§3.1.1.1.3. Insert an example heading3.1.1.1.3 = +

+

§6.1.1.1.3. Insert an example heading6.1.1.1.3 =

-    Complete passage if in one3.1.1.3;
+    Complete passage if in one6.1.1.3;
     int level = 3, star_count = Str::len(mr.exp[0]);
-    tree_node *new_node = DocumentationTree::new_example(cd->tree, mr.exp[1],
+    tree_node *new_node = DocumentationTree::new_example(cd->tree, mr.exp[1], NULL,
         star_count, ++(cd->total_examples));
-    Place this new structural node in the tree3.1.1.1.1.1;
+    Place this new structural node in the tree6.1.1.1.1.1;
     if (star_count == 0) {
-        Begin passage if not already in one3.1.1.1.6;
+        Begin passage if not already in one6.1.1.1.6;
         tree_node *E = DocumentationTree::new_source_error(cd->tree,
             I"this example should be marked (before the title) '*', '**', '***' or '****' for difficulty");
         Trees::make_child(E, current_passage);
     }
     if (star_count > 4) {
-        Begin passage if not already in one3.1.1.1.6;
+        Begin passage if not already in one6.1.1.1.6;
         tree_node *E = DocumentationTree::new_source_error(cd->tree,
             I"four stars '****' is the maximum difficulty rating allowed");
         Trees::make_child(E, current_passage);
     }
 
- -

§3.1.1.1.4. Begin a phrase definition3.1.1.1.4 = +

+

§6.1.1.1.4. Begin a phrase definition6.1.1.1.4 =

-    Check for runaway phrase definitions3.1.1.2;
+    Check for runaway phrase definitions6.1.1.2;
     if (current_phrase_defn == NULL) {
-        Begin passage if not already in one3.1.1.1.6;
-        Complete paragraph or code3.1.1.1.7;
+        Begin passage if not already in one6.1.1.1.6;
+        Complete paragraph or code6.1.1.1.7;
         current_phrase_defn =
             DocumentationTree::new_phrase_defn(cd->tree, mr.exp[0], mr.exp[1]);
         Trees::make_child(current_phrase_defn, current_passage);
-        Complete passage if in one3.1.1.3;
+        Complete passage if in one6.1.1.3;
     }
 
- -

§3.1.1.1.5. End a phrase definition3.1.1.1.5 = +

+

§6.1.1.1.5. End a phrase definition6.1.1.1.5 =

     if (current_phrase_defn) {
-        Complete passage if in one3.1.1.3;
+        Complete passage if in one6.1.1.3;
         current_passage = current_phrase_defn->parent;
         current_phrase_defn = NULL;
     } else {
-        Begin passage if not already in one3.1.1.1.6;
+        Begin passage if not already in one6.1.1.1.6;
         tree_node *E = DocumentationTree::new_source_error(cd->tree,
             I"{end} without {defn}");
         Trees::make_child(E, current_passage);
     }
     language = default_language;
 
- -

§3.1.1.1.1.1. Place this new structural node in the tree3.1.1.1.1.1 = +

+

§6.1.1.1.1.1. Place this new structural node in the tree6.1.1.1.1.1 =

-    Check for runaway phrase definitions3.1.1.2;
+    Check for runaway phrase definitions6.1.1.2;
     for (int j=level-1; j>=0; j--)
         if (current_headings[j]) {
             Trees::make_child(new_node, current_headings[j]);
@@ -367,21 +570,21 @@ part of paragraphs; or indented ones, which are always part of code samples.
     for (int j=level+1; j<4; j++) current_headings[j] = NULL;
     language = default_language;
 
- -

§3.1.1.2. Check for runaway phrase definitions3.1.1.2 = +

+

§6.1.1.2. Check for runaway phrase definitions6.1.1.2 =

     if (current_phrase_defn) {
-        Begin passage if not already in one3.1.1.1.6;
+        Begin passage if not already in one6.1.1.1.6;
         tree_node *E = DocumentationTree::new_source_error(cd->tree,
             I"{defn} has no {end}");
         Trees::make_child(E, current_passage);
         current_phrase_defn = NULL;
     }
 
- -

§3.1.1.1.6. Begin passage if not already in one3.1.1.1.6 = +

+

§6.1.1.1.6. Begin passage if not already in one6.1.1.1.6 =

@@ -397,56 +600,56 @@ part of paragraphs; or indented ones, which are always part of code samples.
         current_paragraph = NULL;
     }
 
- -

§3.1.1.3. Complete passage if in one3.1.1.3 = +

+

§6.1.1.3. Complete passage if in one6.1.1.3 =

     if (current_passage) {
-        Complete paragraph or code3.1.1.1.7;
+        Complete paragraph or code6.1.1.1.7;
         current_passage = NULL;
     }
 
- -

§3.1.1.1.7. Complete paragraph or code3.1.1.1.7 = +

+

§6.1.1.1.7. Complete paragraph or code6.1.1.1.7 =

-    if (current_paragraph) Complete paragraph3.1.1.1.7.1
-    if (current_code) Complete code3.1.1.1.7.2
+    if (current_paragraph) Complete paragraph6.1.1.1.7.1
+    if (current_code) Complete code6.1.1.1.7.2
 
- -

§3.1.1.1.8. Line breaks are treated as spaces in the content of a paragraph, so that +

+

§6.1.1.1.8. Line breaks are treated as spaces in the content of a paragraph, so that P->content here can be a long text but one which contains no line breaks.

-

Begin paragraph3.1.1.1.8 = +

Begin paragraph6.1.1.1.8 =

-    Complete paragraph or code3.1.1.1.7;
-    Begin passage if not already in one3.1.1.1.6;
+    Complete paragraph or code6.1.1.1.7;
+    Begin passage if not already in one6.1.1.1.6;
     current_paragraph = DocumentationTree::new_paragraph(cd->tree, NULL);
     Trees::make_child(current_paragraph, current_passage);
 
- -

§3.1.1.1.9. Insert space in paragraph3.1.1.1.9 = +

+

§6.1.1.1.9. Insert space in paragraph6.1.1.1.9 =

     cdoc_paragraph *P = RETRIEVE_POINTER_cdoc_paragraph(current_paragraph->content);
     if (Str::len(P->content) > 0) WRITE_TO(P->content, " ");
 
- -

§3.1.1.1.10. Insert line in paragraph3.1.1.1.10 = +

+

§6.1.1.1.10. Insert line in paragraph6.1.1.1.10 =

     cdoc_paragraph *P = RETRIEVE_POINTER_cdoc_paragraph(current_paragraph->content);
     WRITE_TO(P->content, "%S", line);
 
- -

§3.1.1.1.7.1. Complete paragraph3.1.1.1.7.1 = +

+

§6.1.1.1.7.1. Complete paragraph6.1.1.1.7.1 =

@@ -454,18 +657,18 @@ part of paragraphs; or indented ones, which are always part of code samples.
         current_paragraph = NULL;
     }
 
- -

§3.1.1.1.11. Line breaks are more significant in code samples, of course. Blank lines +

+

§6.1.1.1.11. Line breaks are more significant in code samples, of course. Blank lines at the end of a code sample are stripped out; and they cannot appear at the start of a code sample either, since a non-blank indented line is needed to trigger one.

-

Begin code3.1.1.1.11 = +

Begin code6.1.1.1.11 =

-    Complete paragraph or code3.1.1.1.7;
-    Begin passage if not already in one3.1.1.1.6;
+    Complete paragraph or code6.1.1.1.7;
+    Begin passage if not already in one6.1.1.1.6;
 
     int paste_me = FALSE, continue_me = FALSE;
     if ((Str::get_at(line, 0) == '*') &&
@@ -482,7 +685,23 @@ of a code sample either, since a non-blank indented line is needed to trigger on
         Str::delete_first_character(line);
         Str::trim_white_space(line);
         continue_me = TRUE;
+    } else if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == '*') &&
+        (Str::get_at(line, 2) == '}')) {
+        Str::delete_first_character(line);
+        Str::delete_first_character(line);
+        Str::delete_first_character(line);
+        Str::trim_white_space(line);
+        paste_me = TRUE;
+    } else if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == '*') &&
+        (Str::get_at(line, 2) == '*') && (Str::get_at(line, 3) == '}')) {
+        Str::delete_first_character(line);
+        Str::delete_first_character(line);
+        Str::delete_first_character(line);
+        Str::delete_first_character(line);
+        Str::trim_white_space(line);
+        continue_me = TRUE;
     }
+
     current_code = DocumentationTree::new_code_sample(cd->tree, paste_me, language);
     if (continue_me) {
         if (last_paste_code) {
@@ -502,8 +721,8 @@ of a code sample either, since a non-blank indented line is needed to trigger on
     pending_code_sample_blanks = 0;
     code_is_tabular = FALSE;
 
- -

§3.1.1.1.12. Insert line break in code3.1.1.1.12 = +

+

§6.1.1.1.12. Insert line break in code6.1.1.1.12 =

@@ -512,8 +731,8 @@ of a code sample either, since a non-blank indented line is needed to trigger on
         code_is_tabular = FALSE;
     }
 
- -

§3.1.1.1.13. Insert line in code sample3.1.1.1.13 = +

+

§6.1.1.1.13. Insert line in code sample6.1.1.1.13 =

@@ -528,8 +747,8 @@ of a code sample either, since a non-blank indented line is needed to trigger on
     Trees::make_child(DocumentationTree::new_code_line(cd->tree, line, indentation-1, code_is_tabular),
         current_code);
 
- -

§3.1.1.1.7.2. Complete code3.1.1.1.7.2 = +

+

§6.1.1.1.7.2. Complete code6.1.1.1.7.2 =

@@ -538,11 +757,11 @@ of a code sample either, since a non-blank indented line is needed to trigger on
         code_is_tabular = FALSE;
     }
 
- -

§4.

+ +

§7.

-programming_language *DocumentationCompiler::get_language(text_stream *name) {
+programming_language *DocumentationCompiler::get_language(text_stream *name) {
     inbuild_nest *N = Supervisor::internal();
     if (N == NULL) return NULL;
     pathname *LP = Pathnames::down(Nests::get_location(N), I"PLs");
diff --git a/docs/supervisor-module/7-dr.html b/docs/supervisor-module/7-dr.html
index 09157c4e5..f9e82e969 100644
--- a/docs/supervisor-module/7-dr.html
+++ b/docs/supervisor-module/7-dr.html
@@ -137,7 +137,7 @@ except the examples, and then up to 26 pages holding the content of examples A t
 

-void DocumentationRenderer::as_HTML(pathname *P, compiled_documentation *cd, text_stream *extras) {
+void DocumentationRenderer::as_HTML(pathname *P, compiled_documentation *cd, text_stream *extras) {
     if (cd) {
         text_stream *OUT = DocumentationRenderer::open_subpage(P, I"index.html");
         if (OUT) {
@@ -551,12 +551,7 @@ in a hierarchical fashion.
             if (M) WRITE_TO(matter, "\n\n");
         } else break;
     }
-    TEMPORARY_TEXT(paste)
-    WRITE_TO(paste, "<span class=\"paste\">%cV</span>", 0x2318);
-     the Unicode for "place of interest", the Swedish castle which became the Apple action symbol
-    PasteButtons::paste_text_using(OUT, matter, paste);
-    DISCARD_TEXT(paste)
-    WRITE("&nbsp;");
+    ExtensionWebsite::paste_button(OUT, matter);
     DISCARD_TEXT(matter)
 
@@ -677,7 +672,6 @@ and this is fiddly but elementary in the usual way of HTML tables:

-    HTML::end_html_row(OUT);
     HTML::end_html_table(OUT);
     HTML::begin_span(OUT, I"indexdullblue");
 
@@ -722,6 +716,8 @@ in the next section. HTML::end_span(OUT); HTML::begin_span(OUT, I"indexblack"); DocumentationRenderer::render_text(OUT, E->name); + HTML_TAG("br"); + DocumentationRenderer::render_text(OUT, E->description); HTML::end_span(OUT); HTML_CLOSE("b"); diff --git a/docs/supervisor-module/7-dt.html b/docs/supervisor-module/7-dt.html index 2e70f2eef..84b488141 100644 --- a/docs/supervisor-module/7-dt.html +++ b/docs/supervisor-module/7-dt.html @@ -100,7 +100,7 @@ function togglePopup(material_id) { &DocumentationTree::source_error_verifier); } heterogeneous_tree *tree = Trees::new(cdoc_tree_TT); - Trees::make_root(tree, DocumentationTree::new_heading(tree, I"(root)", 0, 0, 0, 0)); + Trees::make_root(tree, DocumentationTree::new_heading(tree, I"(root)", NULL, 0, 0, 0, 0)); return tree; }
@@ -124,19 +124,21 @@ which is otherwise something like typedef struct cdoc_heading { struct text_stream *count; struct text_stream *name; + struct text_stream *recognition_name; int level; 0 = root, 1 = chapter, 2 = section int ID; CLASS_DEFINITION } cdoc_heading; -tree_node *DocumentationTree::new_heading(heterogeneous_tree *tree, - text_stream *title, int level, int ID, int cc, int sc) { +tree_node *DocumentationTree::new_heading(heterogeneous_tree *tree, + text_stream *title, text_stream *recognise_as, int level, int ID, int cc, int sc) { cdoc_heading *H = CREATE(cdoc_heading); H->count = Str::new(); if (cc > 0) WRITE_TO(H->count, "%d", cc); if ((cc > 0) && (sc > 0)) WRITE_TO(H->count, "."); if (sc > 0) WRITE_TO(H->count, "%d", sc); H->name = Str::duplicate(title); + H->recognition_name = Str::duplicate(recognise_as); H->level = level; H->ID = ID; return Trees::new_node(tree, heading_TNT, STORE_POINTER_cdoc_heading(H)); @@ -166,23 +168,25 @@ letters are unique from A, B, C, ...
 typedef struct cdoc_example {
     struct text_stream *name;
+    struct text_stream *description;
     int star_count;
     int number;
     char letter;
     CLASS_DEFINITION
 } cdoc_example;
 
-tree_node *DocumentationTree::new_example(heterogeneous_tree *tree,
-    text_stream *title, int star_count, int ecount) {
+tree_node *DocumentationTree::new_example(heterogeneous_tree *tree,
+    text_stream *title, text_stream *desc, int star_count, int ecount) {
     cdoc_example *E = CREATE(cdoc_example);
     E->name = Str::duplicate(title);
+    E->description = Str::duplicate(desc);
     E->star_count = star_count;
     E->number = ecount;
     E->letter = 'A' + (char) ecount - 1;
     return Trees::new_node(tree, example_TNT, STORE_POINTER_cdoc_example(E));
 }
 
- +

§6. An example node always has a single child: the passage containing its content.

@@ -202,7 +206,7 @@ or headings. CLASS_DEFINITION } cdoc_passage; -tree_node *DocumentationTree::new_passage(heterogeneous_tree *tree) { +tree_node *DocumentationTree::new_passage(heterogeneous_tree *tree) { cdoc_passage *P = CREATE(cdoc_passage); return Trees::new_node(tree, passage_TNT, STORE_POINTER_cdoc_passage(P)); } @@ -235,7 +239,7 @@ phrases. The "tag" is optional and is for potential cross-referencing; the CLASS_DEFINITION } cdoc_phrase_defn; -tree_node *DocumentationTree::new_phrase_defn(heterogeneous_tree *tree, +tree_node *DocumentationTree::new_phrase_defn(heterogeneous_tree *tree, text_stream *tag, text_stream *prototype) { cdoc_phrase_defn *P = CREATE(cdoc_phrase_defn); P->tag = Str::duplicate(tag); @@ -263,7 +267,7 @@ phrases. The "tag" is optional and is for potential cross-referencing; the CLASS_DEFINITION } cdoc_paragraph; -tree_node *DocumentationTree::new_paragraph(heterogeneous_tree *tree, +tree_node *DocumentationTree::new_paragraph(heterogeneous_tree *tree, text_stream *content) { cdoc_paragraph *P = CREATE(cdoc_paragraph); P->content = Str::duplicate(content); @@ -287,7 +291,7 @@ phrases. The "tag" is optional and is for potential cross-referencing; the struct programming_language *language; } cdoc_code_sample; -tree_node *DocumentationTree::new_code_sample(heterogeneous_tree *tree, int paste_me, +tree_node *DocumentationTree::new_code_sample(heterogeneous_tree *tree, int paste_me, programming_language *language) { cdoc_code_sample *C = CREATE(cdoc_code_sample); C->with_paste_marker = paste_me; @@ -323,7 +327,7 @@ at 0, and is measured in tab stops. CLASS_DEFINITION } cdoc_code_line; -tree_node *DocumentationTree::new_code_line(heterogeneous_tree *tree, +tree_node *DocumentationTree::new_code_line(heterogeneous_tree *tree, text_stream *content, int indentation, int tabular) { cdoc_code_line *C = CREATE(cdoc_code_line); C->content = Str::duplicate(content); @@ -348,7 +352,7 @@ at 0, and is measured in tab stops. CLASS_DEFINITION } cdoc_source_error; -tree_node *DocumentationTree::new_source_error(heterogeneous_tree *tree, +tree_node *DocumentationTree::new_source_error(heterogeneous_tree *tree, text_stream *content) { cdoc_source_error *E = CREATE(cdoc_source_error); E->error_message = Str::duplicate(content); @@ -371,6 +375,7 @@ if not. dc_find_example_task task; task.to_find_example = eg; task.to_find_heading = NULL; + task.to_find_section = NULL; task.result = NULL; Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0); return task.result; @@ -381,6 +386,18 @@ if not. dc_find_example_task task; task.to_find_example = 0; task.to_find_heading = Str::new(); WRITE_TO(task.to_find_heading, "%d", ch); + task.to_find_section = NULL; + task.result = NULL; + Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0); + return task.result; +} + +tree_node *DocumentationTree::find_section(heterogeneous_tree *T, text_stream *name) { + if (Str::len(name) == 0) return NULL; + dc_find_example_task task; + task.to_find_example = 0; + task.to_find_heading = NULL; + task.to_find_section = name; task.result = NULL; Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0); return task.result; @@ -389,6 +406,7 @@ if not. typedef struct dc_find_example_task { int to_find_example; struct text_stream *to_find_heading; + struct text_stream *to_find_section; struct tree_node *result; } dc_find_example_task; @@ -409,6 +427,15 @@ if not. return FALSE; } } + if ((task->to_find_section) && (N->type == heading_TNT)) { + + cdoc_heading *E = RETRIEVE_POINTER_cdoc_heading(N->content); +LOG("Want %S find %S\n", task->to_find_section, E->recognition_name); + if ((E->level == 2) && (Str::eq_insensitive(E->recognition_name, task->to_find_section))) { + task->result = N; + return FALSE; + } + } return TRUE; } diff --git a/docs/supervisor-module/7-eip.html b/docs/supervisor-module/7-eip.html index 5ad588aa3..3607f1021 100644 --- a/docs/supervisor-module/7-eip.html +++ b/docs/supervisor-module/7-eip.html @@ -500,7 +500,7 @@ the usual ones seen in Mac OS X applications such as iTunes. } inform_extension *E = Extensions::from_copy(res->copy); - parse_node *at = Extensions::get_inclusion_sentence(E); + parse_node *at = Extensions::get_inclusion_sentence(E); if (at) { wording W = Node::get_text(at); source_location sl = Lexer::word_location(Wordings::first_wn(W)); @@ -518,7 +518,7 @@ the usual ones seen in Mac OS X applications such as iTunes. WRITE(" "); TEMPORARY_TEXT(inclusion_text) WRITE_TO(inclusion_text, "Include %X.\n\n\n", res->copy->edition->work); - PasteButtons::paste_text(OUT, inclusion_text); + ExtensionWebsite::paste_button(OUT, inclusion_text); DISCARD_TEXT(inclusion_text) ExtensionIndex::add_to_key(key_list, PASTE_SYMBOL, I"Source text to Include this (click to paste in)"); @@ -593,7 +593,7 @@ the first and last word and just look at what is in between: else WRITE("Installed in this project"); } else { - text_stream *R = Extensions::get_rubric(Extensions::from_copy(res->copy)); + text_stream *R = Extensions::get_rubric(Extensions::from_copy(res->copy)); if (Str::len(R) > 0) WRITE("%S", R); else WRITE("--"); } HTML::end_span(OUT); @@ -604,7 +604,7 @@ the first and last word and just look at what is in between:
     HTML::begin_span(OUT, I"smaller");
-    text_stream *R = Extensions::get_rubric(Extensions::from_copy(res->copy));
+    text_stream *R = Extensions::get_rubric(Extensions::from_copy(res->copy));
     if (Str::len(R) > 0) WRITE("%S", R); else WRITE("--");
     HTML::end_span(OUT);
 
@@ -639,7 +639,7 @@ the first and last word and just look at what is in between:
define PROBLEM_SYMBOL "border=\"0\" height=\"12\" src=\"inform:/doc_images/census_problem.png\""
 define REVEAL_SYMBOL "border=\"0\" src=\"inform:/doc_images/Reveal.png\""
 define HELP_SYMBOL "border=\"0\" src=\"inform:/doc_images/help.png\""
-define PASTE_SYMBOL "border=\"0\" src=\"inform:/doc_images/paste.png\""
+define PASTE_SYMBOL "paste"
 define BUILT_IN_SYMBOL "border=\"0\" src=\"inform:/doc_images/builtin_ext.png\""
 define PROJECT_SPECIFIC_SYMBOL "border=\"0\" src=\"inform:/doc_images/folder4.png\""
 define LEGACY_AREA_SYMBOL "border=\"0\" src=\"inform:/doc_images/pspec_ext.png\""
@@ -651,6 +651,7 @@ the first and last word and just look at what is in between:
     struct text_stream *image_URL;
     struct text_stream *gloss;
     int displayed;
+    int ideograph;
     CLASS_DEFINITION
 } extensions_key_item;
 
@@ -667,6 +668,8 @@ the first and last word and just look at what is in between:
         eki->image_URL = Str::duplicate(as_text);
         eki->gloss = Str::duplicate(gloss);
         eki->displayed = FALSE;
+        eki->ideograph = FALSE;
+        if (Str::eq(as_text, I"paste")) eki->ideograph = TRUE;
         ADD_TO_LINKED_LIST(eki, extensions_key_item, L);
     }
     DISCARD_TEXT(as_text)
@@ -686,7 +689,7 @@ the first and last word and just look at what is in between:
         extensions_key_item *eki;
         LOOP_OVER_LINKED_LIST(eki, extensions_key_item, L) {
             if (Str::eq(eki->image_URL, as_text)) {
-                HTML_TAG_WITH("img", "%S", eki->image_URL);
+                ExtensionIndex::render_icon(OUT, eki);
                 WRITE("&nbsp;%S &nbsp;&nbsp;", eki->gloss);
                 eki->displayed = TRUE;
             }
@@ -696,13 +699,21 @@ the first and last word and just look at what is in between:
     extensions_key_item *eki;
     LOOP_OVER_LINKED_LIST(eki, extensions_key_item, L) {
         if (eki->displayed == FALSE) {
-            HTML_TAG_WITH("img", "%S", eki->image_URL);
+            ExtensionIndex::render_icon(OUT, eki);
             WRITE("&nbsp;%S &nbsp;&nbsp;", eki->gloss);
             eki->displayed = TRUE;
         }
     }
     HTML_CLOSE("p");
 }
+
+void ExtensionIndex::render_icon(OUTPUT_STREAM, extensions_key_item *eki) {
+    if (eki->ideograph) {
+        ExtensionWebsite::paste_ideograph(OUT);
+    } else {
+        HTML_TAG_WITH("img", "%S", eki->image_URL);
+    }
+}
 

§4. Icons for virtual machines. And everything else is cosmetic: printing, or showing icons to signify, diff --git a/docs/supervisor-module/7-ti.html b/docs/supervisor-module/7-ti.html index 7fa0ce1c5..d5208cc03 100644 --- a/docs/supervisor-module/7-ti.html +++ b/docs/supervisor-module/7-ti.html @@ -197,7 +197,7 @@ produces a second report. WRITE("Specifically:"); HTML_CLOSE("p"); Copies::list_attached_errors_to_HTML(OUT, C); - text_stream *rubric = Extensions::get_rubric(Extensions::from_copy(C)); + text_stream *rubric = Extensions::get_rubric(Extensions::from_copy(C)); if (Str::len(rubric) > 0) { WRITE("The extension says this about itself:"); HTML_CLOSE("p"); @@ -213,7 +213,7 @@ produces a second report.

     HTML_OPEN("p");
     WRITE("This looks like a valid extension");
-    text_stream *rubric = Extensions::get_rubric(Extensions::from_copy(C));
+    text_stream *rubric = Extensions::get_rubric(Extensions::from_copy(C));
     if (Str::len(rubric) > 0) {
         WRITE(", and says this about itself:");
         HTML_CLOSE("p");
diff --git a/docs/supervisor-module/7-tm.html b/docs/supervisor-module/7-tm.html
index 672af55f7..64dbbcc6c 100644
--- a/docs/supervisor-module/7-tm.html
+++ b/docs/supervisor-module/7-tm.html
@@ -283,6 +283,23 @@ examples provided in the extension.
     no_EXW_breadcrumbs = 0;
 }
 
+

§8. This is a new-look paste button, using a "command-V" ideograph rather than +a somewhat enigmatic icon. +

+ +
+void ExtensionWebsite::paste_button(OUTPUT_STREAM, text_stream *matter) {
+    TEMPORARY_TEXT(paste)
+    ExtensionWebsite::paste_ideograph(paste);
+    PasteButtons::paste_text_using(OUT, matter, paste);
+    DISCARD_TEXT(paste)
+    WRITE("&nbsp;");
+}
+void ExtensionWebsite::paste_ideograph(OUTPUT_STREAM) {
+     the Unicode for "place of interest", the Swedish castle which became the Apple action symbol
+    WRITE("<span class=\"paste\">%cV</span>", 0x2318);
+}
+
diff --git a/inbuild/supervisor-module/Chapter 1/Supervisor Module.w b/inbuild/supervisor-module/Chapter 1/Supervisor Module.w index 91467f624..3533367a5 100644 --- a/inbuild/supervisor-module/Chapter 1/Supervisor Module.w +++ b/inbuild/supervisor-module/Chapter 1/Supervisor Module.w @@ -47,6 +47,7 @@ which use this module: @e inform_template_CLASS @e kit_configuration_CLASS @e kit_dependency_CLASS +@e satellite_test_case_CLASS = DECLARE_CLASS(build_methodology) @@ -86,6 +87,7 @@ DECLARE_CLASS(inform_project) DECLARE_CLASS(inform_template) DECLARE_CLASS(kit_configuration) DECLARE_CLASS(kit_dependency) +DECLARE_CLASS(satellite_test_case) @ Like all modules, this one must define a |start| and |end| function: diff --git a/inbuild/supervisor-module/Chapter 4/Extension Bundle Manager.w b/inbuild/supervisor-module/Chapter 4/Extension Bundle Manager.w index c721e8170..6e08bd3a2 100644 --- a/inbuild/supervisor-module/Chapter 4/Extension Bundle Manager.w +++ b/inbuild/supervisor-module/Chapter 4/Extension Bundle Manager.w @@ -331,7 +331,7 @@ inbuild_copy *ExtensionBundleManager::claim_folder_as_copy(pathname *P, inbuild_ Str::delete_last_character(subdir); if (Str::eq(subdir, I"Examples")) { ; - } else if (Str::eq(subdir, I"Images")) { + } else if (Str::eq(subdir, I"Tests")) { ; } else { TEMPORARY_TEXT(error_text) diff --git a/inbuild/supervisor-module/Chapter 5/Extension Services.w b/inbuild/supervisor-module/Chapter 5/Extension Services.w index 9a49f3211..d9a711c8f 100644 --- a/inbuild/supervisor-module/Chapter 5/Extension Services.w +++ b/inbuild/supervisor-module/Chapter 5/Extension Services.w @@ -777,9 +777,9 @@ void Extensions::read_source_text_for(inform_extension *E) { SVEXPLAIN(1, "(from %f)\n", F); DISCARD_TEXT(synopsis) if (E->read_into_file) { - E->documentation = - DocumentationCompiler::compile( - TextFromFiles::torn_off_documentation(E->read_into_file), E); + text_stream *doc = TextFromFiles::torn_off_documentation(E->read_into_file); + if (Str::len(doc) > 0) E->documentation = DocumentationCompiler::compile(doc, E); + else E->documentation = NULL; E->read_into_file->your_ref = STORE_POINTER_inbuild_copy(E->as_copy); @; E->body_text_unbroken = FALSE; @@ -830,36 +830,24 @@ compiled_documentation *Extensions::get_documentation(inform_extension *E) { if (E->documentation_sought == FALSE) { if (E->as_copy->location_if_path) { pathname *D = Pathnames::down(E->as_copy->location_if_path, I"Documentation"); - filename *F = Filenames::in(D, I"Documentation.txt"); - if (TextFiles::exists(F)) @; + if (Directories::exists(D)) @; } E->documentation_sought = TRUE; } return E->documentation; } -@ = - if (E->documentation == NULL) { +@ = + if (E->documentation) { TEMPORARY_TEXT(error_text) WRITE_TO(error_text, "this extension provides documentation both as a file and in its source"); Copies::attach_error(E->as_copy, CopyErrors::new_T(EXT_MISWORDED_CE, -1, error_text)); DISCARD_TEXT(error_text) } else { - TEMPORARY_TEXT(temp) - TextFiles::read(F, FALSE, "unable to read file of extension documentation", TRUE, - &Extensions::read_extension_file_helper, NULL, temp); - E->documentation = DocumentationCompiler::compile(temp, E); - DISCARD_TEXT(temp) + E->documentation = DocumentationCompiler::compile_from_path(D, E); } -@ = -void Extensions::read_extension_file_helper(text_stream *text, text_file_position *tfp, - void *v_state) { - text_stream *contents = (text_stream *) v_state; - WRITE_TO(contents, "%S\n", text); -} - @ And this serves the |-document| feature of inbuild: = diff --git a/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w b/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w index 0f09ac26c..a32683a5c 100644 --- a/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w +++ b/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w @@ -14,6 +14,7 @@ typedef struct compiled_documentation { int total_headings[3]; int total_examples; int empty; + struct linked_list *cases; /* of |satellite_test_case| */ CLASS_DEFINITION } compiled_documentation; @@ -28,11 +29,200 @@ compiled_documentation *DocumentationCompiler::new_wrapper(text_stream *source) cd->total_headings[1] = 0; cd->total_headings[2] = 0; cd->empty = FALSE; + cd->cases = NEW_LINKED_LIST(satellite_test_case); return cd; } +typedef struct satellite_test_case { + int is_example; + struct text_stream *owning_heading; + struct tree_node *owning_node; + struct compiled_documentation *owner; + struct text_stream *short_name; + struct filename *test_file; + struct filename *ideal_transcript; + CLASS_DEFINITION +} satellite_test_case; + @ We can compile either from a file... += +compiled_documentation *DocumentationCompiler::compile_from_path(pathname *P, + inform_extension *associated_extension) { + filename *F = Filenames::in(P, I"Documentation.txt"); + if (TextFiles::exists(F) == FALSE) return NULL; + compiled_documentation *cd = + DocumentationCompiler::compile_from_file(F, associated_extension); + if (cd == NULL) return NULL; + pathname *EP = Pathnames::down(P, I"Examples"); + int egs = TRUE; + @; + egs = FALSE; + EP = Pathnames::down(P, I"Tests"); + @; + return cd; +} + +@ = + scan_directory *D = Directories::open(EP); + TEMPORARY_TEXT(leafname) + while (Directories::next(D, leafname)) { + wchar_t first = Str::get_first_char(leafname), last = Str::get_last_char(leafname); + if (Platform::is_folder_separator(last)) continue; + if (first == '.') continue; + if (first == '(') continue; + text_stream *short_name = Str::new(); + filename *F = Filenames::in(EP, leafname); + Filenames::write_unextended_leafname(short_name, F); + if ((Str::get_at(short_name, Str::len(short_name)-2) == '-') && + ((Str::get_at(short_name, Str::len(short_name)-1) == 'I') + || (Str::get_at(short_name, Str::len(short_name)-1) == 'i'))) + continue; + satellite_test_case *stc = CREATE(satellite_test_case); + stc->is_example = egs; + stc->owning_heading = NULL; + stc->owning_node = NULL; + stc->owner = cd; + stc->short_name = short_name; + stc->test_file = F; + stc->ideal_transcript = NULL; + TEMPORARY_TEXT(ideal_leafname) + WRITE_TO(ideal_leafname, "%S-I.txt", stc->short_name); + filename *IF = Filenames::in(EP, ideal_leafname); + if (TextFiles::exists(IF)) stc->ideal_transcript = IF; + DISCARD_TEXT(ideal_leafname) + if (stc->is_example) { + @; + } + ADD_TO_LINKED_LIST(stc, satellite_test_case, cd->cases); + } + DISCARD_TEXT(leafname) + Directories::close(D); + +@ + += +typedef struct example_scanning_state { + int star_count; + struct text_stream *long_title; + struct text_stream *body_text; + struct text_stream *placement; + struct text_stream *desc; + struct linked_list *errors; + struct heterogeneous_tree *tree; + struct text_stream *scanning; + int past_header; +} example_scanning_state; + +@ = + example_scanning_state ess; + ess.star_count = 1; + ess.long_title = NULL; + ess.body_text = Str::new(); + ess.placement = NULL; + ess.desc = NULL; + ess.errors = NEW_LINKED_LIST(tree_node); + ess.tree = cd->tree; + ess.past_header = FALSE; + ess.scanning = Str::new(); WRITE_TO(ess.scanning, "%S", Filenames::get_leafname(stc->test_file)); + TextFiles::read(stc->test_file, FALSE, "unable to read file of example", TRUE, + &DocumentationCompiler::read_example_helper, NULL, &ess); + + tree_node *placement_node = NULL; + if (Str::len(ess.placement) == 0) { + DocumentationCompiler::example_error(&ess, + I"example does not give its Location"); + } else { + placement_node = DocumentationTree::find_section(cd->tree, ess.placement); + if (placement_node == NULL) { + DocumentationCompiler::example_error(&ess, + I"example gives a Location which is not the name of any section"); + } + } + if (Str::len(ess.desc) == 0) { + DocumentationCompiler::example_error(&ess, + I"example does not give its Description"); + } + tree_node *content_node = NULL; + if (Str::len(ess.body_text) == 0) { + DocumentationCompiler::example_error(&ess, + I"example does not give any actual content"); + } else { + compiled_documentation *ecd = + DocumentationCompiler::compile(ess.body_text, associated_extension); + if ((ecd) && (ecd->tree) && (ecd->tree->root) && + (ecd->tree->root->child) && + (ecd->tree->root->child->type == passage_TNT)) + content_node = ecd->tree->root->child; + else { + DocumentationCompiler::example_error(&ess, + I"example file content is missing or wrongly set out"); + } + } + tree_node *example_node = DocumentationTree::new_example(cd->tree, + ess.long_title, ess.desc, ess.star_count, ++(cd->total_examples)); + if (placement_node) Trees::make_child(example_node, placement_node); + if (content_node) Trees::make_child(content_node, example_node); + + tree_node *E; + LOOP_OVER_LINKED_LIST(E, tree_node, ess.errors) + Trees::make_child(E, cd->tree->root); + +@ = +void DocumentationCompiler::example_error(example_scanning_state *ess, text_stream *text) { + text_stream *err = Str::new(); + WRITE_TO(err, "Example file '%S': %S", ess->scanning, text); + tree_node *E = DocumentationTree::new_source_error(ess->tree, err); + ADD_TO_LINKED_LIST(E, tree_node, ess->errors); +} + +@ = +void DocumentationCompiler::read_example_helper(text_stream *text, text_file_position *tfp, + void *v_state) { + example_scanning_state *ess = (example_scanning_state *) v_state; + if (tfp->line_count == 1) { + match_results mr = Regexp::create_mr(); + if ((Regexp::match(&mr, text, L"Example *: *(%**) *(%c+?)")) || + (Regexp::match(&mr, text, L"Example *- *(%**) *(%c+?)"))) { + ess->star_count = Str::len(mr.exp[0]); + if (ess->star_count == 0) { + DocumentationCompiler::example_error(ess, + I"this example should be marked (before the title) '*', '**', '***' or '****' for difficulty"); + ess->star_count = 1; + } + if (ess->star_count > 4) { + DocumentationCompiler::example_error(ess, + I"four stars '****' is the maximum difficulty rating allowed"); + ess->star_count = 4; + } + ess->long_title = Str::duplicate(mr.exp[1]); + } else { + DocumentationCompiler::example_error(ess, + I"titling line of example file is malformed"); + } + Regexp::dispose_of(&mr); + } else if (ess->past_header == FALSE) { + if (Str::is_whitespace(text)) { ess->past_header = TRUE; return; } + match_results mr = Regexp::create_mr(); + if (Regexp::match(&mr, text, L"(%C+?) *: *(%c+?)")) { + if (Str::eq(mr.exp[0], I"Location")) ess->placement = Str::duplicate(mr.exp[1]); + else if (Str::eq(mr.exp[0], I"Description")) ess->desc = Str::duplicate(mr.exp[1]); + else { + DocumentationCompiler::example_error(ess, + I"unknown datum in header line of example file"); + } + } else { + DocumentationCompiler::example_error(ess, + I"header line of example file is malformed"); + } + Regexp::dispose_of(&mr); + } else { + WRITE_TO(ess->body_text, "%S\n", text); + } +} + +@ + = compiled_documentation *DocumentationCompiler::compile_from_file(filename *F, inform_extension *associated_extension) { @@ -197,7 +387,7 @@ part of paragraphs; or indented ones, which are always part of code samples. section_number = 0; int level = 1, id = cd->total_headings[0] + cd->total_headings[1] + cd->total_headings[2]; cd->total_headings[1]++; - tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], level, + tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], mr.exp[0], level, id, chapter_number, section_number); @; @@ -206,14 +396,14 @@ part of paragraphs; or indented ones, which are always part of code samples. section_number++; int level = 2, id = cd->total_headings[0] + cd->total_headings[1] + cd->total_headings[2]; cd->total_headings[2]++; - tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], level, + tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], mr.exp[0], level, id, chapter_number, section_number); @; @ = @; int level = 3, star_count = Str::len(mr.exp[0]); - tree_node *new_node = DocumentationTree::new_example(cd->tree, mr.exp[1], + tree_node *new_node = DocumentationTree::new_example(cd->tree, mr.exp[1], NULL, star_count, ++(cd->total_examples)); @; if (star_count == 0) { @@ -341,7 +531,23 @@ of a code sample either, since a non-blank indented line is needed to trigger on Str::delete_first_character(line); Str::trim_white_space(line); continue_me = TRUE; + } else if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == '*') && + (Str::get_at(line, 2) == '}')) { + Str::delete_first_character(line); + Str::delete_first_character(line); + Str::delete_first_character(line); + Str::trim_white_space(line); + paste_me = TRUE; + } else if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == '*') && + (Str::get_at(line, 2) == '*') && (Str::get_at(line, 3) == '}')) { + Str::delete_first_character(line); + Str::delete_first_character(line); + Str::delete_first_character(line); + Str::delete_first_character(line); + Str::trim_white_space(line); + continue_me = TRUE; } + current_code = DocumentationTree::new_code_sample(cd->tree, paste_me, language); if (continue_me) { if (last_paste_code) { diff --git a/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w b/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w index a5ef4bc78..10be33815 100644 --- a/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w +++ b/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w @@ -471,12 +471,7 @@ int DocumentationRenderer::body_visitor(tree_node *N, void *state, int L) { if (M) WRITE_TO(matter, "\n\n"); } else break; } - TEMPORARY_TEXT(paste) - WRITE_TO(paste, "%cV", 0x2318); - /* the Unicode for "place of interest", the Swedish castle which became the Apple action symbol */ - PasteButtons::paste_text_using(OUT, matter, paste); - DISCARD_TEXT(paste) - WRITE(" "); + ExtensionWebsite::paste_button(OUT, matter); DISCARD_TEXT(matter) @ = @@ -568,7 +563,6 @@ and this is fiddly but elementary in the usual way of HTML tables: HTML::end_html_row(OUT); @ = - HTML::end_html_row(OUT); HTML::end_html_table(OUT); HTML::begin_span(OUT, I"indexdullblue"); @@ -611,6 +605,8 @@ void DocumentationRenderer::render_example_heading(OUTPUT_STREAM, tree_node *EN, HTML::end_span(OUT); HTML::begin_span(OUT, I"indexblack"); DocumentationRenderer::render_text(OUT, E->name); + HTML_TAG("br"); + DocumentationRenderer::render_text(OUT, E->description); HTML::end_span(OUT); HTML_CLOSE("b"); diff --git a/inbuild/supervisor-module/Chapter 7/Documentation Tree.w b/inbuild/supervisor-module/Chapter 7/Documentation Tree.w index 57cbd2763..c74945ff5 100644 --- a/inbuild/supervisor-module/Chapter 7/Documentation Tree.w +++ b/inbuild/supervisor-module/Chapter 7/Documentation Tree.w @@ -41,7 +41,7 @@ heterogeneous_tree *DocumentationTree::new(void) { &DocumentationTree::source_error_verifier); } heterogeneous_tree *tree = Trees::new(cdoc_tree_TT); - Trees::make_root(tree, DocumentationTree::new_heading(tree, I"(root)", 0, 0, 0, 0)); + Trees::make_root(tree, DocumentationTree::new_heading(tree, I"(root)", NULL, 0, 0, 0, 0)); return tree; } @@ -63,19 +63,21 @@ which is otherwise something like |5| (chapter 5) or |3.4| (section 4 in chapter typedef struct cdoc_heading { struct text_stream *count; struct text_stream *name; + struct text_stream *recognition_name; int level; /* 0 = root, 1 = chapter, 2 = section */ int ID; CLASS_DEFINITION } cdoc_heading; tree_node *DocumentationTree::new_heading(heterogeneous_tree *tree, - text_stream *title, int level, int ID, int cc, int sc) { + text_stream *title, text_stream *recognise_as, int level, int ID, int cc, int sc) { cdoc_heading *H = CREATE(cdoc_heading); H->count = Str::new(); if (cc > 0) WRITE_TO(H->count, "%d", cc); if ((cc > 0) && (sc > 0)) WRITE_TO(H->count, "."); if (sc > 0) WRITE_TO(H->count, "%d", sc); H->name = Str::duplicate(title); + H->recognition_name = Str::duplicate(recognise_as); H->level = level; H->ID = ID; return Trees::new_node(tree, heading_TNT, STORE_POINTER_cdoc_heading(H)); @@ -102,6 +104,7 @@ letters are unique from A, B, C, ... = typedef struct cdoc_example { struct text_stream *name; + struct text_stream *description; int star_count; int number; char letter; @@ -109,9 +112,10 @@ typedef struct cdoc_example { } cdoc_example; tree_node *DocumentationTree::new_example(heterogeneous_tree *tree, - text_stream *title, int star_count, int ecount) { + text_stream *title, text_stream *desc, int star_count, int ecount) { cdoc_example *E = CREATE(cdoc_example); E->name = Str::duplicate(title); + E->description = Str::duplicate(desc); E->star_count = star_count; E->number = ecount; E->letter = 'A' + (char) ecount - 1; @@ -289,6 +293,7 @@ tree_node *DocumentationTree::find_example(heterogeneous_tree *T, int eg) { dc_find_example_task task; task.to_find_example = eg; task.to_find_heading = NULL; + task.to_find_section = NULL; task.result = NULL; Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0); return task.result; @@ -299,6 +304,18 @@ tree_node *DocumentationTree::find_chapter(heterogeneous_tree *T, int ch) { dc_find_example_task task; task.to_find_example = 0; task.to_find_heading = Str::new(); WRITE_TO(task.to_find_heading, "%d", ch); + task.to_find_section = NULL; + task.result = NULL; + Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0); + return task.result; +} + +tree_node *DocumentationTree::find_section(heterogeneous_tree *T, text_stream *name) { + if (Str::len(name) == 0) return NULL; + dc_find_example_task task; + task.to_find_example = 0; + task.to_find_heading = NULL; + task.to_find_section = name; task.result = NULL; Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0); return task.result; @@ -307,6 +324,7 @@ tree_node *DocumentationTree::find_chapter(heterogeneous_tree *T, int ch) { typedef struct dc_find_example_task { int to_find_example; struct text_stream *to_find_heading; + struct text_stream *to_find_section; struct tree_node *result; } dc_find_example_task; @@ -327,5 +345,14 @@ int DocumentationTree::find_visit(tree_node *N, void *state, int L) { return FALSE; } } + if ((task->to_find_section) && (N->type == heading_TNT)) { + + cdoc_heading *E = RETRIEVE_POINTER_cdoc_heading(N->content); +LOG("Want %S find %S\n", task->to_find_section, E->recognition_name); + if ((E->level == 2) && (Str::eq_insensitive(E->recognition_name, task->to_find_section))) { + task->result = N; + return FALSE; + } + } return TRUE; } diff --git a/inbuild/supervisor-module/Chapter 7/Extensions Index Page.w b/inbuild/supervisor-module/Chapter 7/Extensions Index Page.w index 094770dd3..704d89579 100644 --- a/inbuild/supervisor-module/Chapter 7/Extensions Index Page.w +++ b/inbuild/supervisor-module/Chapter 7/Extensions Index Page.w @@ -383,7 +383,7 @@ the usual ones seen in Mac OS X applications such as iTunes. WRITE(" "); TEMPORARY_TEXT(inclusion_text) WRITE_TO(inclusion_text, "Include %X.\n\n\n", res->copy->edition->work); - PasteButtons::paste_text(OUT, inclusion_text); + ExtensionWebsite::paste_button(OUT, inclusion_text); DISCARD_TEXT(inclusion_text) ExtensionIndex::add_to_key(key_list, PASTE_SYMBOL, I"Source text to Include this (click to paste in)"); @@ -481,7 +481,7 @@ There is just no need to do this efficiently in either running time or memory. @d PROBLEM_SYMBOL "border=\"0\" height=\"12\" src=\"inform:/doc_images/census_problem.png\"" @d REVEAL_SYMBOL "border=\"0\" src=\"inform:/doc_images/Reveal.png\"" @d HELP_SYMBOL "border=\"0\" src=\"inform:/doc_images/help.png\"" -@d PASTE_SYMBOL "border=\"0\" src=\"inform:/doc_images/paste.png\"" +@d PASTE_SYMBOL "paste" @d BUILT_IN_SYMBOL "border=\"0\" src=\"inform:/doc_images/builtin_ext.png\"" @d PROJECT_SPECIFIC_SYMBOL "border=\"0\" src=\"inform:/doc_images/folder4.png\"" @d LEGACY_AREA_SYMBOL "border=\"0\" src=\"inform:/doc_images/pspec_ext.png\"" @@ -493,6 +493,7 @@ typedef struct extensions_key_item { struct text_stream *image_URL; struct text_stream *gloss; int displayed; + int ideograph; CLASS_DEFINITION } extensions_key_item; @@ -509,6 +510,8 @@ void ExtensionIndex::add_to_key(linked_list *L, char *URL, text_stream *gloss) { eki->image_URL = Str::duplicate(as_text); eki->gloss = Str::duplicate(gloss); eki->displayed = FALSE; + eki->ideograph = FALSE; + if (Str::eq(as_text, I"paste")) eki->ideograph = TRUE; ADD_TO_LINKED_LIST(eki, extensions_key_item, L); } DISCARD_TEXT(as_text) @@ -528,7 +531,7 @@ void ExtensionIndex::render_key(OUTPUT_STREAM, linked_list *L) { extensions_key_item *eki; LOOP_OVER_LINKED_LIST(eki, extensions_key_item, L) { if (Str::eq(eki->image_URL, as_text)) { - HTML_TAG_WITH("img", "%S", eki->image_URL); + ExtensionIndex::render_icon(OUT, eki); WRITE(" %S   ", eki->gloss); eki->displayed = TRUE; } @@ -538,7 +541,7 @@ void ExtensionIndex::render_key(OUTPUT_STREAM, linked_list *L) { extensions_key_item *eki; LOOP_OVER_LINKED_LIST(eki, extensions_key_item, L) { if (eki->displayed == FALSE) { - HTML_TAG_WITH("img", "%S", eki->image_URL); + ExtensionIndex::render_icon(OUT, eki); WRITE(" %S   ", eki->gloss); eki->displayed = TRUE; } @@ -546,6 +549,14 @@ void ExtensionIndex::render_key(OUTPUT_STREAM, linked_list *L) { HTML_CLOSE("p"); } +void ExtensionIndex::render_icon(OUTPUT_STREAM, extensions_key_item *eki) { + if (eki->ideograph) { + ExtensionWebsite::paste_ideograph(OUT); + } else { + HTML_TAG_WITH("img", "%S", eki->image_URL); + } +} + @h Icons for virtual machines. And everything else is cosmetic: printing, or showing icons to signify, the current VM or some set of permitted VMs. The following plots the diff --git a/inbuild/supervisor-module/Chapter 7/The Mini-Website.w b/inbuild/supervisor-module/Chapter 7/The Mini-Website.w index 79712c491..bcceb30bd 100644 --- a/inbuild/supervisor-module/Chapter 7/The Mini-Website.w +++ b/inbuild/supervisor-module/Chapter 7/The Mini-Website.w @@ -216,3 +216,19 @@ void ExtensionWebsite::titling_and_navigation(OUTPUT_STREAM, text_stream *subtit HTML_CLOSE("div"); no_EXW_breadcrumbs = 0; } + +@ This is a new-look paste button, using a "command-V" ideograph rather than +a somewhat enigmatic icon. + += +void ExtensionWebsite::paste_button(OUTPUT_STREAM, text_stream *matter) { + TEMPORARY_TEXT(paste) + ExtensionWebsite::paste_ideograph(paste); + PasteButtons::paste_text_using(OUT, matter, paste); + DISCARD_TEXT(paste) + WRITE(" "); +} +void ExtensionWebsite::paste_ideograph(OUTPUT_STREAM) { + /* the Unicode for "place of interest", the Swedish castle which became the Apple action symbol */ + WRITE("%cV", 0x2318); +} diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt index 93cbe064d..fdbe7eb0a 100644 --- a/inform7/Figures/memory-diagnostics.txt +++ b/inform7/Figures/memory-diagnostics.txt @@ -1,33 +1,33 @@ -Total memory consumption was 139568K = 136 MB +Total memory consumption was 137254K = 134 MB - ---- was used for 2122779 objects, in 374830 frames in 0 x 800K = 0K = 0 MB: + ---- was used for 2122978 objects, in 374831 frames in 0 x 800K = 0K = 0 MB: - 30.2% inter_tree_node_array 60 x 8192 = 491520 objects, 43255680 bytes - 19.2% text_stream_array 4881 x 100 = 488100 objects, 27489792 bytes - 17.7% linked_list 45342 objects, 25391520 bytes - 10.0% inter_symbol_array 135 x 1024 = 138240 objects, 14381280 bytes - 9.8% inter_error_stash_array 107 x 1024 = 109568 objects, 14028128 bytes - 7.4% parse_node 133764 objects, 10701120 bytes - 5.3% verb_conjugation 164 objects, 7610912 bytes + 30.7% inter_tree_node_array 60 x 8192 = 491520 objects, 43255680 bytes + 19.5% text_stream_array 4882 x 100 = 488200 objects, 27495424 bytes + 18.0% linked_list 45345 objects, 25393200 bytes + 10.2% inter_symbol_array 135 x 1024 = 138240 objects, 14381280 bytes + 9.9% inter_error_stash_array 107 x 1024 = 109568 objects, 14028128 bytes + 7.6% parse_node 133764 objects, 10701120 bytes + 5.4% verb_conjugation 164 objects, 7610912 bytes 4.0% parse_node_annotation_array 357 x 500 = 178500 objects, 5723424 bytes - 3.1% scan_directory 1091 objects, 4503648 bytes - 2.4% pcalc_prop_array 26 x 1000 = 26000 objects, 3536832 bytes + 3.2% scan_directory 1091 objects, 4503648 bytes + 2.5% pcalc_prop_array 26 x 1000 = 26000 objects, 3536832 bytes 2.2% inter_name_array 67 x 1000 = 67000 objects, 3218144 bytes 1.9% kind_array 68 x 1000 = 68000 objects, 2722176 bytes 1.5% inter_schema_token 14176 objects, 2154752 bytes 1.4% inter_name_generator_array 51 x 1000 = 51000 objects, 2041632 bytes 1.3% package_request 21340 objects, 1877920 bytes - 1.2% vocabulary_entry_array 163 x 100 = 16300 objects, 1830816 bytes - 1.1% dict_entry_array 490 x 100 = 49000 objects, 1583680 bytes + 1.3% vocabulary_entry_array 163 x 100 = 16300 objects, 1830816 bytes + 1.1% dict_entry_array 491 x 100 = 49100 objects, 1586912 bytes 1.0% inter_symbols_table 26913 objects, 1507128 bytes 1.0% match_trie_array 11 x 1000 = 11000 objects, 1496352 bytes 1.0% i6_schema_array 24 x 100 = 2400 objects, 1440768 bytes 0.9% inter_package 26913 objects, 1291824 bytes - 0.7% map_data 677 objects, 1137360 bytes + 0.8% map_data 677 objects, 1137360 bytes 0.7% id_body 977 objects, 1117688 bytes 0.7% adjective_meaning 208 objects, 1030016 bytes 0.7% inter_schema_node 9066 objects, 1015392 bytes - 0.6% excerpt_meaning 3162 objects, 986544 bytes + 0.7% excerpt_meaning 3162 objects, 986544 bytes 0.6% production 3985 objects, 924520 bytes 0.6% ptoken 8652 objects, 899808 bytes 0.6% grammatical_usage 3648 objects, 875520 bytes @@ -47,7 +47,7 @@ Total memory consumption was 139568K = 136 MB 0.1% hierarchy_location 1189 objects, 171216 bytes 0.1% linguistic_stock_item 3338 objects, 160224 bytes 0.1% rule_family_data 404 objects, 148672 bytes - ---- nonterminal 773 objects, 142232 bytes + 0.1% nonterminal 773 objects, 142232 bytes ---- nascent_array 2130 objects, 136320 bytes ---- inference 1705 objects, 122760 bytes ---- pcalc_term_array 3 x 1000 = 3000 objects, 120096 bytes @@ -65,8 +65,8 @@ Total memory consumption was 139568K = 136 MB ---- spatial_data 677 objects, 64992 bytes ---- kind_constructor 79 objects, 64464 bytes ---- linked_list_item_array 4 x 1000 = 4000 objects, 64128 bytes - ---- actions_rcd_data 1954 objects, 62528 bytes ---- scenes_rcd_data 1954 objects, 62528 bytes + ---- actions_rcd_data 1954 objects, 62528 bytes ---- booking 868 objects, 62496 bytes ---- kind_macro_definition 9 objects, 62280 bytes ---- command_grammar 130 objects, 58240 bytes @@ -81,8 +81,8 @@ Total memory consumption was 139568K = 136 MB ---- heading 212 objects, 47488 bytes ---- text_substitution 438 objects, 42048 bytes ---- to_family_data 525 objects, 42000 bytes - ---- anl_clause_array 1 x 1000 objects, 40032 bytes ---- activity_list_array 1 x 1000 objects, 40032 bytes + ---- anl_clause_array 1 x 1000 objects, 40032 bytes ---- shared_variable_access_list_array 12 x 100 = 1200 objects, 38784 bytes ---- parsing_data 677 objects, 37912 bytes ---- production_list 627 objects, 35112 bytes @@ -109,14 +109,14 @@ Total memory consumption was 139568K = 136 MB ---- pcalc_prop_deferral 86 objects, 17888 bytes ---- to_phrase_request 63 objects, 17136 bytes ---- understanding_reference_array 2 x 100 = 200 objects, 16064 bytes - ---- action_name_list_array 1 x 1000 objects, 16032 bytes ---- match_avinue_array 1 x 1000 objects, 16032 bytes + ---- action_name_list_array 1 x 1000 objects, 16032 bytes ---- adjective 140 objects, 15680 bytes ---- JSON_value 174 objects, 15312 bytes ---- booking_list 407 objects, 13024 bytes ---- web_bibliographic_datum 203 objects, 12992 bytes ---- adjective_iname_holder 323 objects, 12920 bytes - ---- tree_node 149 objects, 11920 bytes + ---- tree_node 148 objects, 11840 bytes ---- uniqueness_count 482 objects, 11568 bytes ---- inter_construct 32 objects, 11008 bytes ---- stopwatch_timer 124 objects, 9920 bytes @@ -145,8 +145,8 @@ Total memory consumption was 139568K = 136 MB ---- command_line_switch 55 objects, 4400 bytes ---- semver_range 42 objects, 4368 bytes ---- use_option 31 objects, 4216 bytes - ---- either_or_property_data 62 objects, 3968 bytes ---- parse_node_annotation_type 124 objects, 3968 bytes + ---- either_or_property_data 62 objects, 3968 bytes ---- method_set 109 objects, 3488 bytes ---- definition 48 objects, 3456 bytes ---- property_setting_bp_data 86 objects, 3440 bytes @@ -157,8 +157,8 @@ Total memory consumption was 139568K = 136 MB ---- JSON_single_requirement 55 objects, 2640 bytes ---- part_of_inference_data 79 objects, 2528 bytes ---- parentage_inference_data 79 objects, 2528 bytes - ---- kind_constructor_casting_rule_array 1 x 100 objects, 2432 bytes ---- kind_constructor_instance_rule_array 1 x 100 objects, 2432 bytes + ---- kind_constructor_casting_rule_array 1 x 100 objects, 2432 bytes ---- equation_symbol 30 objects, 2400 bytes ---- scene 1 object, 2352 bytes ---- build_step 28 objects, 2016 bytes @@ -181,24 +181,24 @@ Total memory consumption was 139568K = 136 MB ---- runtime_kind_structure 13 objects, 1040 bytes ---- quantifier 16 objects, 1024 bytes ---- web_md 7 objects, 1008 bytes - ---- pipeline_stage 20 objects, 960 bytes ---- named_rulebook_outcome 15 objects, 960 bytes + ---- pipeline_stage 20 objects, 960 bytes ---- JSON_pair_requirement 29 objects, 928 bytes ---- control_structure_phrase 12 objects, 864 bytes ---- kit_configuration 21 objects, 840 bytes ---- cached_understanding 21 objects, 840 bytes ---- phrase_option_array 1 x 100 objects, 824 bytes - ---- copy_error 7 objects, 784 bytes ---- inform_kit 7 objects, 784 bytes + ---- copy_error 7 objects, 784 bytes ---- internal_test 15 objects, 720 bytes ---- relation_guard 5 objects, 640 bytes ---- implication 13 objects, 624 bytes ---- chapter_md 7 objects, 616 bytes ---- cdoc_paragraph 18 objects, 576 bytes ---- code_generation 1 object, 576 bytes - ---- inter_warehouse_room 10 objects, 560 bytes - ---- generated_segment 14 objects, 560 bytes ---- module 7 objects, 560 bytes + ---- generated_segment 14 objects, 560 bytes + ---- inter_warehouse_room 10 objects, 560 bytes ---- inter_annotation_form 14 objects, 560 bytes ---- rulebook_outcome 17 objects, 544 bytes ---- small_word_set 11 objects, 528 bytes @@ -210,76 +210,76 @@ Total memory consumption was 139568K = 136 MB ---- source_file 5 objects, 400 bytes ---- tree_node_type 8 objects, 384 bytes ---- article_usage 8 objects, 384 bytes + ---- module_request 8 objects, 320 bytes + ---- tree_inventory 1 object, 320 bytes ---- grammatical_category 8 objects, 320 bytes - ---- door_dir_notice 5 objects, 320 bytes ---- cached_kind_declaration 8 objects, 320 bytes ---- pronoun 8 objects, 320 bytes - ---- tree_inventory 1 object, 320 bytes - ---- module_request 8 objects, 320 bytes + ---- door_dir_notice 5 objects, 320 bytes ---- inter_pipeline 1 object, 312 bytes ---- cdoc_code_sample 6 objects, 288 bytes - ---- compiled_documentation 4 objects, 288 bytes ---- up_family 9 objects, 288 bytes - ---- explicit_bp_data 5 objects, 280 bytes - ---- compilation_unit 5 objects, 280 bytes ---- door_to_notice 5 objects, 280 bytes + ---- compilation_unit 5 objects, 280 bytes ---- contents_entry 7 objects, 280 bytes - ---- kit_dependency 5 objects, 240 bytes + ---- explicit_bp_data 5 objects, 280 bytes + ---- compiled_documentation 3 objects, 264 bytes ---- verb_usage_tier 5 objects, 240 bytes + ---- kit_dependency 5 objects, 240 bytes ---- inform_project 1 object, 232 bytes - ---- local_block_value 4 objects, 224 bytes ---- adjective_meaning_family 7 objects, 224 bytes + ---- local_block_value 4 objects, 224 bytes ---- test_scenario 1 object, 216 bytes ---- release_instructions 1 object, 208 bytes ---- attachment_instruction 5 objects, 200 bytes - ---- code_generator 5 objects, 200 bytes ---- build_skill 5 objects, 200 bytes - ---- cdoc_heading 4 objects, 192 bytes + ---- code_generator 5 objects, 200 bytes + ---- cdoc_example 4 objects, 192 bytes ---- plural_dictionary_entry 4 objects, 192 bytes ---- element_activation 6 objects, 192 bytes ---- cdoc_passage 7 objects, 168 bytes - ---- heterogeneous_tree 4 objects, 160 bytes - ---- imperative_defn_family 4 objects, 160 bytes - ---- cdoc_example 4 objects, 160 bytes - ---- inference_subject_family 5 objects, 160 bytes + ---- cdoc_heading 3 objects, 168 bytes ---- inter_architecture 4 objects, 160 bytes + ---- imperative_defn_family 4 objects, 160 bytes + ---- inference_subject_family 5 objects, 160 bytes ---- inbuild_nest 3 objects, 120 bytes + ---- heterogeneous_tree 3 objects, 120 bytes ---- inform_language 1 object, 104 bytes ---- article 2 objects, 80 bytes ---- compile_task_data 1 object, 80 bytes ---- group_together_function 2 objects, 80 bytes + ---- figures_data 1 object, 56 bytes ---- build_methodology 1 object, 56 bytes ---- inter_warehouse 1 object, 56 bytes - ---- figures_data 1 object, 56 bytes ---- HTML_file_state 1 object, 48 bytes ---- inform_kit_ittt 1 object, 48 bytes ---- star_invention 1 object, 48 bytes - ---- target_pragma_setting 1 object, 40 bytes - ---- tree_type 1 object, 40 bytes - ---- loop_over_scope 1 object, 40 bytes ---- kind_template_definition 1 object, 40 bytes ---- I6_generation_data 1 object, 40 bytes ---- by_function_bp_data 1 object, 40 bytes + ---- tree_type 1 object, 40 bytes + ---- target_pragma_setting 1 object, 40 bytes + ---- loop_over_scope 1 object, 40 bytes 100.0% was used for memory not allocated for objects: - 62.3% text stream storage 89055024 bytes in 508489 claims + 61.6% text stream storage 86685820 bytes in 508181 claims 3.8% dictionary storage 5479936 bytes in 7752 claims ---- sorting 2624 bytes in 531 claims - 5.0% source text 7200000 bytes in 3 claims - 7.5% source text details 10800000 bytes in 2 claims + 5.1% source text 7200000 bytes in 3 claims + 7.6% source text details 10800000 bytes in 2 claims 0.1% documentation fragments 262144 bytes in 1 claim ---- linguistic stock array 81920 bytes in 2 claims ---- small word set array 105600 bytes in 22 claims - 3.2% inter symbols storage 4703712 bytes in 28290 claims - 11.7% inter bytecode storage 16758140 bytes in 15 claims - 4.3% inter links storage 6222976 bytes in 11 claims + 3.3% inter symbols storage 4703712 bytes in 28290 claims + 11.9% inter bytecode storage 16758140 bytes in 15 claims + 4.4% inter links storage 6222976 bytes in 11 claims 0.1% inter tree location list storage 191232 bytes in 32 claims 1.2% instance-of-kind counting 1731856 bytes in 1 claim ---- compilation workspace for objects 21936 bytes in 25 claims ---- lists for type-checking invocations 16000 bytes in 1 claim ---- code generation workspace for objects 3488 bytes in 19 claims - 0.1% emitter array storage 281184 bytes in 2006 claims + 0.2% emitter array storage 281184 bytes in 2006 claims --136.-4% was overhead - -194989176 bytes = -190419K = -185 MB +-138.-7% was overhead - -194999584 bytes = -190429K = -185 MB diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index 39317d5cd..6aafffa51 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,29 +1,29 @@ 100.0% in inform7 run 67.4% in compilation to Inter - 45.4% in //Sequence::undertake_queued_tasks// - 4.5% in //MajorNodes::pre_pass// + 45.7% in //Sequence::undertake_queued_tasks// + 4.2% in //MajorNodes::pre_pass// 3.4% in //MajorNodes::pass_1// - 1.8% in //ImperativeDefinitions::assess_all// - 1.8% in //RTPhrasebook::compile_entries// + 1.9% in //ImperativeDefinitions::assess_all// 1.5% in //RTKindConstructors::compile// + 1.5% in //RTPhrasebook::compile_entries// 1.1% in //Sequence::lint_inter// - 0.7% in //Sequence::undertake_queued_tasks// 0.3% in //CompletionModule::compile// 0.3% in //ImperativeDefinitions::compile_first_block// 0.3% in //MajorNodes::pass_2// 0.3% in //RTKindConstructors::compile_permissions// 0.3% in //Sequence::undertake_queued_tasks// + 0.3% in //Sequence::undertake_queued_tasks// 0.3% in //World::stage_V// - 4.6% not specifically accounted for - 27.6% in running Inter pipeline - 9.4% in step 14/15: generate inform6 -> auto.inf - 6.8% in step 5/15: load-binary-kits - 6.0% in step 6/15: make-synoptic-module - 1.8% in step 9/15: make-identifiers-unique + 5.0% not specifically accounted for + 28.2% in running Inter pipeline + 9.6% in step 14/15: generate inform6 -> auto.inf + 6.9% in step 5/15: load-binary-kits + 5.8% in step 6/15: make-synoptic-module + 1.9% in step 9/15: make-identifiers-unique 0.3% in step 12/15: eliminate-redundant-operations 0.3% in step 4/15: compile-splats 0.3% in step 7/15: shorten-wiring 0.3% in step 8/15: detect-indirect-calls - 1.9% not specifically accounted for - 4.1% in supervisor + 2.3% not specifically accounted for + 3.4% in supervisor 0.8% not specifically accounted for diff --git a/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json b/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json index e51515112..aafd806ed 100644 --- a/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json +++ b/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "Architecture16Kit", - "version": "10.2.0-beta+6W86" + "version": "10.2.0-beta+6W87" }, "compatibility": "16-bit", "kit-details": { diff --git a/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json b/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json index 5c5d6f3fe..528a67e37 100644 --- a/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json +++ b/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "Architecture32Kit", - "version": "10.2.0-beta+6W86" + "version": "10.2.0-beta+6W87" }, "compatibility": "32-bit", "kit-details": { diff --git a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json index d9a6edcb6..fe4a67d7d 100644 --- a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json +++ b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "BasicInformKit", - "version": "10.2.0-beta+6W86" + "version": "10.2.0-beta+6W87" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json index 0e5439854..6d31a1b05 100644 --- a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json +++ b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "CommandParserKit", - "version": "10.2.0-beta+6W86" + "version": "10.2.0-beta+6W87" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json index e1b531be4..bcfd59618 100644 --- a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json +++ b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "EnglishLanguageKit", - "version": "10.2.0-beta+6W86" + "version": "10.2.0-beta+6W87" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json index 1cb5a1a95..bf5c5e571 100644 --- a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json +++ b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "WorldModelKit", - "version": "10.2.0-beta+6W86" + "version": "10.2.0-beta+6W87" }, "needs": [ { "need": {