From 8c553d6565ee1ff6d7679e65f7958c36a5858522 Mon Sep 17 00:00:00 2001
From: Graham Nelson
-[ WhetherProvides K obj q issue_rtp a l holder; - if (K ~= OBJECT_TY) { - if ((obj < 1) || (obj > value_ranges-->K)) { - if (issue_rtp) RunTimeProblem(RTP_BADVALUEPROPERTY); - rfalse; - } else { - holder = value_property_holders-->K; - if ((holder) && (holder provides q)) rtrue; +[ ProvidesProperty K obj q issue_rtp a l holder; + if (K == OBJECT_TY) { + if (ScanPropertyMetadata(obj, q, 4)) jump PermissionFound; + if (obj provides KD_Count) { + l = obj.KD_Count; + while (l > 0) { + a = l*2; + if (ScanPropertyMetadata(KindHierarchy-->a, q, 4)) jump PermissionFound; + l = KindHierarchy-->(a+1); + } } - } - if (obj == 0) { - if (issue_rtp) RunTimeProblem(RTP_PROPOFNOTHING, 0, q); + if (ScanPropertyMetadata(K0_kind, q, 4)) jump PermissionFound; + if (issue_rtp) RunTimeProblem(RTP_UNPROVIDED, obj, q); rfalse; } - if (metaclass(obj) ~= Object) rfalse; - if (q<0) q = ~q; - - if (ScanPropertyMetadata(obj, q, 4)) jump PermissionFound; - if (obj provides KD_Count) { - l = obj.KD_Count; - while (l > 0) { - a = l*2; - if (ScanPropertyMetadata(KindHierarchy-->a, q, 4)) jump PermissionFound; - l = KindHierarchy-->(a+1); - } - } - if (ScanPropertyMetadata(K0_kind, q, 4)) jump PermissionFound; - if (issue_rtp) RunTimeProblem(RTP_UNPROVIDED, obj, q); - rfalse; .PermissionFound; - if (q-->2) rtrue; - if (obj provides q) rtrue; - if (issue_rtp) RunTimeProblem(RTP_UNSET, obj, q); - rfalse; + + @provides_gprop K obj q a; + if (a) rtrue; +if (K ~= OBJECT_TY) { + if ((obj >= 1) && (obj <= value_ranges-->K)) { + holder = value_property_holders-->K; + if ((holder) && (holder provides q)) rtrue; + } +} else { + if ((obj) && (metaclass(obj) == Object)) { + if (q-->0 == 2) rtrue; + if (obj provides q) rtrue; + } +} + + if (issue_rtp) RunTimeProblem(RTP_UNSET, obj, q); + rfalse; ]; [ PrintPropertyName p textual; @@ -375,18 +374,20 @@ the one which the player is on.-[ GProperty K V pr err holder; - if (WhetherProvides(K, V, pr, 1-err)) { - if (K == OBJECT_TY) { - if (pr-->0 == 2) { - if (V has pr) rtrue; rfalse; - } - if (pr == door_to) return V.pr(); - return V.pr; - } else { - holder = value_property_holders-->K; - return (holder.pr)-->(V+COL_HSIZE); - } +[ GProperty K V pr err holder val; + if (ProvidesProperty(K, V, pr, 1-err)) { + @read_gprop K V pr val; + return val; + if (K == OBJECT_TY) { + if (pr-->0 == 2) { + if (V has pr) rtrue; rfalse; + } + if (pr == door_to) return V.pr(); + return V.pr; + } else { + holder = value_property_holders-->K; + return (holder.pr)-->(V+COL_HSIZE); + } } return 0; ]; @@ -398,17 +399,18 @@ converted from an rvalue to an lvalue.[ WriteGProperty K V pr val holder; - if (WhetherProvides(K, V, pr, true)) { - if (K == OBJECT_TY) { - if (pr-->0 == 2) { - if (val) give V pr; else give V ~pr; - } else { - V.pr = val; - } - } else { - holder = value_property_holders-->K; - (holder.pr)-->(V+COL_HSIZE) = val; - } + if (ProvidesProperty(K, V, pr, true)) { + @write_gprop K V pr val; + if (K == OBJECT_TY) { + if (pr-->0 == 2) { + if (val) give V pr; else give V ~pr; + } else { + V.pr = val; + } + } else { + holder = value_property_holders-->K; + (holder.pr)-->(V+COL_HSIZE) = val; + } } ];diff --git a/docs/final-module/2-cg.html b/docs/final-module/2-cg.html index 9c750a932..99a7234c6 100644 --- a/docs/final-module/2-cg.html +++ b/docs/final-module/2-cg.html @@ -334,7 +334,7 @@ but for now about 10 layers is plenty.-segmentation_pos CodeGen::select(code_generation *gen, int i) { +segmentation_pos CodeGen::select(code_generation *gen, int i) { return CodeGen::select_layered(gen, i, 1); } @@ -351,7 +351,7 @@ but for now about 10 layers is plenty. return previous_pos; } -void CodeGen::deselect(code_generation *gen, segmentation_pos saved) { +void CodeGen::deselect(code_generation *gen, segmentation_pos saved) { if (gen->segmentation.temporarily_diverted) internal_error("poorly timed deselection"); gen->segmentation.pos = saved; } @@ -361,13 +361,13 @@ some temporary stream somewhere. For that, use the following pair:+-void CodeGen::select_temporary(code_generation *gen, text_stream *T) { +void CodeGen::select_temporary(code_generation *gen, text_stream *T) { if (gen->segmentation.temporarily_diverted) internal_error("nested temporary segments"); gen->segmentation.temporarily_diverted_to = T; gen->segmentation.temporarily_diverted = TRUE; } -void CodeGen::deselect_temporary(code_generation *gen) { +void CodeGen::deselect_temporary(code_generation *gen) { gen->segmentation.temporarily_diverted_to = NULL; gen->segmentation.temporarily_diverted = FALSE; } @@ -377,7 +377,7 @@ if it has been "temporarily diverted" then the regiular selection is ignored.-text_stream *CodeGen::current(code_generation *gen) { +text_stream *CodeGen::current(code_generation *gen) { if (gen->segmentation.temporarily_diverted) return gen->segmentation.temporarily_diverted_to; if (gen->segmentation.pos.current_segment == NULL) return NULL; @@ -453,7 +453,7 @@ extracted from some Inter instruction. Generate from a value pair15.1; } -void CodeGen::pair(code_generation *gen, inter_tree_node *P, +void CodeGen::pair(code_generation *gen, inter_tree_node *P, inter_ti val1, inter_ti val2) { inter_symbols_table *T = P?(Inter::Packages::scope_of(P)):NULL; Generate from a value pair15.1; diff --git a/docs/final-module/2-cg2.html b/docs/final-module/2-cg2.html index 28d3fc018..f736613f1 100644 --- a/docs/final-module/2-cg2.html +++ b/docs/final-module/2-cg2.html @@ -233,7 +233,7 @@ I6 code. Still, all pragmas are offered to all generators.VOID_METHOD_TYPE(MANGLE_IDENTIFIER_MTID, code_generator *generator, text_stream *OUT, text_stream *identifier) -void Generators::mangle(code_generation *gen, text_stream *OUT, text_stream *identifier) { +void Generators::mangle(code_generation *gen, text_stream *OUT, text_stream *identifier) { VOID_METHOD_CALL(gen->generator, MANGLE_IDENTIFIER_MTID, OUT, identifier); }diff --git a/docs/final-module/2-tvg.html b/docs/final-module/2-tvg.html index a81209a25..137e0d4bf 100644 --- a/docs/final-module/2-tvg.html +++ b/docs/final-module/2-tvg.html @@ -254,7 +254,7 @@ well the entire tree by the end. define VNODE_ALLC LOOP_THROUGH_INTER_CHILDREN(C, P) Vanilla::node(gen, C)-void Vanilla::node(code_generation *gen, inter_tree_node *P) { +void Vanilla::node(code_generation *gen, inter_tree_node *P) { switch (P->W.data[ID_IFLD]) { case CONSTANT_IST: VanillaConstants::constant(gen, P); break; diff --git a/docs/final-module/4-fi6.html b/docs/final-module/4-fi6.html index 576fc1f17..c9850abaf 100644 --- a/docs/final-module/4-fi6.html +++ b/docs/final-module/4-fi6.html @@ -146,15 +146,15 @@ function togglePopup(material_id) { METHOD_ADD(cgt, EVALUATE_LABEL_MTID, I6Target::evaluate_label); METHOD_ADD(cgt, INVOKE_FUNCTION_MTID, I6Target::invoke_function); METHOD_ADD(cgt, INVOKE_OPCODE_MTID, I6Target::invoke_opcode); - METHOD_ADD(cgt, BEGIN_ARRAY_MTID, I6Target::begin_array); - METHOD_ADD(cgt, ARRAY_ENTRY_MTID, I6Target::array_entry); - METHOD_ADD(cgt, COMPILE_LITERAL_SYMBOL_MTID, I6Target::compile_literal_symbol); - METHOD_ADD(cgt, ARRAY_ENTRIES_MTID, I6Target::array_entries); - METHOD_ADD(cgt, END_ARRAY_MTID, I6Target::end_array); + METHOD_ADD(cgt, BEGIN_ARRAY_MTID, I6Target::begin_array); + METHOD_ADD(cgt, ARRAY_ENTRY_MTID, I6Target::array_entry); + METHOD_ADD(cgt, COMPILE_LITERAL_SYMBOL_MTID, I6Target::compile_literal_symbol); + METHOD_ADD(cgt, ARRAY_ENTRIES_MTID, I6Target::array_entries); + METHOD_ADD(cgt, END_ARRAY_MTID, I6Target::end_array); METHOD_ADD(cgt, OFFER_PRAGMA_MTID, I6Target::offer_pragma) METHOD_ADD(cgt, END_GENERATION_MTID, I6Target::end_generation); - METHOD_ADD(cgt, PSEUDO_OBJECT_MTID, I6Target::pseudo_object); - METHOD_ADD(cgt, NEW_ACTION_MTID, I6Target::new_action); + METHOD_ADD(cgt, PSEUDO_OBJECT_MTID, I6Target::pseudo_object); + METHOD_ADD(cgt, NEW_ACTION_MTID, I6Target::new_action); inform6_target = cgt; }@@ -1405,6 +1405,9 @@ or implement assembly-language operations like text_stream *opcode, int operand_count, inter_tree_node **operands, inter_tree_node *label, int label_sense, int void_context) { text_stream *OUT = CodeGen::current(gen); + if (Str::eq(opcode, I"@provides_gprop")) Invoke special provides_gprop9.1; + if (Str::eq(opcode, I"@read_gprop")) Invoke special read_gprop9.2; + if (Str::eq(opcode, I"@write_gprop")) Invoke special write_gprop9.3; WRITE("%S", opcode); for (int opc = 0; opc < operand_count; opc++) { WRITE(" "); @@ -1417,7 +1420,133 @@ or implement assembly-language operations like } if (void_context) WRITE(";\n"); } +§9.1. Invoke special provides_gprop9.1 = +
++ TEMPORARY_TEXT(K) + TEMPORARY_TEXT(obj) + TEMPORARY_TEXT(p) + TEMPORARY_TEXT(val) + CodeGen::select_temporary(gen, K); + Vanilla::node(gen, operands[0]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, obj); + Vanilla::node(gen, operands[1]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, p); + Vanilla::node(gen, operands[2]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, val); + Vanilla::node(gen, operands[3]); + CodeGen::deselect_temporary(gen); + + WRITE("if (%S == OBJECT_TY) {\n", K); + WRITE(" if ((%S) && (metaclass(%S) == Object)) {\n", obj, obj); + WRITE(" if ((%S-->0 == 2) || (%S provides %S-->1)) {\n", p, obj, p); + WRITE(" %S = 1;\n", val); + WRITE(" } else {\n"); + WRITE(" %S = 0;\n", val); + WRITE(" }\n"); + WRITE(" } else {\n"); + WRITE(" %S = 0;\n", val); + WRITE(" }\n"); + WRITE("} else {\n"); + WRITE(" if ((%S >= 1) && (%S <= value_ranges-->%S)) {\n", obj, obj, K); + WRITE(" holder = value_property_holders-->%S;\n", K); + WRITE(" if ((holder) && (holder provides %S-->1)) {\n", p); + WRITE(" %S = 1;\n", val); + WRITE(" } else {\n"); + WRITE(" %S = 0;\n", val); + WRITE(" }\n"); + WRITE(" } else {\n"); + WRITE(" %S = 0;\n", val); + WRITE(" }\n"); + WRITE("}\n"); + + DISCARD_TEXT(K) + DISCARD_TEXT(obj) + DISCARD_TEXT(p) + DISCARD_TEXT(val) + return; ++
§9.2. Invoke special read_gprop9.2 = +
+ ++ TEMPORARY_TEXT(K) + TEMPORARY_TEXT(obj) + TEMPORARY_TEXT(p) + CodeGen::select_temporary(gen, K); + Vanilla::node(gen, operands[0]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, obj); + Vanilla::node(gen, operands[1]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, p); + Vanilla::node(gen, operands[2]); + CodeGen::deselect_temporary(gen); + + WRITE("if (%S == OBJECT_TY) {\n", K); + WRITE(" if (%S-->0 == 2) {\n", p); + WRITE(" if (%S has %S-->1) rtrue; rfalse;\n", obj, p); + WRITE(" }\n"); + WRITE(" if (%S == door_to) return (%S-->1).%S();\n", p, obj, p); + WRITE(" return %S.(%S-->1);\n", obj, p); + WRITE("} else {\n"); + WRITE(" holder = value_property_holders-->%S;\n", K); + WRITE(" return (holder.(%S-->1))-->(%S+COL_HSIZE);\n", p, obj); + WRITE("}\n"); + + DISCARD_TEXT(K) + DISCARD_TEXT(obj) + DISCARD_TEXT(p) + return; ++
§9.3. Invoke special write_gprop9.3 = +
+ ++ TEMPORARY_TEXT(K) + TEMPORARY_TEXT(obj) + TEMPORARY_TEXT(p) + TEMPORARY_TEXT(val) + CodeGen::select_temporary(gen, K); + Vanilla::node(gen, operands[0]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, obj); + Vanilla::node(gen, operands[1]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, p); + Vanilla::node(gen, operands[2]); + CodeGen::deselect_temporary(gen); + CodeGen::select_temporary(gen, val); + Vanilla::node(gen, operands[3]); + CodeGen::deselect_temporary(gen); + + WRITE("if (%S == OBJECT_TY) {\n", K); + WRITE(" if (%S-->0 == 2) {\n", p); + WRITE(" if (%S) give %S %S-->1; else give %S ~(%S-->1);\n", val, obj, p, obj, p); + WRITE(" } else {\n"); + WRITE(" %S.(%S-->1) = %S;\n", obj, p, val); + WRITE(" }\n"); + WRITE("} else {\n"); + WRITE(" ((value_property_holders-->%S).(%S-->1))-->(%S+COL_HSIZE) = %S;\n", K, p, obj, val); + WRITE("}\n"); + + DISCARD_TEXT(K) + DISCARD_TEXT(obj) + DISCARD_TEXT(p) + DISCARD_TEXT(val) + return; ++
int I6Target::begin_array(code_generator *cgt, code_generation *gen, text_stream *array_name, inter_symbol *array_s, inter_tree_node *P, int format, segmentation_pos *saved) { if (saved) { int choice = early_matter_I7CGS; @@ -1466,7 +1595,7 @@ or implement assembly-language operations like else if (aliased == verb_directive_creature_symbol) WRITE("creature"); else if (aliased == verb_directive_topic_symbol) WRITE("topic"); else if (aliased == verb_directive_multiexcept_symbol) WRITE("multiexcept"); - else I6Target::compile_literal_symbol(cgt, gen, aliased); + else I6Target::compile_literal_symbol(cgt, gen, aliased); } } else { CodeGen::pair(gen, P, val1, val2); @@ -1496,7 +1625,7 @@ or implement assembly-language operations like Generators::mangle(gen, OUT, S); }-
§10. Alternatively, we can just specify how many entries there will be: they will +
§11. Alternatively, we can just specify how many entries there will be: they will then be initialised to 0.
diff --git a/docs/runtime-module/5-prp.html b/docs/runtime-module/5-prp.html index 7b9f1bbce..07a025326 100644 --- a/docs/runtime-module/5-prp.html +++ b/docs/runtime-module/5-prp.html @@ -126,7 +126,7 @@ package already supplied: return prn->compilation_data.prop_package; } -inter_name *RTProperties::iname(property *prn) { +inter_name *RTProperties::iname(property *prn) { if (prn == NULL) internal_error("tried to find iname for null property"); if ((Properties::is_either_or(prn)) && (prn->compilation_data.store_in_negation)) return RTProperties::iname(EitherOrProperties::get_negation(prn)); @@ -188,7 +188,7 @@ kit, we'll have to use that one.-int RTProperties::stored_in_negation(property *prn) { +int RTProperties::stored_in_negation(property *prn) { if ((prn == NULL) || (prn->either_or_data == NULL)) internal_error("non-EO property"); return prn->compilation_data.store_in_negation; @@ -367,89 +367,46 @@ and its analogue for writing, return TRUE; }-
§10. Either-or properties are trickier, though only because they use a different -pair of functions at runtime for EO properties of objects than for EO properties -of anything else: +
§10. Either-or properties work analogously, though note that on reading, GProperty +is called slightly differently so that objects are allowed access to read (though +not write) either/or properties which they do not possess. The result is always +false, but run-time errors do not occur. (This all goes back to the way +attributes were handled on the Z-machine VM, but is an assumption made by some +of the kit code inherited from early days of Inform, and does no actual harm.)
void RTProperties::write_either_or_schemas(adjective_meaning *am, property *prn, int T) { kind *K = AdjectiveMeaningDomains::get_kind(am); - if (Kinds::Behaviour::is_object(K)) - Set the schemata for an either/or property adjective with objects as domain10.1 - else - Set the schemata for an either/or property adjective with some other domain10.2; + if (RTProperties::stored_in_negation(prn)) { + property *neg = EitherOrProperties::get_negation(prn); + + i6_schema *sch = AdjectiveMeanings::make_schema(am, TEST_ATOM_TASK); + Calculus::Schemas::modify(sch, "GProperty(%k, *1, %n, 1) == false", K, + RTProperties::iname(neg)); + + sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_TRUE_TASK); + Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n, 0)", K, + RTProperties::iname(neg)); + + sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_FALSE_TASK); + Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n, 1)", K, + RTProperties::iname(neg)); + } else { + i6_schema *sch = AdjectiveMeanings::make_schema(am, TEST_ATOM_TASK); + Calculus::Schemas::modify(sch, "GProperty(%k, *1, %n, 1)", K, + RTProperties::iname(prn)); + + sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_TRUE_TASK); + Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n, 1)", K, + RTProperties::iname(prn)); + + sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_FALSE_TASK); + Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n, 0)", K, + RTProperties::iname(prn)); + } }-
§10.1. The "objects" domain is not really very different, but it's the one used -overwhelmingly most often, so we will call the relevant routines directly rather -than accessing them via the unifying routines GProperty and WriteGProperty — -which would work just as well, but more slowly. -
- -Set the schemata for an either/or property adjective with objects as domain10.1 = -
- -- if (RTProperties::stored_in_negation(prn)) { - property *neg = EitherOrProperties::get_negation(prn); - inter_name *identifier = RTProperties::iname(neg); - - i6_schema *sch = AdjectiveMeanings::make_schema(am, TEST_ATOM_TASK); - Calculus::Schemas::modify(sch, "GProperty(OBJECT_TY, *1, %n, true) == false", identifier); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_TRUE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(OBJECT_TY, *1, %n, 0)", identifier); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_FALSE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(OBJECT_TY, *1, %n, 1)", identifier); - } else { - inter_name *identifier = RTProperties::iname(prn); - - i6_schema *sch = AdjectiveMeanings::make_schema(am, TEST_ATOM_TASK); - Calculus::Schemas::modify(sch, "GProperty(OBJECT_TY, *1, %n, true)", identifier); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_TRUE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(OBJECT_TY, *1, %n, 1)", identifier); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_FALSE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(OBJECT_TY, *1, %n, 0)", identifier); - } --
§10.2. Set the schemata for an either/or property adjective with some other domain10.2 = -
- -- if (RTProperties::stored_in_negation(prn)) { - property *neg = EitherOrProperties::get_negation(prn); - - i6_schema *sch = AdjectiveMeanings::make_schema(am, TEST_ATOM_TASK); - Calculus::Schemas::modify(sch, "GProperty(%k, *1, %n) == false", K, - RTProperties::iname(neg)); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_TRUE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n)", K, - RTProperties::iname(neg)); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_FALSE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n, true)", K, - RTProperties::iname(neg)); - } else { - i6_schema *sch = AdjectiveMeanings::make_schema(am, TEST_ATOM_TASK); - Calculus::Schemas::modify(sch, "GProperty(%k, *1, %n)", K, - RTProperties::iname(prn)); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_TRUE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n, true)", K, - RTProperties::iname(prn)); - - sch = AdjectiveMeanings::make_schema(am, NOW_ATOM_FALSE_TASK); - Calculus::Schemas::modify(sch, "WriteGProperty(%k, *1, %n)", K, - RTProperties::iname(prn)); - } --
§11. And finally, provision of a property can be tested at runtime with the following schemas:
@@ -468,7 +425,7 @@ following schemas: } else if (Kinds::Behaviour::is_object(K)) { kind *PK = Cinders::kind_of_term(asch->pt1); if (Kinds::get_construct(PK) == CON_property) { - Calculus::Schemas::modify(asch->schema, "WhetherProvides(%k, *1, *2)", K); + Calculus::Schemas::modify(asch->schema, "ProvidesProperty(%k, *1, *2)", K); return TRUE; } } @@ -484,7 +441,7 @@ of object the left operand is, we can only test property provision at run-time:- Calculus::Schemas::modify(asch->schema, "WhetherProvides(%k, *1, *2)", K); + Calculus::Schemas::modify(asch->schema, "ProvidesProperty(%k, *1, *2)", K);
§11.2. For all other kinds, type-checking is strong enough that we can prove the
diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt
index 5d558d79e..1d785b107 100644
--- a/inform7/Figures/memory-diagnostics.txt
+++ b/inform7/Figures/memory-diagnostics.txt
@@ -1,6 +1,6 @@
-Total memory consumption was 394323K = 385 MB
+Total memory consumption was 394317K = 385 MB
-60.6% was used for 2004452 objects, in 372321 frames in 299 x 800K = 239200K = 233 MB:
+60.6% was used for 2004468 objects, in 372337 frames in 299 x 800K = 239200K = 233 MB:
10.3% inter_tree_node_array 58 x 8192 = 475136 objects, 41813824 bytes
7.2% text_stream_array 5187 x 100 = 518700 objects, 29213184 bytes
@@ -13,7 +13,7 @@ Total memory consumption was 394323K = 385 MB
0.8% inter_name_array 69 x 1000 = 69000 objects, 3314208 bytes
0.6% kind_array 68 x 1000 = 68000 objects, 2722176 bytes
0.5% inter_name_generator_array 53 x 1000 = 53000 objects, 2121696 bytes
- 0.5% inter_schema_token 14185 objects, 2042640 bytes
+ 0.5% inter_schema_token 14197 objects, 2044368 bytes
0.4% inter_package 26565 objects, 1912680 bytes
0.4% package_request 21137 objects, 1860056 bytes
0.4% vocabulary_entry_array 161 x 100 = 16100 objects, 1808352 bytes
@@ -30,7 +30,7 @@ Total memory consumption was 394323K = 385 MB
0.2% ptoken 8382 objects, 871728 bytes
0.2% grammatical_usage 3611 objects, 866640 bytes
0.2% individual_form 2561 objects, 860496 bytes
- 0.2% inter_schema_node 8905 objects, 854880 bytes
+ 0.2% inter_schema_node 8909 objects, 855264 bytes
0.1% unary_predicate_array 16 x 1000 = 16000 objects, 640512 bytes
0.1% local_variable_array 47 x 100 = 4700 objects, 452704 bytes
---- scan_directory 94 objects, 388032 bytes
@@ -238,7 +238,7 @@ Total memory consumption was 394323K = 385 MB
39.3% was used for memory not allocated for objects:
- 20.5% text stream storage 82882584 bytes in 536688 claims
+ 20.5% text stream storage 82876796 bytes in 536689 claims
4.5% dictionary storage 18271744 bytes in 33265 claims
---- sorting 736 bytes in 3 claims
1.7% source text 7200000 bytes in 3 claims
@@ -246,8 +246,8 @@ Total memory consumption was 394323K = 385 MB
---- documentation fragments 262144 bytes in 1 claim
---- linguistic stock array 81920 bytes in 2 claims
---- small word set array 105600 bytes in 22 claims
- 1.0% inter symbols storage 4175072 bytes in 27677 claims
- 4.1% inter bytecode storage 16802732 bytes in 14 claims
+ 1.0% inter symbols storage 4174576 bytes in 27676 claims
+ 4.1% inter bytecode storage 16802744 bytes in 14 claims
4.0% inter links storage 16174208 bytes in 266 claims
---- inter tree location list storage 191232 bytes in 32 claims
0.4% instance-of-kind counting 1695204 bytes in 1 claim
@@ -256,5 +256,5 @@ Total memory consumption was 394323K = 385 MB
---- code generation workspace for objects 4128 bytes in 4 claims
---- emitter array storage 161792 bytes in 2062 claims
-18.4% was overhead - 74415928 bytes = 72671K = 70 MB
+18.4% was overhead - 74413816 bytes = 72669K = 70 MB
diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt
index 2d1f7c083..9e28d97e5 100644
--- a/inform7/Figures/timings-diagnostics.txt
+++ b/inform7/Figures/timings-diagnostics.txt
@@ -1,11 +1,11 @@
100.0% in inform7 run
- 55.0% in compilation to Inter
- 39.5% in //Sequence::undertake_queued_tasks//
+ 55.1% in compilation to Inter
+ 39.6% in //Sequence::undertake_queued_tasks//
3.5% in //MajorNodes::pre_pass//
- 2.6% in //MajorNodes::pass_1//
- 2.1% in //RTPhrasebook::compile_entries//
- 1.4% in //ImperativeDefinitions::assess_all//
- 1.1% in //RTKindConstructors::compile//
+ 2.5% in //MajorNodes::pass_1//
+ 2.0% in //RTPhrasebook::compile_entries//
+ 1.3% in //ImperativeDefinitions::assess_all//
+ 1.2% in //RTKindConstructors::compile//
0.4% in //ImperativeDefinitions::compile_first_block//
0.4% in //MajorNodes::pass_2//
0.4% in //Sequence::undertake_queued_tasks//
@@ -16,22 +16,22 @@
0.1% in //RTKindConstructors::compile_permissions//
0.1% in //Task::make_built_in_kind_constructors//
0.1% in //World::stages_II_and_III//
- 1.6% not specifically accounted for
- 43.1% in running Inter pipeline
- 12.4% in step preparation
+ 1.8% not specifically accounted for
+ 42.9% in running Inter pipeline
+ 12.5% in step preparation
9.6% in inter step 7/16: consolidate-text
- 7.8% in inter step 2/16: link
- 6.8% in inter step 16/16: generate inform6 -> auto.inf
+ 8.0% in inter step 2/16: link
+ 6.5% in inter step 16/16: generate inform6 -> auto.inf
1.5% in inter step 11/16: make-identifiers-unique
0.4% in inter step 12/16: reconcile-verbs
+ 0.2% in inter step 10/16: detect-indirect-calls
0.2% in inter step 14/16: eliminate-redundant-operations
0.2% in inter step 6/16: assimilate
0.2% in inter step 8/16: resolve-external-symbols
0.2% in inter step 9/16: inspect-plugs
- 0.1% in inter step 10/16: detect-indirect-calls
0.1% in inter step 13/16: eliminate-redundant-labels
0.1% in inter step 4/16: parse-linked-matter
0.1% in inter step 5/16: resolve-conditional-compilation
- 2.7% not specifically accounted for
- 1.7% in supervisor
- 0.2% not specifically accounted for
+ 2.4% not specifically accounted for
+ 1.6% in supervisor
+ 0.3% not specifically accounted for
diff --git a/inform7/Internal/Inter/BasicInformKit/Sections/RTP.i6t b/inform7/Internal/Inter/BasicInformKit/Sections/RTP.i6t
index cc3006401..7f62a107c 100644
--- a/inform7/Internal/Inter/BasicInformKit/Sections/RTP.i6t
+++ b/inform7/Internal/Inter/BasicInformKit/Sections/RTP.i6t
@@ -260,41 +260,40 @@ have the property in question at an I6 level -- having permission to have
it doesn't mean it actually does have.
=
-[ WhetherProvides K obj q issue_rtp a l holder;
- if (K ~= OBJECT_TY) {
- if ((obj < 1) || (obj > value_ranges-->K)) {
- if (issue_rtp) RunTimeProblem(RTP_BADVALUEPROPERTY);
- rfalse;
- } else {
- holder = value_property_holders-->K;
- if ((holder) && (holder provides q)) rtrue;
+[ ProvidesProperty K obj q issue_rtp a l holder;
+ if (K == OBJECT_TY) {
+ if (ScanPropertyMetadata(obj, q, 4)) jump PermissionFound;
+ if (obj provides KD_Count) {
+ l = obj.KD_Count;
+ while (l > 0) {
+ a = l*2;
+ if (ScanPropertyMetadata(KindHierarchy-->a, q, 4)) jump PermissionFound;
+ l = KindHierarchy-->(a+1);
+ }
}
- }
- if (obj == 0) {
- if (issue_rtp) RunTimeProblem(RTP_PROPOFNOTHING, 0, q);
+ if (ScanPropertyMetadata(K0_kind, q, 4)) jump PermissionFound;
+ if (issue_rtp) RunTimeProblem(RTP_UNPROVIDED, obj, q);
rfalse;
}
- if (metaclass(obj) ~= Object) rfalse;
- if (q<0) q = ~q;
-
- if (ScanPropertyMetadata(obj, q, 4)) jump PermissionFound;
- if (obj provides KD_Count) {
- l = obj.KD_Count;
- while (l > 0) {
- a = l*2;
- if (ScanPropertyMetadata(KindHierarchy-->a, q, 4)) jump PermissionFound;
- l = KindHierarchy-->(a+1);
- }
- }
- if (ScanPropertyMetadata(K0_kind, q, 4)) jump PermissionFound;
- if (issue_rtp) RunTimeProblem(RTP_UNPROVIDED, obj, q);
- rfalse;
.PermissionFound;
- if (q-->2) rtrue;
- if (obj provides q) rtrue;
- if (issue_rtp) RunTimeProblem(RTP_UNSET, obj, q);
- rfalse;
+
+ @provides_gprop K obj q a;
+ if (a) rtrue;
+! if (K ~= OBJECT_TY) {
+! if ((obj >= 1) && (obj <= value_ranges-->K)) {
+! holder = value_property_holders-->K;
+! if ((holder) && (holder provides q)) rtrue;
+! }
+! } else {
+! if ((obj) && (metaclass(obj) == Object)) {
+! if (q-->0 == 2) rtrue;
+! if (obj provides q) rtrue;
+! }
+! }
+
+ if (issue_rtp) RunTimeProblem(RTP_UNSET, obj, q);
+ rfalse;
];
[ PrintPropertyName p textual;
@@ -331,18 +330,20 @@ this enables it to be an I6 routine returning the other side of the door from
the one which the player is on.
=
-[ GProperty K V pr err holder;
- if (WhetherProvides(K, V, pr, 1-err)) {
- if (K == OBJECT_TY) {
- if (pr-->0 == 2) {
- if (V has pr) rtrue; rfalse;
- }
- if (pr == door_to) return V.pr();
- return V.pr;
- } else {
- holder = value_property_holders-->K;
- return (holder.pr)-->(V+COL_HSIZE);
- }
+[ GProperty K V pr err holder val;
+ if (ProvidesProperty(K, V, pr, 1-err)) {
+ @read_gprop K V pr val;
+ return val;
+! if (K == OBJECT_TY) {
+! if (pr-->0 == 2) {
+! if (V has pr) rtrue; rfalse;
+! }
+! if (pr == door_to) return V.pr();
+! return V.pr;
+! } else {
+! holder = value_property_holders-->K;
+! return (holder.pr)-->(V+COL_HSIZE);
+! }
}
return 0;
];
@@ -354,17 +355,18 @@ converted from an rvalue to an lvalue.
=
[ WriteGProperty K V pr val holder;
- if (WhetherProvides(K, V, pr, true)) {
- if (K == OBJECT_TY) {
- if (pr-->0 == 2) {
- if (val) give V pr; else give V ~pr;
- } else {
- V.pr = val;
- }
- } else {
- holder = value_property_holders-->K;
- (holder.pr)-->(V+COL_HSIZE) = val;
- }
+ if (ProvidesProperty(K, V, pr, true)) {
+ @write_gprop K V pr val;
+! if (K == OBJECT_TY) {
+! if (pr-->0 == 2) {
+! if (val) give V pr; else give V ~pr;
+! } else {
+! V.pr = val;
+! }
+! } else {
+! holder = value_property_holders-->K;
+! (holder.pr)-->(V+COL_HSIZE) = val;
+! }
}
];
diff --git a/inform7/Tests/Test Makes/Eg4-C/textual.txt b/inform7/Tests/Test Makes/Eg4-C/textual.txt
index 087ecd41f..8d1ecdf79 100644
--- a/inform7/Tests/Test Makes/Eg4-C/textual.txt
+++ b/inform7/Tests/Test Makes/Eg4-C/textual.txt
@@ -6545,9 +6545,9 @@ package main _plain
symbol public misc #dictionary_table
symbol public misc #grammar_table
symbol public misc __assembly_sp `sp`
+ symbol public misc KindHierarchy
symbol public misc value_ranges
symbol public misc value_property_holders
- symbol public misc KindHierarchy
constant String K_unchecked = 0 __veneer=1
constant Routine K_unchecked = 0 __veneer=1
constant self K_unchecked = 0 __veneer=1
@@ -6558,9 +6558,9 @@ package main _plain
constant #dictionary_table K_unchecked = 0 __veneer=1
constant #grammar_table K_unchecked = 0 __veneer=1
constant __assembly_sp K_unchecked = 0 __veneer=1
+ constant KindHierarchy K_unchecked = 0 __veneer=1
constant value_ranges K_unchecked = 0 __veneer=1
constant value_property_holders K_unchecked = 0 __veneer=1
- constant KindHierarchy K_unchecked = 0 __veneer=1
package basic_inform_by_graham_nelson _module
symbol private misc ^category `^category_U1`
symbol external misc K_typeless_int --> /main/generic/kinds/K_typeless_int
@@ -39392,11 +39392,9 @@ package main _plain
symbol socket misc RunTimeError --> /main/connectors/RunTimeError
symbol socket misc ArgumentTypeFailed --> /main/connectors/ArgumentTypeFailed
symbol socket misc CheckKindReturned --> /main/connectors/CheckKindReturned
- symbol socket misc WhetherProvides --> /main/connectors/WhetherProvides
+ symbol socket misc ProvidesProperty --> /main/connectors/ProvidesProperty
symbol socket misc PrintPropertyName --> /main/connectors/PrintPropertyName
symbol socket misc ScanPropertyMetadata --> /main/connectors/ScanPropertyMetadata
- symbol socket misc GetEitherOrProperty --> /main/connectors/GetEitherOrProperty
- symbol socket misc SetEitherOrProperty --> /main/connectors/SetEitherOrProperty
symbol socket misc GProperty --> /main/connectors/GProperty
symbol socket misc WriteGProperty --> /main/connectors/WriteGProperty
symbol socket misc PROPERTY_TY_Say --> /main/connectors/PROPERTY_TY_Say
@@ -97061,10 +97059,10 @@ package main _plain
inv !return
val K_unchecked V
constant CheckKindReturned K_unchecked_function = CheckKindReturned_B __assimilated=1
- package WhetherProvides_fn _function
- symbol public misc WhetherProvides
+ package ProvidesProperty_fn _function
+ symbol public misc ProvidesProperty
symbol external misc K_unchecked_function --> /main/generic/kinds/K_unchecked_function
- package WhetherProvides_B _code
+ package ProvidesProperty_B _code
symbol private misc K
symbol external misc K_unchecked --> /main/generic/kinds/K_unchecked
symbol private misc obj
@@ -97074,19 +97072,17 @@ package main _plain
symbol private misc l
symbol private misc holder
symbol external misc plug_00140 --> /main/generic/kinds/kind1/OBJECT_TY
- symbol external misc value_ranges --> /main/veneer/value_ranges
- symbol external misc RunTimeProblem --> /main/BasicInformKit/functions/RunTimeProblem_fn/RunTimeProblem
- symbol external misc RTP_BADVALUEPROPERTY --> /main/BasicInformKit/constants/RTP_BADVALUEPROPERTY_con/RTP_BADVALUEPROPERTY
- symbol external misc value_property_holders --> /main/veneer/value_property_holders
- symbol external misc RTP_PROPOFNOTHING --> /main/BasicInformKit/constants/RTP_PROPOFNOTHING_con/RTP_PROPOFNOTHING
- symbol external misc metaclass --> /main/veneer/metaclass
- symbol external misc Object --> /main/veneer/Object
symbol external misc ScanPropertyMetadata --> /main/BasicInformKit/functions/ScanPropertyMetadata_fn/ScanPropertyMetadata
symbol private label .PermissionFound
symbol external misc KD_Count --> /main/BasicInformKit/properties/KD_Count_prop/KD_Count
symbol external misc KindHierarchy --> /main/veneer/KindHierarchy
symbol external misc plug_00165 --> /main/generic/kinds/kind1/K_object
+ symbol external misc RunTimeProblem --> /main/BasicInformKit/functions/RunTimeProblem_fn/RunTimeProblem
symbol external misc RTP_UNPROVIDED --> /main/BasicInformKit/constants/RTP_UNPROVIDED_con/RTP_UNPROVIDED
+ symbol external misc value_ranges --> /main/veneer/value_ranges
+ symbol external misc value_property_holders --> /main/veneer/value_property_holders
+ symbol external misc metaclass --> /main/veneer/metaclass
+ symbol external misc Object --> /main/veneer/Object
symbol external misc RTP_UNSET --> /main/BasicInformKit/constants/RTP_UNSET_con/RTP_UNSET
local K K_unchecked
local obj K_unchecked
@@ -97097,26 +97093,91 @@ package main _plain
local holder K_unchecked
code
inv !if
+ inv !eq
+ val K_unchecked K
+ val K_unchecked OBJECT_TY
+ code
+ inv !if
+ inv ScanPropertyMetadata
+ val K_unchecked obj
+ val K_unchecked q
+ val K_unchecked 4
+ code
+ inv !jump
+ lab .PermissionFound
+ inv !if
+ inv !provides
+ val K_unchecked obj
+ val K_unchecked KD_Count
+ code
+ inv !store
+ reference
+ val K_unchecked l
+ inv !propertyvalue
+ val K_unchecked obj
+ val K_unchecked KD_Count
+ inv !while
+ inv !gt
+ val K_unchecked l
+ val K_unchecked 0
+ code
+ inv !store
+ reference
+ val K_unchecked a
+ inv !times
+ val K_unchecked l
+ val K_unchecked 2
+ inv !if
+ inv ScanPropertyMetadata
+ inv !lookup
+ val K_unchecked KindHierarchy
+ val K_unchecked a
+ val K_unchecked q
+ val K_unchecked 4
+ code
+ inv !jump
+ lab .PermissionFound
+ inv !store
+ reference
+ val K_unchecked l
+ inv !lookup
+ val K_unchecked KindHierarchy
+ inv !plus
+ val K_unchecked a
+ val K_unchecked 1
+ inv !if
+ inv ScanPropertyMetadata
+ val K_unchecked K_object
+ val K_unchecked q
+ val K_unchecked 4
+ code
+ inv !jump
+ lab .PermissionFound
+ inv !if
+ val K_unchecked issue_rtp
+ code
+ inv RunTimeProblem
+ val K_unchecked RTP_UNPROVIDED
+ val K_unchecked obj
+ val K_unchecked q
+ inv !return
+ val K_unchecked 0
+ .PermissionFound
+ inv !ifelse
inv !ne
val K_unchecked K
val K_unchecked OBJECT_TY
code
- inv !ifelse
- inv !or
- inv !lt
+ inv !if
+ inv !and
+ inv !ge
val K_unchecked obj
val K_unchecked 1
- inv !gt
+ inv !le
val K_unchecked obj
inv !lookup
val K_unchecked value_ranges
val K_unchecked K
- code
- inv !if
- val K_unchecked issue_rtp
- code
- inv RunTimeProblem
- val K_unchecked RTP_BADVALUEPROPERTY
code
inv !store
reference
@@ -97133,120 +97194,31 @@ package main _plain
code
inv !return
val K_unchecked 1
- inv !return
- val K_unchecked 0
- inv !if
- inv !eq
- val K_unchecked obj
- val K_unchecked 0
code
inv !if
- val K_unchecked issue_rtp
- code
- inv RunTimeProblem
- val K_unchecked RTP_PROPOFNOTHING
- val K_unchecked 0
- val K_unchecked q
- inv !return
- val K_unchecked 0
- inv !if
- inv !ne
- inv metaclass
- val K_unchecked obj
- val K_unchecked Object
- code
- inv !return
- val K_unchecked 0
- inv !if
- inv !lt
- val K_unchecked q
- val K_unchecked 0
- code
- inv !store
- reference
- val K_unchecked q
- inv !bitwisenot
- val K_unchecked q
- inv !if
- inv ScanPropertyMetadata
- val K_unchecked obj
- val K_unchecked q
- val K_unchecked 4
- code
- inv !jump
- lab .PermissionFound
- inv !if
- inv !provides
- val K_unchecked obj
- val K_unchecked KD_Count
- code
- inv !store
- reference
- val K_unchecked l
- inv !propertyvalue
+ inv !and
val K_unchecked obj
- val K_unchecked KD_Count
- inv !while
- inv !gt
- val K_unchecked l
- val K_unchecked 0
+ inv !eq
+ inv metaclass
+ val K_unchecked obj
+ val K_unchecked Object
code
- inv !store
- reference
- val K_unchecked a
- inv !times
- val K_unchecked l
- val K_unchecked 2
inv !if
- inv ScanPropertyMetadata
+ inv !eq
inv !lookup
- val K_unchecked KindHierarchy
- val K_unchecked a
- val K_unchecked q
- val K_unchecked 4
+ val K_unchecked q
+ val K_unchecked 0
+ val K_unchecked 2
code
- inv !jump
- lab .PermissionFound
- inv !store
- reference
- val K_unchecked l
- inv !lookup
- val K_unchecked KindHierarchy
- inv !plus
- val K_unchecked a
+ inv !return
+ val K_unchecked 1
+ inv !if
+ inv !provides
+ val K_unchecked obj
+ val K_unchecked q
+ code
+ inv !return
val K_unchecked 1
- inv !if
- inv ScanPropertyMetadata
- val K_unchecked K_object
- val K_unchecked q
- val K_unchecked 4
- code
- inv !jump
- lab .PermissionFound
- inv !if
- val K_unchecked issue_rtp
- code
- inv RunTimeProblem
- val K_unchecked RTP_UNPROVIDED
- val K_unchecked obj
- val K_unchecked q
- inv !return
- val K_unchecked 0
- .PermissionFound
- inv !if
- inv !lookup
- val K_unchecked q
- val K_unchecked 2
- code
- inv !return
- val K_unchecked 1
- inv !if
- inv !provides
- val K_unchecked obj
- val K_unchecked q
- code
- inv !return
- val K_unchecked 1
inv !if
val K_unchecked issue_rtp
code
@@ -97256,7 +97228,7 @@ package main _plain
val K_unchecked q
inv !return
val K_unchecked 0
- constant WhetherProvides K_unchecked_function = WhetherProvides_B __assimilated=1
+ constant ProvidesProperty K_unchecked_function = ProvidesProperty_B __assimilated=1
package PrintPropertyName_fn _function
symbol public misc PrintPropertyName
symbol external misc K_unchecked_function --> /main/generic/kinds/K_unchecked_function
@@ -97326,56 +97298,6 @@ package main _plain
inv !return
val K_unchecked 0
constant ScanPropertyMetadata K_unchecked_function = ScanPropertyMetadata_B __assimilated=1
- package GetEitherOrProperty_fn _function
- symbol public misc GetEitherOrProperty
- symbol external misc K_unchecked_function --> /main/generic/kinds/K_unchecked_function
- package GetEitherOrProperty_B _code
- symbol private misc o
- symbol external misc K_unchecked --> /main/generic/kinds/K_unchecked
- symbol private misc p
- symbol external misc GProperty --> /main/BasicInformKit/functions/GProperty_fn/GProperty
- symbol external misc plug_00140 --> /main/generic/kinds/kind1/OBJECT_TY
- local o K_unchecked
- local p K_unchecked
- code
- inv !return
- inv GProperty
- val K_unchecked OBJECT_TY
- val K_unchecked o
- val K_unchecked p
- val K_unchecked 1
- constant GetEitherOrProperty K_unchecked_function = GetEitherOrProperty_B __assimilated=1
- package SetEitherOrProperty_fn _function
- symbol public misc SetEitherOrProperty
- symbol external misc K_unchecked_function --> /main/generic/kinds/K_unchecked_function
- package SetEitherOrProperty_B _code
- symbol private misc o
- symbol external misc K_unchecked --> /main/generic/kinds/K_unchecked
- symbol private misc p
- symbol private misc negate
- symbol private misc adj
- symbol external misc WriteGProperty --> /main/BasicInformKit/functions/WriteGProperty_fn/WriteGProperty
- symbol external misc plug_00140 --> /main/generic/kinds/kind1/OBJECT_TY
- local o K_unchecked
- local p K_unchecked
- local negate K_unchecked
- local adj K_unchecked
- code
- inv !ifelse
- val K_unchecked negate
- code
- inv WriteGProperty
- val K_unchecked OBJECT_TY
- val K_unchecked o
- val K_unchecked p
- val K_unchecked 0
- code
- inv WriteGProperty
- val K_unchecked OBJECT_TY
- val K_unchecked o
- val K_unchecked p
- val K_unchecked 1
- constant SetEitherOrProperty K_unchecked_function = SetEitherOrProperty_B __assimilated=1
package GProperty_fn _function
symbol public misc GProperty
symbol external misc K_unchecked_function --> /main/generic/kinds/K_unchecked_function
@@ -97386,7 +97308,7 @@ package main _plain
symbol private misc pr
symbol private misc err
symbol private misc holder
- symbol external misc WhetherProvides --> /main/BasicInformKit/functions/WhetherProvides_fn/WhetherProvides
+ symbol external misc ProvidesProperty --> /main/BasicInformKit/functions/ProvidesProperty_fn/ProvidesProperty
symbol external misc plug_00140 --> /main/generic/kinds/kind1/OBJECT_TY
symbol external misc door_to --> /main/BasicInformKit/properties/door_to_prop/door_to
symbol external misc value_property_holders --> /main/veneer/value_property_holders
@@ -97398,7 +97320,7 @@ package main _plain
local holder K_unchecked
code
inv !if
- inv WhetherProvides
+ inv ProvidesProperty
val K_unchecked K
val K_unchecked V
val K_unchecked pr
@@ -97468,7 +97390,7 @@ package main _plain
symbol private misc pr
symbol private misc val
symbol private misc holder
- symbol external misc WhetherProvides --> /main/BasicInformKit/functions/WhetherProvides_fn/WhetherProvides
+ symbol external misc ProvidesProperty --> /main/BasicInformKit/functions/ProvidesProperty_fn/ProvidesProperty
symbol external misc plug_00140 --> /main/generic/kinds/kind1/OBJECT_TY
symbol external misc value_property_holders --> /main/veneer/value_property_holders
symbol external misc COL_HSIZE --> /main/BasicInformKit/constants/COL_HSIZE_con/COL_HSIZE
@@ -97479,7 +97401,7 @@ package main _plain
local holder K_unchecked
code
inv !if
- inv WhetherProvides
+ inv ProvidesProperty
val K_unchecked K
val K_unchecked V
val K_unchecked pr
diff --git a/inform7/runtime-module/Chapter 5/Properties.w b/inform7/runtime-module/Chapter 5/Properties.w
index 6f4b2035c..757cee925 100644
--- a/inform7/runtime-module/Chapter 5/Properties.w
+++ b/inform7/runtime-module/Chapter 5/Properties.w
@@ -268,79 +268,45 @@ int RTProperties::set_property_value_schema(annotated_i6_schema *asch, property
return TRUE;
}
-@ Either-or properties are trickier, though only because they use a different
-pair of functions at runtime for EO properties of objects than for EO properties
-of anything else:
+@ Either-or properties work analogously, though note that on reading, |GProperty|
+is called slightly differently so that objects are allowed access to read (though
+not write) either/or properties which they do not possess. The result is always
+|false|, but run-time errors do not occur. (This all goes back to the way
+attributes were handled on the Z-machine VM, but is an assumption made by some
+of the kit code inherited from early days of Inform, and does no actual harm.)
=
void RTProperties::write_either_or_schemas(adjective_meaning *am, property *prn, int T) {
kind *K = AdjectiveMeaningDomains::get_kind(am);
- if (Kinds::Behaviour::is_object(K))
- @