Global variables translated to C.

§1.

void CGlobals::initialise(code_generator *gtr) {
    METHOD_ADD(gtr, DECLARE_VARIABLES_MTID, CGlobals::declare_variables);
    METHOD_ADD(gtr, EVALUATE_VARIABLE_MTID, CGlobals::evaluate_variable);
}

typedef struct C_generation_variables_data {
    int no_variables;
} C_generation_variables_data;

void CGlobals::initialise_data(code_generation *gen) {
    C_GEN_DATA(vardata.no_variables) = 1;
}

§2. The basic scheme is this: the global Inter variables are going to have their values stored in an array, so to identify which variable you are reading or writing, you need an index (i.e., position) in that array.

The main thing we need to compile is a (static) array of initial values for these variables, so that a new process can be initialised. But we must also define constants to refer to their positions in the array.

void CGlobals::begin(code_generation *gen) {
}

void CGlobals::end(code_generation *gen) {
    segmentation_pos saved = CodeGen::select(gen, c_ids_and_maxima_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE("#define i7_no_variables %d\n", C_GEN_DATA(vardata.no_variables));
    WRITE("i7word_t i7_initial_variable_values[i7_no_variables];\n");
    CodeGen::deselect(gen, saved);
}

§3. We will assign the global variables unique index numbers 0, 1, 2, ..., with the special variable self given index 0. Note that self always exists, but has no Inter declaration node.

void CGlobals::declare_variables(code_generator *gtr, code_generation *gen, linked_list *L) {
    segmentation_pos saved = CodeGen::select(gen, c_globals_array_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE("i7word_t i7_initial_variable_values[i7_no_variables] = {\n");

    Define a constant for the self position in the globals array3.1;
    Add the initial value for self to the globals array3.3;
    Define a more legible constant for self to the header target3.5;

    int N = 1;
    inter_symbol *var_name;
    LOOP_OVER_LINKED_LIST(var_name, inter_symbol, L) {
        text_stream *identifier = InterSymbol::trans(var_name);
        Define a constant for this position in the globals array3.2;
        Add the initial value to the globals array3.4;
        Define a more legible constant for the header target3.6;
        N++;
    }
    C_GEN_DATA(vardata.no_variables) = N;

    WRITE("};\n");
    CodeGen::deselect(gen, saved);
}

§3.1. Define a constant for the self position in the globals array3.1 =

    segmentation_pos saved = CodeGen::select(gen, c_ids_and_maxima_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE("#define ");
    CNamespace::mangle_variable(OUT, I"self");
    WRITE(" 0\n");
    CodeGen::deselect(gen, saved);

§3.2. Define a constant for this position in the globals array3.2 =

    segmentation_pos saved = CodeGen::select(gen, c_predeclarations_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE("#define ");
    CNamespace::mangle_variable(OUT, identifier);
    WRITE(" %d\n", N);
    CodeGen::deselect(gen, saved);

§3.3. Add the initial value for self to the globals array3.3 =

    segmentation_pos saved = CodeGen::select(gen, c_globals_array_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE("  0 /* self */\n");
    CodeGen::deselect(gen, saved);

§3.4. Add the initial value to the globals array3.4 =

    segmentation_pos saved = CodeGen::select(gen, c_globals_array_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE(", ");
    if (var_name->definition) {
        inter_tree_node *P = var_name->definition;
        CodeGen::pair(gen, P, VariableInstruction::value(P));
    } else {
        WRITE("0");
    }
    WRITE(" /* %S */\n", identifier);
    CodeGen::deselect(gen, saved);

§3.5. Define a more legible constant for self to the header target3.5 =

    CGlobals::define_header_constant_for_variable(gen, I"self", 0);

§3.6. Define a more legible constant for the header target3.6 =

    text_stream *name = Metadata::optional_textual(
        InterPackage::container(var_name->definition), I"^name");
    if (name)
        CGlobals::define_header_constant_for_variable(gen, name, N);
    else
        CGlobals::define_header_constant_for_variable(gen, identifier, N);

§4.

void CGlobals::define_header_constant_for_variable(code_generation *gen, text_stream *var_name,
    int id) {
    segmentation_pos saved = CodeGen::select(gen, c_variable_symbols_I7CGS);
    text_stream *OUT = CodeGen::current(gen);
    WRITE("#define %S %d\n", CTarget::symbols_header_identifier(gen, I"V", var_name), id);
    CodeGen::deselect(gen, saved);
}

§5. Within a process proc, the current value of variable i is proc->state.variables[i].

void CGlobals::evaluate_variable(code_generator *gtr, code_generation *gen,
    inter_symbol *var_name, int as_reference) {
    text_stream *OUT = CodeGen::current(gen);
    WRITE("proc->state.variables[");
    CNamespace::mangle_variable(OUT, InterSymbol::trans(var_name));
    WRITE("]");
}

§6. Finally, this function, part of the C library, initialises the variables for a newly-starting process.

void i7_initialise_variables(i7process_t *proc);
void i7_initialise_variables(i7process_t *proc) {
    proc->state.variables = i7_calloc(proc, i7_no_variables, sizeof(i7word_t));
    for (int i=0; i<i7_no_variables; i++)
        proc->state.variables[i] = i7_initial_variable_values[i];
}