The standard set of primitive invocations available in Inter code as generated by the Inform tool-chain.
§1. The standard Inform 7 instruction set. Metadata on the primitives used by Inter in the Inform tool-set is stored as
an array standard_inform7_primitives of the following records:
typedef struct inform7_primitive { inter_ti BIP; char *name_c; char *signature_c; struct text_stream *name; struct text_stream *signature; int term_count; int term_categories[8]; int takes_code_blocks; } inform7_primitive;
- The structure inform7_primitive is accessed in 2/i6o and here.
§2. Each different primitive has a unique BIP number. (The origins of the term BIP are now lost, though the I and the P presumably once stood for "Inform" and "primitive".) BIPs count upwards contiguously from 1.
The point of BIPs is simply that it would be too slow to index primitives only by their instruction names, because even with all the hashing in the world, there would have to be string comparisons.
define MAX_BIPS 100
enumerate PLUS_BIP 1
enumerate MINUS_BIP
enumerate UNARYMINUS_BIP
enumerate TIMES_BIP
enumerate DIVIDE_BIP
enumerate MODULO_BIP
enumerate BITWISEAND_BIP
enumerate BITWISEOR_BIP
enumerate BITWISENOT_BIP
enumerate SEQUENTIAL_BIP
enumerate TERNARYSEQUENTIAL_BIP
enumerate RANDOM_BIP
enumerate STORE_BIP
enumerate PREINCREMENT_BIP
enumerate POSTINCREMENT_BIP
enumerate PREDECREMENT_BIP
enumerate POSTDECREMENT_BIP
enumerate SETBIT_BIP
enumerate CLEARBIT_BIP
enumerate PUSH_BIP
enumerate PULL_BIP
enumerate LOOKUP_BIP
enumerate LOOKUPBYTE_BIP
enumerate PROPERTYARRAY_BIP
enumerate PROPERTYLENGTH_BIP
enumerate PROPERTYEXISTS_BIP
enumerate PROPERTYVALUE_BIP
enumerate MOVE_BIP
enumerate REMOVE_BIP
enumerate CHILD_BIP
enumerate CHILDREN_BIP
enumerate SIBLING_BIP
enumerate PARENT_BIP
enumerate METACLASS_BIP
enumerate NOT_BIP
enumerate AND_BIP
enumerate OR_BIP
enumerate EQ_BIP
enumerate NE_BIP
enumerate GT_BIP
enumerate GE_BIP
enumerate LT_BIP
enumerate LE_BIP
enumerate OFCLASS_BIP
enumerate IN_BIP
enumerate NOTIN_BIP
enumerate ALTERNATIVE_BIP
enumerate ENABLEPRINTING_BIP
enumerate FONT_BIP
enumerate STYLE_BIP
enumerate PRINT_BIP
enumerate PRINTNL_BIP
enumerate PRINTCHAR_BIP
enumerate PRINTOBJ_BIP
enumerate PRINTNUMBER_BIP
enumerate PRINTDWORD_BIP
enumerate PRINTSTRING_BIP
enumerate BOX_BIP
enumerate SPACES_BIP
enumerate IF_BIP
enumerate IFDEBUG_BIP
enumerate IFSTRICT_BIP
enumerate IFELSE_BIP
enumerate WHILE_BIP
enumerate DO_BIP
enumerate FOR_BIP
enumerate OBJECTLOOP_BIP
enumerate OBJECTLOOPX_BIP
enumerate BREAK_BIP
enumerate CONTINUE_BIP
enumerate SWITCH_BIP
enumerate CASE_BIP
enumerate ALTERNATIVECASE_BIP
enumerate DEFAULT_BIP
enumerate RETURN_BIP
enumerate JUMP_BIP
enumerate QUIT_BIP
enumerate RESTORE_BIP
enumerate INDIRECT0V_BIP
enumerate INDIRECT1V_BIP
enumerate INDIRECT2V_BIP
enumerate INDIRECT3V_BIP
enumerate INDIRECT4V_BIP
enumerate INDIRECT5V_BIP
enumerate INDIRECT6V_BIP
enumerate INDIRECT0_BIP
enumerate INDIRECT1_BIP
enumerate INDIRECT2_BIP
enumerate INDIRECT3_BIP
enumerate INDIRECT4_BIP
enumerate INDIRECT5_BIP
enumerate INDIRECT6_BIP
enumerate MESSAGE0_BIP
enumerate MESSAGE1_BIP
enumerate MESSAGE2_BIP
enumerate MESSAGE3_BIP
enumerate EXTERNALCALL_BIP
§3. And here is the array of metadata. It's tiresome to have to include the null
fields here, which is done only because text_stream literals I"like this"
cannot be compiled in a constant context by the clang C compiler. So the
names and signatures of the primitives are compiled as char * literals instead,
and converted on first use at runtime.
It is essential that the sequence of rows below is the same as the sequence of enumerations above; but Primitives::prepare_standard_set_array checks this at runtime and throws an error if not.
define SIP_RECORD_END NULL, NULL, 0, { VAL_PRIM_CAT, VAL_PRIM_CAT, VAL_PRIM_CAT, VAL_PRIM_CAT, VAL_PRIM_CAT, VAL_PRIM_CAT, VAL_PRIM_CAT, VAL_PRIM_CAT }, FALSE
inform7_primitive standard_inform7_primitives[] = { { PLUS_BIP, "!plus", "val val -> val", SIP_RECORD_END }, { MINUS_BIP, "!minus", "val val -> val", SIP_RECORD_END }, { UNARYMINUS_BIP, "!unaryminus", "val -> val", SIP_RECORD_END }, { TIMES_BIP, "!times", "val val -> val", SIP_RECORD_END }, { DIVIDE_BIP, "!divide", "val val -> val", SIP_RECORD_END }, { MODULO_BIP, "!modulo", "val val -> val", SIP_RECORD_END }, { BITWISEAND_BIP, "!bitwiseand", "val val -> val", SIP_RECORD_END }, { BITWISEOR_BIP, "!bitwiseor", "val val -> val", SIP_RECORD_END }, { BITWISENOT_BIP, "!bitwisenot", "val -> val", SIP_RECORD_END }, { SEQUENTIAL_BIP, "!sequential", "val val -> val", SIP_RECORD_END }, { TERNARYSEQUENTIAL_BIP, "!ternarysequential", "val val val -> val", SIP_RECORD_END }, { RANDOM_BIP, "!random", "val -> val", SIP_RECORD_END }, { STORE_BIP, "!store", "ref val -> val", SIP_RECORD_END }, { PREINCREMENT_BIP, "!preincrement", "ref -> val", SIP_RECORD_END }, { POSTINCREMENT_BIP, "!postincrement", "ref -> val", SIP_RECORD_END }, { PREDECREMENT_BIP, "!predecrement", "ref -> val", SIP_RECORD_END }, { POSTDECREMENT_BIP, "!postdecrement", "ref -> val", SIP_RECORD_END }, { SETBIT_BIP, "!setbit", "ref val -> void", SIP_RECORD_END }, { CLEARBIT_BIP, "!clearbit", "ref val -> void", SIP_RECORD_END }, { PUSH_BIP, "!push", "val -> void", SIP_RECORD_END }, { PULL_BIP, "!pull", "ref -> void", SIP_RECORD_END }, { LOOKUP_BIP, "!lookup", "val val -> val", SIP_RECORD_END }, { LOOKUPBYTE_BIP, "!lookupbyte", "val val -> val", SIP_RECORD_END }, { PROPERTYARRAY_BIP, "!propertyarray", "val val val -> val", SIP_RECORD_END }, { PROPERTYLENGTH_BIP, "!propertylength", "val val val -> val", SIP_RECORD_END }, { PROPERTYEXISTS_BIP, "!propertyexists", "val val val -> val", SIP_RECORD_END }, { PROPERTYVALUE_BIP, "!propertyvalue", "val val val -> val", SIP_RECORD_END }, { MOVE_BIP, "!move", "val val -> void", SIP_RECORD_END }, { REMOVE_BIP, "!remove", "val -> void", SIP_RECORD_END }, { CHILD_BIP, "!child", "val -> val", SIP_RECORD_END }, { CHILDREN_BIP, "!children", "val -> val", SIP_RECORD_END }, { SIBLING_BIP, "!sibling", "val -> val", SIP_RECORD_END }, { PARENT_BIP, "!parent", "val -> val", SIP_RECORD_END }, { METACLASS_BIP, "!metaclass", "val -> val", SIP_RECORD_END }, { NOT_BIP, "!not", "val -> val", SIP_RECORD_END }, { AND_BIP, "!and", "val val -> val", SIP_RECORD_END }, { OR_BIP, "!or", "val val -> val", SIP_RECORD_END }, { EQ_BIP, "!eq", "val val -> val", SIP_RECORD_END }, { NE_BIP, "!ne", "val val -> val", SIP_RECORD_END }, { GT_BIP, "!gt", "val val -> val", SIP_RECORD_END }, { GE_BIP, "!ge", "val val -> val", SIP_RECORD_END }, { LT_BIP, "!lt", "val val -> val", SIP_RECORD_END }, { LE_BIP, "!le", "val val -> val", SIP_RECORD_END }, { OFCLASS_BIP, "!ofclass", "val val -> val", SIP_RECORD_END }, { IN_BIP, "!in", "val val -> val", SIP_RECORD_END }, { NOTIN_BIP, "!notin", "val val -> val", SIP_RECORD_END }, { ALTERNATIVE_BIP, "!alternative", "val val -> val", SIP_RECORD_END }, { ENABLEPRINTING_BIP, "!enableprinting", "void -> void", SIP_RECORD_END }, { FONT_BIP, "!font", "val -> void", SIP_RECORD_END }, { STYLE_BIP, "!style", "val -> void", SIP_RECORD_END }, { PRINT_BIP, "!print", "val -> void", SIP_RECORD_END }, { PRINTNL_BIP, "!printnl", "void -> void", SIP_RECORD_END }, { PRINTCHAR_BIP, "!printchar", "val -> void", SIP_RECORD_END }, { PRINTOBJ_BIP, "!printobj", "val -> void", SIP_RECORD_END }, { PRINTNUMBER_BIP, "!printnumber", "val -> void", SIP_RECORD_END }, { PRINTDWORD_BIP, "!printdword", "val -> void", SIP_RECORD_END }, { PRINTSTRING_BIP, "!printstring", "val -> void", SIP_RECORD_END }, { BOX_BIP, "!box", "val -> void", SIP_RECORD_END }, { SPACES_BIP, "!spaces", "val -> void", SIP_RECORD_END }, { IF_BIP, "!if", "val code -> void", SIP_RECORD_END }, { IFDEBUG_BIP, "!ifdebug", "code -> void", SIP_RECORD_END }, { IFSTRICT_BIP, "!ifstrict", "code -> void", SIP_RECORD_END }, { IFELSE_BIP, "!ifelse", "val code code -> void", SIP_RECORD_END }, { WHILE_BIP, "!while", "val code -> void", SIP_RECORD_END }, { DO_BIP, "!do", "val code -> void", SIP_RECORD_END }, { FOR_BIP, "!for", "val val val code -> void", SIP_RECORD_END }, { OBJECTLOOP_BIP, "!objectloop", "ref val val code -> void", SIP_RECORD_END }, { OBJECTLOOPX_BIP, "!objectloopx", "ref val code -> void", SIP_RECORD_END }, { BREAK_BIP, "!break", "void -> void", SIP_RECORD_END }, { CONTINUE_BIP, "!continue", "void -> void", SIP_RECORD_END }, { SWITCH_BIP, "!switch", "val code -> void", SIP_RECORD_END }, { CASE_BIP, "!case", "val code -> void", SIP_RECORD_END }, { ALTERNATIVECASE_BIP, "!alternativecase", "val val -> val", SIP_RECORD_END }, { DEFAULT_BIP, "!default", "code -> void", SIP_RECORD_END }, { RETURN_BIP, "!return", "val -> void", SIP_RECORD_END }, { JUMP_BIP, "!jump", "lab -> void", SIP_RECORD_END }, { QUIT_BIP, "!quit", "void -> void", SIP_RECORD_END }, { RESTORE_BIP, "!restore", "lab -> void", SIP_RECORD_END }, { INDIRECT0V_BIP, "!indirect0v", "val -> void", SIP_RECORD_END }, { INDIRECT1V_BIP, "!indirect1v", "val val -> void", SIP_RECORD_END }, { INDIRECT2V_BIP, "!indirect2v", "val val val -> void", SIP_RECORD_END }, { INDIRECT3V_BIP, "!indirect3v", "val val val val -> void", SIP_RECORD_END }, { INDIRECT4V_BIP, "!indirect4v", "val val val val val -> void", SIP_RECORD_END }, { INDIRECT5V_BIP, "!indirect5v", "val val val val val val -> void", SIP_RECORD_END }, { INDIRECT6V_BIP, "!indirect6v", "val val val val val val val -> void", SIP_RECORD_END }, { INDIRECT0_BIP, "!indirect0", "val -> val", SIP_RECORD_END }, { INDIRECT1_BIP, "!indirect1", "val val -> val", SIP_RECORD_END }, { INDIRECT2_BIP, "!indirect2", "val val val -> val", SIP_RECORD_END }, { INDIRECT3_BIP, "!indirect3", "val val val val -> val", SIP_RECORD_END }, { INDIRECT4_BIP, "!indirect4", "val val val val val -> val", SIP_RECORD_END }, { INDIRECT5_BIP, "!indirect5", "val val val val val val -> val", SIP_RECORD_END }, { INDIRECT6_BIP, "!indirect6", "val val val val val val val -> val", SIP_RECORD_END }, { MESSAGE0_BIP, "!message0", "val val -> val", SIP_RECORD_END }, { MESSAGE1_BIP, "!message1", "val val val -> val", SIP_RECORD_END }, { MESSAGE2_BIP, "!message2", "val val val val -> val", SIP_RECORD_END }, { MESSAGE3_BIP, "!message3", "val val val val val -> val", SIP_RECORD_END }, { EXTERNALCALL_BIP, "!externalcall", "val val -> val", SIP_RECORD_END }, { 0, "", "", SIP_RECORD_END } };
§4. The following must be called before the above array can be used. It checks
that the numbering is right, and converts the names and signatures from char *
to text_stream *.
int standard_inform7_primitives_prepared = FALSE; inter_ti standard_inform7_primitives_extent = 0; void Primitives::prepare_standard_set_array(void) { if (standard_inform7_primitives_prepared == FALSE) { standard_inform7_primitives_prepared = TRUE; for (inter_ti i=0; ; i++) { if (standard_inform7_primitives[i].BIP == 0) break; if (i >= MAX_BIPS) internal_error("MAX_BIPS set too low"); if (standard_inform7_primitives[i].BIP != i+1) internal_error("primitives table disordered"); standard_inform7_primitives[i].name = Str::new(); WRITE_TO(standard_inform7_primitives[i].name, "%s", standard_inform7_primitives[i].name_c); standard_inform7_primitives[i].signature = Str::new(); WRITE_TO(standard_inform7_primitives[i].signature, "%s", standard_inform7_primitives[i].signature_c); Parse and sanity-check the signature text4.1; standard_inform7_primitives_extent++; } } }
§4.1. We only care here abput the part of the signature before the ->, but we go
ahead and perform a full sanity check on it anyway, just in case somebody some day
amends the above table but gets it wrong. The time consumed by these checks
is trivial, since this happens only once per run.
Parse and sanity-check the signature text4.1 =
int p = 0, before_arrow = TRUE, pre_void = FALSE, inputs = 0, outputs = 0; text_stream *S = standard_inform7_primitives[i].signature; TEMPORARY_TEXT(term) while (p <= Str::len(S)) { inchar32_t c = Str::get_at(S, p); if ((Characters::is_whitespace(c)) || (c == 0)) { if ((Str::eq(term, I"->")) && (before_arrow)) before_arrow = FALSE; else { int this = -1; if (Str::eq(term, I"void")) { this = -2; if (before_arrow) pre_void = TRUE; } if (Str::eq(term, I"val")) this = VAL_PRIM_CAT; if (Str::eq(term, I"ref")) this = REF_PRIM_CAT; if (Str::eq(term, I"lab")) this = LAB_PRIM_CAT; if (Str::eq(term, I"code")) this = CODE_PRIM_CAT; if (this == -1) internal_error("unknown term category in primitive"); if (before_arrow) { if (this != -2) { if (inputs >= 8) internal_error("too many terms in primitive"); standard_inform7_primitives[i].term_categories[inputs] = this; inputs++; } } else { if ((this != -2) && (this != VAL_PRIM_CAT)) internal_error("bad term after -> in primitive"); outputs++; } } Str::clear(term); } else { PUT_TO(term, c); } p++; } DISCARD_TEXT(term) if ((outputs > 1) || ((pre_void) && (inputs > 0))) internal_error("malformed signature in primitive"); standard_inform7_primitives[i].term_count = inputs; standard_inform7_primitives[i].takes_code_blocks = FALSE; for (int t=0; t<inputs; t++) if (standard_inform7_primitives[i].term_categories[t] == CODE_PRIM_CAT) standard_inform7_primitives[i].takes_code_blocks = TRUE;
- This code is used in §4.
§5. We can now convert between BIP and name. Note that Primitives::name_to_BIP is relatively slow: but this doesn't matter because we will always cache the results (see below).
text_stream *Primitives::BIP_to_name(inter_ti bip) { Primitives::prepare_standard_set_array(); if ((bip >= 1) && (bip <= standard_inform7_primitives_extent)) return standard_inform7_primitives[bip - 1].name; return I"<none>"; } inter_ti Primitives::name_to_BIP(text_stream *name) { Primitives::prepare_standard_set_array(); for (inter_ti i=0; i<standard_inform7_primitives_extent; i++) if (Str::eq(name, standard_inform7_primitives[i].name)) return i+1; return 0; }
§6. This is printed when inter is run with the -primitives switch.
void Primitives::show_primitives(OUTPUT_STREAM) { WRITE(" Code Primitive Signature\n"); Primitives::prepare_standard_set_array(); for (inter_ti i=0; i<standard_inform7_primitives_extent; i++) { inform7_primitive *prim = &(standard_inform7_primitives[i]); WRITE(" %4x %S", prim->BIP, prim->name); for (int j = Str::len(prim->name); j<20; j++) PUT(' '); WRITE("%S\n", prim->signature); } }
§7. In general the standard set is a miscellany, but with one systematic family of primitives for making indirect function calls (that is, calling a function whose identity is not known at compile time). These 12 primitives all do the same thing, but vary in their signatures, according to how many arguments the function call has, and whether its return value is to be used or discarded.
The following functions allow us to ask for the right primitive for the job:
int Primitives::arity_too_great_for_indirection(int arity) { if (arity > 6) return TRUE; return FALSE; } inter_ti Primitives::BIP_for_indirect_call_returning_value(int arity) { switch (arity) { case 0: return INDIRECT0_BIP; case 1: return INDIRECT1_BIP; case 2: return INDIRECT2_BIP; case 3: return INDIRECT3_BIP; case 4: return INDIRECT4_BIP; case 5: return INDIRECT5_BIP; case 6: return INDIRECT6_BIP; default: internal_error("indirect function call with too many arguments"); } return 0; } inter_ti Primitives::BIP_for_void_indirect_call(int arity) { switch (arity) { case 0: return INDIRECT0V_BIP; case 1: return INDIRECT1V_BIP; case 2: return INDIRECT2V_BIP; case 3: return INDIRECT3V_BIP; case 4: return INDIRECT4V_BIP; case 5: return INDIRECT5V_BIP; case 6: return INDIRECT6V_BIP; default: internal_error("indirectv function call with too many arguments"); } return 0; } inter_ti Primitives::BIP_for_message_send(int arity) { switch (arity) { case 2: return MESSAGE0_BIP; case 3: return MESSAGE1_BIP; case 4: return MESSAGE2_BIP; case 5: return MESSAGE3_BIP; default: internal_error("message call must have arity 2 to 5"); } return 0; }
int Primitives::is_BIP_for_indirect_call_returning_value(inter_ti s) { if (s == INDIRECT0_BIP) return TRUE; if (s == INDIRECT1_BIP) return TRUE; if (s == INDIRECT2_BIP) return TRUE; if (s == INDIRECT3_BIP) return TRUE; if (s == INDIRECT4_BIP) return TRUE; if (s == INDIRECT5_BIP) return TRUE; if (s == INDIRECT6_BIP) return TRUE; return FALSE; } int Primitives::is_BIP_for_void_indirect_call(inter_ti s) { if (s == INDIRECT0V_BIP) return TRUE; if (s == INDIRECT1V_BIP) return TRUE; if (s == INDIRECT2V_BIP) return TRUE; if (s == INDIRECT3V_BIP) return TRUE; if (s == INDIRECT4V_BIP) return TRUE; if (s == INDIRECT5V_BIP) return TRUE; if (s == INDIRECT6V_BIP) return TRUE; return FALSE; }
§9. About the terms. For example, 0 for the signature void -> val, or 2 for ref val -> val.
The *_XBIP operations are treated as if they had the signature val val -> void.
int Primitives::term_count(inter_ti BIP) { Primitives::prepare_standard_set_array(); if (BIP >= LOWEST_XBIP_VALUE) return 2; return standard_inform7_primitives[BIP - 1].term_count; }
§10. And this returns the primitive category for each term, counting from 0:
this will be VAL_PRIM_CAT, CODE_PRIM_CAT, REF_PRIM_CAT or LAB_PRIM_CAT.
Again, the *_XBIP operations are treated as if val val -> void.
int Primitives::term_category(inter_ti BIP, int i) { Primitives::prepare_standard_set_array(); if ((i < 0) || (i >= 8)) internal_error("term out of range"); if (BIP >= LOWEST_XBIP_VALUE) return VAL_PRIM_CAT; return standard_inform7_primitives[BIP - 1].term_categories[i]; }
§11. Returns TRUE if any of those categories is a CODE_PRIM_CAT; note that
this is cached for speed.
int Primitives::takes_code_blocks(inter_ti BIP) { Primitives::prepare_standard_set_array(); if (BIP >= LOWEST_XBIP_VALUE) return FALSE; return standard_inform7_primitives[BIP - 1].takes_code_blocks; }
§12. Primitives within a specific tree. So much for discussing the instruction set in the abstract: now we need code
to handle its declaration in each Inter tree we make. Note that, for speed,
each inter_tree structure contains the following index array inside it:
typedef struct site_primitives_data { struct inter_symbol *primitives_by_BIP[MAX_BIPS]; } site_primitives_data; void Primitives::clear_site_data(inter_tree *I) { building_site *B = &(I->site); for (int i=0; i<MAX_BIPS; i++) B->spridata.primitives_by_BIP[i] = NULL; }
- The structure site_primitives_data is private to this section.
§13. That array will allow us to obtain almost instantly the Inter symbol for
the primitive in I having any given BIP. We need to remember that primitives
can come into being in two ways, though: either by us creating them here (see
below), or by Inter code being read in from an external file. If the latter,
the following function must be run to make sure the index is built:
void Primitives::index_primitives_in_tree(inter_tree *I) { InterTree::traverse_root_only(I, Primitives::scan_visitor, NULL, PRIMITIVE_IST); } void Primitives::scan_visitor(inter_tree *I, inter_tree_node *P, void *v_state) { inter_symbol *prim = PrimitiveInstruction::primitive(P); inter_ti bip = Primitives::to_BIP(I, prim); if (bip) I->site.spridata.primitives_by_BIP[bip] = prim; }
§14. Here is where we declare primitives. Since there are only around 100 of these, it's fine for the actual primitive declarations to be made a little slowly: so we do it by writing the declarations out in textual Inter and then parsing them. We then make various paranoid consistency checks.
void Primitives::declare_standard_set(inter_tree *I, inter_bookmark *IBM) { Primitives::prepare_standard_set_array(); for (inter_ti i=0; i<standard_inform7_primitives_extent; i++) Primitives::declare_one(I, IBM, &(standard_inform7_primitives[i])); } inter_symbol *Primitives::declare_one(inter_tree *I, inter_bookmark *IBM, inform7_primitive *prim) { text_stream *name = prim->name; text_stream *signature = prim->signature; TEMPORARY_TEXT(prim_command) WRITE_TO(prim_command, "primitive %S %S", name, signature); Produce::guard(TextualInter::parse_single_line(prim_command, NULL, IBM)); inter_error_message *E = NULL; inter_symbol *S = TextualInter::find_global_symbol(IBM, NULL, name, PRIMITIVE_IST, &E); inter_ti bip = Primitives::to_BIP(I, S); if (bip == 0) internal_error("missing bip"); if (bip != prim->BIP) internal_error("wrong BIP"); if (bip >= MAX_BIPS) internal_error("unsafely high bip"); I->site.spridata.primitives_by_BIP[bip] = S; Produce::guard(E); DISCARD_TEXT(prim_command) return S; }
inter_symbol *Primitives::declare_one_named(inter_tree *I, inter_bookmark *IBM, text_stream *name) { Primitives::prepare_standard_set_array(); for (inter_ti i=0; i<standard_inform7_primitives_extent; i++) { inform7_primitive *prim = &(standard_inform7_primitives[i]); if (Str::eq(prim->name, name)) return Primitives::declare_one(I, IBM, prim); } return NULL; }
inter_symbol *Primitives::from_BIP(inter_tree *I, inter_ti bip) { if (I == NULL) internal_error("no tree"); if ((bip < 1) || (bip >= MAX_BIPS)) internal_error("bip out of range"); inter_symbol *prim = I->site.spridata.primitives_by_BIP[bip]; if (prim == NULL) { WRITE_TO(STDERR, "BIP = %d\n", bip); internal_error("undefined primitive"); } return prim; } inter_ti Primitives::to_BIP(inter_tree *I, inter_symbol *symb) { if (symb == NULL) return 0; inter_ti B = PrimitiveInstruction::get_BIP(symb); if (B == 0) { B = Primitives::name_to_BIP(InterSymbol::identifier(symb)); if (B != 0) PrimitiveInstruction::set_BIP(symb, B); } return B; }