To issue problem messages when parsing or running erroneous pipelines.


§1. Syntax errors.

void PipelineErrors::syntax(text_file_position *tfp, text_stream *syntax,
    char *erm) {
    #ifdef CORE_MODULE
    Begin syntax problem message using the module of the same name1.1;
    TEMPORARY_TEXT(full)
    WRITE_TO(full, "%s", erm);
    End syntax problem message using the module of the same name1.2;
    DISCARD_TEXT(full)
    #endif
    #ifndef CORE_MODULE
    Errors::in_text_file(erm, tfp);
    #endif
}

void PipelineErrors::syntax_with(text_file_position *tfp, text_stream *syntax,
    char *erm, text_stream *quoted) {
    TEMPORARY_TEXT(full)
    WRITE_TO(full, erm, quoted);
    #ifdef CORE_MODULE
    Begin syntax problem message using the module of the same name1.1;
    End syntax problem message using the module of the same name1.2;
    #endif
    #ifndef CORE_MODULE
    Errors::in_text_file_S(full, tfp);
    #endif
    DISCARD_TEXT(full)
}

§1.1. Begin syntax problem message using the module of the same name1.1 =

    do_not_locate_problems = TRUE;
    Problems::issue_problem_begin(NULL, erm);
    Problems::issue_problem_segment(
        "I was nearly done, and about to run through the 'pipeline' of "
        "code-generation steps, but it turned out to have a syntax error. "
        "(The built-in pipelines do not have syntax errors, so this must be "
        "because you are experimenting with a non-standard pipeline,) "
        "Specifically:");
    Problems::issue_problem_end();

§1.2. End syntax problem message using the module of the same name1.2 =

    Problems::issue_problem_begin(Task::syntax_tree(), "****");
    int N = tfp->line_count;
    Problems::quote_number(1, &N);
    Problems::quote_stream(2, syntax);
    Problems::quote_stream_tinted_red(3, full);
    Problems::issue_problem_begin(Task::syntax_tree(), "****");
    Problems::issue_problem_segment("Line %1 '%2': %3");
    Problems::issue_problem_end();
    do_not_locate_problems = FALSE;

§2. Execution errors.

void PipelineErrors::error(pipeline_step *step, char *erm) {
    #ifdef CORE_MODULE
    Begin problem message using the module of the same name2.1;
    TEMPORARY_TEXT(full)
    WRITE_TO(full, "%s", erm);
    Problems::quote_stream(1, full);
    DISCARD_TEXT(full)
    End problem message using the module of the same name2.2;
    #endif
    #ifndef CORE_MODULE
    Errors::fatal(erm);
    exit(1);
    #endif
}

void PipelineErrors::error_with(pipeline_step *step, char *erm, text_stream *quoted) {
    #ifdef CORE_MODULE
    Begin problem message using the module of the same name2.1;
    TEMPORARY_TEXT(full)
    WRITE_TO(full, erm, quoted);
    Problems::quote_stream(1, full);
    End problem message using the module of the same name2.2;
    DISCARD_TEXT(full)
    #endif
    #ifndef CORE_MODULE
    Errors::fatal_with_text(erm, quoted);
    exit(1);
    #endif
}

§2.1. Begin problem message using the module of the same name2.1 =

    do_not_locate_problems = TRUE;
    Problems::issue_problem_begin(NULL, erm);
    Problems::issue_problem_segment(
        "Something went wrong late in compilation, when working through the "
        "'pipeline' of code-generation steps. (This should not normally happen "
        "unless your source text is making use of '(-' and '-)' and getting "
        "that wrong, or unless you are experimenting with non-standard pipelines.) "
        "The pipeline looks like so:");
    Problems::issue_problem_end();

§2.2. End problem message using the module of the same name2.2 =

    if (step) {
        inter_pipeline *pipeline = step->pipeline;
        pipeline_step *some_step;
        int N = 1;
        LOOP_OVER_LINKED_LIST(some_step, pipeline_step, pipeline->steps) {
            TEMPORARY_TEXT(description)
            ParsingPipelines::write_step(description, some_step);
            Problems::issue_problem_begin(Task::syntax_tree(), "****");
            Problems::quote_number(1, &N);
            if (some_step == step) {
                Problems::quote_stream_tinted_red(2, description);
                Problems::issue_problem_segment("%1. %2");
            } else {
                Problems::quote_stream_tinted_green(2, description);
                Problems::issue_problem_segment("%1. %2");
            }
            DISCARD_TEXT(description)
            Problems::issue_problem_end();
            if (some_step == step) {
                Problems::issue_problem_begin(Task::syntax_tree(), "****");
                Problems::quote_stream(1, full);
                Problems::issue_problem_segment("Problem: %1");
                Problems::issue_problem_end();
            }
            N++;
        }
    }
    do_not_locate_problems = FALSE;
    if (Log::aspect_switched_on(INTER_DA))
        TextualInter::write(DL, Emit::tree(), NULL);

§3. Errors in kit source. Errors like this used to be basically failed assertions, but inevitably people reported that as a bug (0001596). It was never intended that Inform 6-syntax hacking should be part of the outside-facing Inform language; but if you leave power tools just lying around, people will eventually pick them up and wonder what the red button marked "danger" does.

int pipeline_error_count = 0;

void PipelineErrors::kit_error(char *message, text_stream *quote) {
    #ifdef PROBLEMS_MODULE
    TEMPORARY_TEXT(M)
    WRITE_TO(M, message, quote);
    Problems::quote_stream(1, M);
    StandardProblems::handmade_problem(Task::syntax_tree(), _p_(...));
    Problems::issue_problem_segment(
        "My low-level reader of source code reported a mistake - \"%1\". "
        "%PLow-level material written in Inform 6 syntax occurs either in kits or "
        "in matter written inside 'Include (- ... -)' in source text, either in "
        "the main source or in an extension used by it.");
    Problems::issue_problem_end();
    DISCARD_TEXT(M)
    #endif
    #ifndef PROBLEMS_MODULE
    Errors::with_text(message, quote);
    #endif
    pipeline_error_count++;
}

void PipelineErrors::reset_errors(void) {
    pipeline_error_count = 0;
}

int PipelineErrors::errors_occurred(void) {
    if (pipeline_error_count != 0) return TRUE;
    return FALSE;
}