The different sorts of work managed by inbuild.


§1. Genres. Each different genre of work managed by Inbuild is represented by an instance of the following structure. (At present, then, there are exactly seven instances of it: nothing the user can do at the command line can change that total.) A work unambiguously specifies what genre it has by means of a non-null pointer to inbuild_genre. Moreover, the rules for how Inbuild manages works of this genre are expressed by methods attached to the structure. For example, to copy a work, Inbuild calls the GENRE_COPY_TO_NEST_MTID method attached to its inbuild_genre.

Each genre has its own section of code: for example, Kit Manager defines the instance kit_genre and provides its method functions.

typedef struct inbuild_genre {
    text_stream *genre_name;
    text_stream *metadata_type_name;
    int stored_in_nests;
    int genre_class;
    struct method_set *methods;
    CLASS_DEFINITION
} inbuild_genre;

inbuild_genre *Genres::new(text_stream *name, text_stream *md, int nested) {
    inbuild_genre *gen = CREATE(inbuild_genre);
    gen->genre_name = Str::duplicate(name);
    gen->metadata_type_name = Str::duplicate(md);
    gen->stored_in_nests = nested;
    gen->genre_class = 0;
    gen->methods = Methods::new_set();
    return gen;
}

text_stream *Genres::name(inbuild_genre *G) {
    if (G == NULL) return I"(none)";
    return G->genre_name;
}

text_stream *Genres::metadata_type_name(inbuild_genre *G) {
    if (G == NULL) return I"(none)";
    return G->metadata_type_name;
}

§2. Some genres of work, such as kits and extensions, can be stored in nests; others, such as Inform projects, cannot. Whether a copy can be stored in a nest depends only on its genre.

int Genres::stored_in_nests(inbuild_genre *G) {
    if (G == NULL) return FALSE;
    return G->stored_in_nests;
}

§3. The requirements parser needs to identify genres by name, so:

inbuild_genre *Genres::by_name(text_stream *name) {
    inbuild_genre *G;
    LOOP_OVER(G, inbuild_genre)
        if (Str::eq_insensitive(G->genre_name, name))
            return G;
    return NULL;
}

§4. When searching, treat these as equivalently good:

int Genres::equivalent(inbuild_genre *G1, inbuild_genre *G2) {
    if (G1 == G2) return TRUE;
    if ((G1->genre_class != 0) && (G1->genre_class == G2->genre_class)) return TRUE;
    return FALSE;
}

void Genres::place_in_class(inbuild_genre *G, int c) {
    G->genre_class = c;
}

§5. For sorting of search results:

int Genres::cmp(inbuild_genre *G1, inbuild_genre *G2) {
    if ((G1 == NULL) || (G2 == NULL)) internal_error("bad genre match");
    if (G1->allocation_id < G2->allocation_id) return -1;
    if (G1->allocation_id > G2->allocation_id) return 1;
    return 0;
}

§6. Method functions. And here are the method functions which a genre can, optionally, provide. All of these act on a given work, or a given copy of a work, having the genre in question.

First, this writes text sufficient to identify a work: e.g., "Locksmith by Emily Short".

enum GENRE_WRITE_WORK_MTID
VOID_METHOD_TYPE(GENRE_WRITE_WORK_MTID,
    inbuild_genre *gen, text_stream *OUT, inbuild_work *work)

§7. This looks at a textual file locator, which might be a pathname or a filename, to see if it might refer to a copy of a work of the given genre. If it does, an inbuild_copy is created, and the pointer *C is set to point to it. If not, no error is issued, and *C is left unchanged.

Errors can, however, be produced if Inbuild is pretty sure that the object in the file system is intended to be such a copy, but is damaged in some way: an extension with a malformed titling line, for example. Such errors are attached to the copy for later issuing.

enum GENRE_CLAIM_AS_COPY_MTID
VOID_METHOD_TYPE(GENRE_CLAIM_AS_COPY_MTID,
    inbuild_genre *gen, inbuild_copy **C, text_stream *arg, text_stream *ext,
    int directory_status)

§8. This searches the nest N for anything which (a) looks like a copy of a work of our genre, and (b) meets the given requirements. If a genre does not provide this method, then nothing of that genre can ever appear in -matching search results.

enum GENRE_SEARCH_NEST_FOR_MTID
VOID_METHOD_TYPE(GENRE_SEARCH_NEST_FOR_MTID,
    inbuild_genre *gen, inbuild_nest *N, inbuild_requirement *req,
    linked_list *search_results)

§9. Some genres of work involve Inform source text — Inform projects and extensions, for example. Reading in source text is fairly fast, but it's not an instant process, and we don't automatically perform it. (When an extension is scanned for metadata during claiming, only the opening line is looked at.)

This method should exist only for such genres, and it should read the source text. It will never be called twice on the same copy.

Text should actually be read by feeding it into the lexer. Inbuild will take of it from there.

enum GENRE_READ_SOURCE_TEXT_FOR_MTID
VOID_METHOD_TYPE(GENRE_READ_SOURCE_TEXT_FOR_MTID,
    inbuild_genre *gen, inbuild_copy *C)

§10. At the Graph Construction phase of Inbuild, each copy is offered the chance to finalise its internal representation. For example, this may be when its build graph is constructed, because we can now know for sure that there are no further unsuspected dependencies.

This method is optional, and is called exactly once on every copy (whose genre provides it) which has been claimed by Inbuild.

enum GENRE_CONSTRUCT_GRAPH_MTID
VOID_METHOD_TYPE(GENRE_CONSTRUCT_GRAPH_MTID,
    inbuild_genre *gen, inbuild_copy *C)

§11. This method is called when a copy is about to be built or have its graph described, for example by -graph, -build and -rebuild. Nothing actually needs to be done, but if any work is needed before building can take place, now's the time; and the vertex to build from can be altered by setting *V. (This is used to create upstream targets for Inform projects, such as the blorbed release version. It affects -graph, -build and -rebuild but is ignored for other inspection options such as -use-missing.)

enum GENRE_BUILDING_SOON_MTID
VOID_METHOD_TYPE(GENRE_BUILDING_SOON_MTID,
    inbuild_genre *gen, inbuild_copy *C, build_vertex **V)

§12. This duplicates, or syncs, a copy C of a work in our genre, placing it at a canonical location inside the given nest N. In effect, it implements the Inbuild command-line options -copy-to N and -sync-to N.

enum GENRE_COPY_TO_NEST_MTID
INT_METHOD_TYPE(GENRE_COPY_TO_NEST_MTID,
    inbuild_genre *gen, inbuild_copy *C, inbuild_nest *N, int syncing,
    build_methodology *meth)

§13. This writes documentation on the edition (if it provides any).

enum GENRE_DOCUMENT_MTID
VOID_METHOD_TYPE(GENRE_DOCUMENT_MTID,
    inbuild_genre *gen, inbuild_copy *C, pathname *dest, filename *sitemap)

§14. This performs some sort of automatic-update to the latest format:

enum GENRE_MODERNISE_MTID
INT_METHOD_TYPE(GENRE_MODERNISE_MTID,
    inbuild_genre *gen, inbuild_copy *C, text_stream *OUT)