A format which renders as a plain-text serialisation of the weave tree, useful only for testing the weaver.


§1. Creation.

void DebuggingWeaving::create(void) {
    weave_format *wf = WeavingFormats::create_weave_format(I"TestingInweb", I".debug.txt");
    METHOD_ADD(wf, RENDER_FOR_MTID, DebuggingWeaving::render);
}

§2. Rendering. The weave tree will be rendered by traversing it, and rendering each node in its turn.

void DebuggingWeaving::render(weave_format *self, text_stream *OUT, heterogeneous_tree *tree) {
    weave_document_node *C = RETRIEVE_POINTER_weave_document_node(tree->root->content);
    debugging_render_state drs;
    Initialise the render state2.2;
    Trees::traverse_from(tree->root, &DebuggingWeaving::render_visit, (void *) &drs, 0);
    Append the Markdown traces2.3;
}

§2.1. The following instructions will be carried through the traverse:

classdef debugging_render_state {
    struct text_stream *OUT;
    struct weave_order *wv;
    struct linked_list *fragments; /* of markdown_item */
    int observed[100];
} debugging_render_state;

§2.2. Initialise the render state2.2 =

    drs.OUT = OUT;
    drs.wv = C->wv;
    drs.fragments = NEW_LINKED_LIST(markdown_item);
    for (int i=0; i<100; i++) drs.observed[i] = 0;

§2.3. Append the Markdown traces2.3 =

    markdown_item *md;
    int f = 1;
    LOOP_OVER_LINKED_LIST(md, markdown_item, drs.fragments) {
        WRITE("\nMarkdown fragment (%d)\n", f++);
        INDENT;
        Markdown::debug_subtree(OUT, md);
        OUTDENT;
    }
    WRITE("\n");
    tree_node_type *tnt;
    LOOP_OVER(tnt, tree_node_type) {
        int id = tnt->allocation_id;
        if (id < 100)
            WRITE("%S: %d node%s\n",
                tnt->node_type_name, drs.observed[id], (drs.observed[id]==1)?"":"s");
    }

§3. So, then, the visiting function, called on each node. C does not allow switch statements whose cases are not literal constants, so there's a big contrived if instead. But it is morally a switch.

int DebuggingWeaving::render_visit(tree_node *N, void *state, int L) {
    debugging_render_state *drs = (debugging_render_state *) state;
    text_stream *OUT = drs->OUT;
    for (int i=0; i<L; i++) WRITE("    ");
    WRITE("%S: ", N->type->node_type_name);
    int id = N->type->allocation_id;
    if (id < 100) drs->observed[id]++;

    /* Document superstructure */

         if (N->type == weave_document_node_type) Render document3.1
    else if (N->type == weave_head_node_type) Render head3.2
    else if (N->type == weave_body_node_type) Render body3.3
    else if (N->type == weave_tail_node_type) Render tail3.4

    /* Large-scale structure */

    else if (N->type == weave_chapter_node_type) Render chapter3.5
    else if (N->type == weave_chapter_header_node_type) Render chapter header3.6
    else if (N->type == weave_chapter_footer_node_type) Render chapter footer3.7
    else if (N->type == weave_section_node_type) Render section3.8
    else if (N->type == weave_section_header_node_type) Render section header3.9
    else if (N->type == weave_section_footer_node_type) Render section footer3.10
    else if (N->type == weave_section_purpose_node_type) Render section purpose3.11
    else if (N->type == weave_toc_node_type) Render toc3.12
    else if (N->type == weave_toc_line_node_type) Render toc line3.13

    /* Small-scale structure */

    else if (N->type == weave_subheading_node_type) Render subheading3.14
    else if (N->type == weave_subsubheading_node_type) Render subsubheading3.15
    else if (N->type == weave_paragraph_heading_node_type) Render paragraph heading3.16
    else if (N->type == weave_material_node_type) Render material3.17

    /* Code-like material */

    else if (N->type == weave_holon_declaration_node_type) Render holon declaration3.18
    else if (N->type == weave_code_line_node_type) Render code line3.19
    else if (N->type == weave_holon_usage_node_type) Render holon usage3.20
    else if (N->type == weave_tangler_command_node_type) Render tangler command3.21
    else if (N->type == weave_verbatim_node_type) Render verbatim3.22
    else if (N->type == weave_source_code_node_type) Render source code3.23
    else if (N->type == weave_function_defn_node_type) Render function defn3.24
    else if (N->type == weave_function_usage_node_type) Render function usage3.25
    else if (N->type == weave_comment_in_holon_node_type) Render comment in holon3.26
    else if (N->type == weave_defn_node_type) Render defn3.27

    /* Commentary and gadget material */

    else if (N->type == weave_markdown_node_type) Render Markdown3.28
    else if (N->type == weave_audio_node_type) Render audio3.29
    else if (N->type == weave_carousel_slide_node_type) Render carousel slide3.30
    else if (N->type == weave_download_node_type) Render download3.31
    else if (N->type == weave_embed_node_type) Render embed3.32
    else if (N->type == weave_figure_node_type) Render figure3.33
    else if (N->type == weave_raw_HTML_node_type) Render raw HTML3.34
    else if (N->type == weave_video_node_type) Render video3.35

    /* Paragraph tail material */

    else if (N->type == weave_index_begins_node_type) Render index begins3.36
    else if (N->type == weave_index_lemma_node_type) Render index lemma3.37
    else if (N->type == weave_index_ends_node_type) Render index ends3.38
    else if (N->type == weave_endnote_node_type) Render endnote3.39
    else if (N->type == weave_locale_node_type) Render locale3.40
    else if (N->type == weave_endnote_text_node_type) Render endnote text3.41

    else internal_error("no HTML rendering for this node type");

    WRITE("\n");
    return TRUE;
}

§3.1. Document superstructure renderers. Render document3.1 =

    weave_document_node *C = RETRIEVE_POINTER_weave_document_node(N->content);
    WRITE(" weave order %d", C->wv->allocation_id);

§3.2. Render head3.2 =

    weave_head_node *C = RETRIEVE_POINTER_weave_head_node(N->content);
    WRITE(" banner <%S>", C->banner);

§3.3. Render body3.3 =

    ;

§3.4. Render tail3.4 =

    weave_tail_node *C = RETRIEVE_POINTER_weave_tail_node(N->content);
    WRITE(" rennab <%S>", C->rennab);

§3.5. Large-scale structure renderers. Render chapter3.5 =

    weave_chapter_node *C = RETRIEVE_POINTER_weave_chapter_node(N->content);
    WRITE(" <%S>", C->chap->ch_title);

§3.6. Render chapter header3.6 =

    weave_chapter_header_node *C = RETRIEVE_POINTER_weave_chapter_header_node(N->content);
    WRITE(" <%S>", C->chap->ch_title);

§3.7. Render chapter footer3.7 =

    weave_chapter_footer_node *C = RETRIEVE_POINTER_weave_chapter_footer_node(N->content);
    WRITE(" <%S>", C->chap->ch_title);

§3.8. Render section3.8 =

    weave_section_node *C = RETRIEVE_POINTER_weave_section_node(N->content);
    WRITE(" <%S>", C->sect->sect_title);

§3.9. Render section header3.9 =

    weave_section_header_node *C = RETRIEVE_POINTER_weave_section_header_node(N->content);
    WRITE(" <%S>", C->sect->sect_title);

§3.10. Render section footer3.10 =

    weave_section_footer_node *C = RETRIEVE_POINTER_weave_section_footer_node(N->content);
    WRITE(" <%S>", C->sect->sect_title);

§3.11. Render section purpose3.11 =

    weave_section_purpose_node *C = RETRIEVE_POINTER_weave_section_purpose_node(N->content);
    WRITE(" <%S>", C->purpose);

§3.12. Render toc3.12 =

    weave_toc_node *C = RETRIEVE_POINTER_weave_toc_node(N->content);
    WRITE(" - <%S>", C->text1);

§3.13. Render toc line3.13 =

    weave_toc_line_node *C = RETRIEVE_POINTER_weave_toc_line_node(N->content);
    WRITE(" - <%S, %S>", C->text1, C->text2);
    if (C->para) DebuggingWeaving::show_para(OUT, C->para);

§3.14. Small-scale structure renderers. Render subheading3.14 =

    weave_subheading_node *C = RETRIEVE_POINTER_weave_subheading_node(N->content);
    WRITE(" <%S>", C->text);

§3.15. Render subsubheading3.15 =

    weave_subsubheading_node *C = RETRIEVE_POINTER_weave_subsubheading_node(N->content);
    WRITE(" <%S>", C->text);

§3.16. Render paragraph heading3.16 =

    weave_paragraph_heading_node *C = RETRIEVE_POINTER_weave_paragraph_heading_node(N->content);
    DebuggingWeaving::show_para(OUT, C->para);
    if (C->no_skip) WRITE(" (no skip)");

§3.17. Render material3.17 =

    weave_material_node *C = RETRIEVE_POINTER_weave_material_node(N->content);
    WRITE(" ");
    switch (C->material_type) {
        case COMMENTARY_MATERIAL:        WRITE("discussion"); break;
        case HOLON_DECLARATION_MATERIAL: WRITE("named holon"); break;
        case DEFINITION_MATERIAL:        WRITE("definition"); break;
        case CODE_MATERIAL:              WRITE("code"); break;
        case ENDNOTES_MATERIAL:          WRITE("endnotes"); break;
        case FOOTNOTES_MATERIAL:         WRITE("footnotes"); break;
        default:                         WRITE("unknown"); break;
    }
    if (C->material_type == CODE_MATERIAL) WRITE(": %S", C->styling->language_name);
    if (C->plainly) WRITE(" (plainly)");

§3.18. Code-like material renderers. Render holon declaration3.18 =

    weave_holon_declaration_node *C = RETRIEVE_POINTER_weave_holon_declaration_node(N->content);
    WRITE(" <%S> (definition)", C->holon->holon_name);

§3.19. Render code line3.19 =

    ;

§3.20. Render holon usage3.20 =

    weave_holon_usage_node *C = RETRIEVE_POINTER_weave_holon_usage_node(N->content);
    WRITE(" <%S>", (C->holon)?(C->holon->holon_name):NULL);

§3.21. Render tangler command3.21 =

    weave_tangler_command_node *C = RETRIEVE_POINTER_weave_tangler_command_node(N->content);
    WRITE("command: %S", C->command);

§3.22. Render verbatim3.22 =

    weave_verbatim_node *C = RETRIEVE_POINTER_weave_verbatim_node(N->content);
    DebuggingWeaving::show_text(OUT, C->content, 80);

§3.23. Render source code3.23 =

    weave_source_code_node *C = RETRIEVE_POINTER_weave_source_code_node(N->content);
    WRITE(" <%S>\n", C->matter);
    for (int i=0; i<L; i++) WRITE("  ");
    WRITE("           ");
    WRITE(" _%S_", C->colouring);

§3.24. Render function defn3.24 =

    weave_function_defn_node *C = RETRIEVE_POINTER_weave_function_defn_node(N->content);
    WRITE(" <%S>", C->fn->function_name);

§3.25. Render function usage3.25 =

    weave_function_usage_node *C = RETRIEVE_POINTER_weave_function_usage_node(N->content);
    WRITE(" <%S>", C->fn->function_name);

§3.26. Render comment in holon3.26 =

    weave_comment_in_holon_node *C = RETRIEVE_POINTER_weave_comment_in_holon_node(N->content);
    WRITE("comment %S", C->comment_open);
    WRITE("%S", C->raw);
    WRITE("%S", C->comment_close);

§3.27. Render defn3.27 =

    weave_defn_node *C = RETRIEVE_POINTER_weave_defn_node(N->content);
    WRITE(" <%S>", C->keyword);

§3.28. Commentary and gadget material renderers. Render Markdown3.28 =

    weave_markdown_node *C = RETRIEVE_POINTER_weave_markdown_node(N->content);
    ADD_TO_LINKED_LIST(C->content, markdown_item, drs->fragments);
    WRITE("fragment (%d)", LinkedLists::len(drs->fragments));

§3.29. Render audio3.29 =

    weave_audio_node *C = RETRIEVE_POINTER_weave_audio_node(N->content);
    WRITE(" <%S> %d", C->audio_name, C->w);

§3.30. Render carousel slide3.30 =

    weave_carousel_slide_node *C = RETRIEVE_POINTER_weave_carousel_slide_node(N->content);
    WRITE(" %d/%d caption <%S> position %d", C->slide_number, C->slide_of, C->caption, C->positioning);

§3.31. Render download3.31 =

    weave_download_node *C = RETRIEVE_POINTER_weave_download_node(N->content);
    WRITE(" <%S> %S", C->download_name, C->filetype);

§3.32. Render embed3.32 =

    weave_embed_node *C = RETRIEVE_POINTER_weave_embed_node(N->content);
    WRITE(" service <%S> ID <%S> %d by %d", C->service, C->ID, C->w, C->h);

§3.33. Render figure3.33 =

    weave_figure_node *C = RETRIEVE_POINTER_weave_figure_node(N->content);
    WRITE(" <%S> %d by %d", C->figname, C->w, C->h);

§3.34. Render raw HTML3.34 =

    weave_raw_HTML_node *C = RETRIEVE_POINTER_weave_raw_HTML_node(N->content);
    WRITE(" <%S>", C->extract);

§3.35. Render video3.35 =

    weave_video_node *C = RETRIEVE_POINTER_weave_video_node(N->content);
    WRITE(" <%S> %d", C->video_name, C->w);

§3.36. Paragraph tail material renderers. Render index begins3.36 =

    WRITE("index begins");

§3.37. Render index lemma3.37 =

    weave_index_lemma_node *C = RETRIEVE_POINTER_weave_index_lemma_node(N->content);
    ls_index_lemma *lemma = C->lemma;
    for (ls_index_lemma *l2 = lemma->parent; l2; l2 = l2->parent) WRITE("> ");
    if (lemma->style == 2) WRITE("`");
    if (lemma->style == 3) WRITE("/");
    WRITE("%S", lemma->text);
    if (lemma->style == 2) WRITE("`");
    if (lemma->style == 3) WRITE("/");
    ls_index_mark *mark; int c = 0;
    LOOP_OVER_LINKED_LIST(mark, ls_index_mark, lemma->marks) {
        if (c++ > 0) WRITE(", "); else WRITE("  ");
        if (mark->important) WRITE("_");
        WRITE("%S", mark->at->paragraph_number);
        if (mark->important) WRITE("_");
    }

§3.38. Render index ends3.38 =

    WRITE("index ends");

§3.39. Render endnote3.39 =

    ;

§3.40. Render locale3.40 =

    weave_locale_node *C = RETRIEVE_POINTER_weave_locale_node(N->content);
    DebuggingWeaving::show_para(OUT, C->par1);
    if (C->par2) {
        WRITE(" to ");
        DebuggingWeaving::show_para(OUT, C->par2);
    }

§3.41. Render endnote text3.41 =

    weave_endnote_text_node *C = RETRIEVE_POINTER_weave_endnote_text_node(N->content);
    DebuggingWeaving::show_text(OUT, C->text, 80);

§4. And the above make liberal use of these helpers:

void DebuggingWeaving::show_text(text_stream *OUT, text_stream *text, int limit) {
    WRITE(" <");
    for (int i=0; (i<limit) && (i<Str::len(text)); i++)
        if (Str::get_at(text, i) == '\n')
            WRITE("\\n");
        else
            PUT(Str::get_at(text, i));
    WRITE(">");
    if (Str::len(text) > limit) WRITE(" ... continues to %d chars", Str::len(text));
}

void DebuggingWeaving::show_para(text_stream *OUT, ls_paragraph *par) {
    WRITE(" P%S", par->paragraph_number);
    text_stream *title = LiterateSource::par_title(par);
    if (Str::len(title) > 0) WRITE("'%S'", title);
}