Defining the insert construct.


§1. Definition.For what this does and why it is used, see Data Packages in Textual Inter (in inter). But please use it as little as possible: in an ideal world it would be abolished.

void InsertInstruction::define_construct(void) {
    inter_construct *IC = InterInstruction::create_construct(INSERT_IST, I"insert");
    InterInstruction::specify_syntax(IC, I"insert TEXT TEXT TEXT NUMBER");
    InterInstruction::data_extent_always(IC, 4);
    InterInstruction::permit(IC, INSIDE_PLAIN_PACKAGE_ICUP);
    METHOD_ADD(IC, CONSTRUCT_READ_MTID, InsertInstruction::read);
    METHOD_ADD(IC, CONSTRUCT_TRANSPOSE_MTID, InsertInstruction::transpose);
    METHOD_ADD(IC, CONSTRUCT_VERIFY_MTID, InsertInstruction::verify);
    METHOD_ADD(IC, CONSTRUCT_WRITE_MTID, InsertInstruction::write);
}

§2. Instructions.In bytecode, the frame of an insert instruction is laid out with the compulsory words — see Inter Nodes — followed by:

define TEXT_INSERT_IFLD (DATA_IFLD + 0)
define REPLACING_INSERT_IFLD (DATA_IFLD + 1)
define PROVENANCEFILE_INSERT_IFLD (DATA_IFLD + 2)
define PROVENANCELINE_INSERT_IFLD (DATA_IFLD + 3)
inter_error_message *InsertInstruction::new(inter_bookmark *IBM,
    text_stream *text, text_stream *replacing,
    filename *file, inter_ti line_number,
    inter_ti level, struct inter_error_location *eloc) {
    TEMPORARY_TEXT(file_as_text)
    if (file) WRITE_TO(file_as_text, "%f", file);
    inter_warehouse *warehouse = InterBookmark::warehouse(IBM);
    inter_package *pack = InterBookmark::package(IBM);
    inter_ti ID = InterWarehouse::create_text(warehouse, pack);
    Str::copy(InterWarehouse::get_text(warehouse, ID), text);
    inter_ti RID = InterWarehouse::create_text(warehouse, pack);
    Str::copy(InterWarehouse::get_text(warehouse, RID), replacing);
    inter_ti FID = InterWarehouse::create_text(warehouse, pack);
    Str::copy(InterWarehouse::get_text(warehouse, FID), file_as_text);
    inter_tree_node *P = Inode::new_with_4_data_fields(IBM, INSERT_IST,
        /* TEXT_INSERT_IFLD: */           ID,
        /* REPLACING_INSERT_IFLD: */      RID,
        /* PROVENANCEFILE_INSERT_IFLD: */ FID,
        /* PROVENANCELINE_INSERT_IFLD: */ line_number,
        eloc, level);
    inter_error_message *E = VerifyingInter::instruction(pack, P); if (E) return E;
    NodePlacement::move_to_moving_bookmark(P, IBM);
    return NULL;
}

void InsertInstruction::transpose(inter_construct *IC, inter_tree_node *P, inter_ti *grid,
    inter_ti grid_extent, inter_error_message **E) {
    P->W.instruction[TEXT_INSERT_IFLD] = grid[P->W.instruction[TEXT_INSERT_IFLD]];
}

§3. Verification consists only of sanity checks.

void InsertInstruction::verify(inter_construct *IC, inter_tree_node *P,
    inter_package *owner, inter_error_message **E) {
    *E = VerifyingInter::text_field(owner, P, TEXT_INSERT_IFLD);
    if (*E) return;
    *E = VerifyingInter::text_field(owner, P, REPLACING_INSERT_IFLD);
    if (*E) return;
    *E = VerifyingInter::text_field(owner, P, PROVENANCEFILE_INSERT_IFLD);
    if (*E) return;
}

§4. Creating from textual Inter syntax.

void InsertInstruction::read(inter_construct *IC, inter_bookmark *IBM, inter_line_parse *ilp,
    inter_error_location *eloc, inter_error_message **E) {
    text_stream *rq = ilp->mr.exp[0];
    text_stream *repq = ilp->mr.exp[1];
    text_stream *fn = ilp->mr.exp[2];
    text_stream *lc = ilp->mr.exp[3];
    TEMPORARY_TEXT(raw)
    TEMPORARY_TEXT(replacing)
    TEMPORARY_TEXT(file_as_text)
    *E = TextualInter::parse_literal_text(raw, rq, 0, Str::len(rq), eloc);
    if (*E == NULL)
        *E = TextualInter::parse_literal_text(replacing, repq, 0, Str::len(repq), eloc);
    if (*E == NULL)
        *E = TextualInter::parse_literal_text(file_as_text, fn, 0, Str::len(fn), eloc);
    if (*E == NULL) {
        filename *F = NULL;
        if (Str::len(file_as_text) > 0) F = Filenames::from_text(file_as_text);
        inter_ti line_number = 0;
        if (Str::len(lc) > 0) line_number = (inter_ti) Str::atoi(lc, 0);
        *E = InsertInstruction::new(IBM, raw, replacing, F, line_number,
            (inter_ti) ilp->indent_level, eloc);
    }
    DISCARD_TEXT(raw)
    DISCARD_TEXT(replacing)
    DISCARD_TEXT(file_as_text)
}

§5. Writing to textual Inter syntax.

void InsertInstruction::write(inter_construct *IC, OUTPUT_STREAM, inter_tree_node *P) {
    text_stream *insertion = InsertInstruction::insertion(P);
    text_stream *replacing = InsertInstruction::replacing(P);
    WRITE("insert ");
    TextualInter::write_text(OUT, insertion);
    WRITE(" ");
    TextualInter::write_text(OUT, replacing);
    WRITE(" ");
    Provenance::write(OUT, InsertInstruction::provenance(P));
}

§6. Access functions.

text_stream *InsertInstruction::insertion(inter_tree_node *P) {
    if (P == NULL) return NULL;
    if (Inode::isnt(P, INSERT_IST)) return NULL;
    return Inode::ID_to_text(P, P->W.instruction[TEXT_INSERT_IFLD]);
}

text_stream *InsertInstruction::replacing(inter_tree_node *P) {
    if (P == NULL) return NULL;
    if (Inode::isnt(P, INSERT_IST)) return NULL;
    return Inode::ID_to_text(P, P->W.instruction[REPLACING_INSERT_IFLD]);
}

text_provenance InsertInstruction::provenance(inter_tree_node *P) {
    if (P == NULL) return Provenance::nowhere();
    if (Inode::isnt(P, INSERT_IST)) return Provenance::nowhere();
    return Provenance::at_file_and_line(
        Inode::ID_to_text(P, P->W.instruction[PROVENANCEFILE_INSERT_IFLD]),
        (int) P->W.instruction[PROVENANCELINE_INSERT_IFLD]);
}