Global variables translated to C.
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; }
- The structure C_generation_variables_data is private to this section.
§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);
- This code is used in §3.
§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);
- This code is used in §3.
§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);
- This code is used in §3.
§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);
- This code is used in §3.
§3.5. Define a more legible constant for self to the header target3.5 =
CGlobals::define_header_constant_for_variable(gen, I"self", 0);
- This code is used in §3.
§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);
- This code is used in §3.
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);
- This is part of the extract file inform7_clib.h.
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]; }
- This is part of the extract file inform7_clib.c.