From b0069b92ce4d441cfdeecf61d0d9f96a5f10bda4 Mon Sep 17 00:00:00 2001
From: Graham Nelson
The door_to property, relevant only for doors, is called rather than read: -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 val; if (ProvidesProperty(K, V, pr, 1-err)) { diff --git a/docs/final-module/2-cg.html b/docs/final-module/2-cg.html index 5723b5df7..fa2724d92 100644 --- a/docs/final-module/2-cg.html +++ b/docs/final-module/2-cg.html @@ -296,7 +296,7 @@ everything else. define PRINTING_LTM 2
-void CodeGen::lt_mode(code_generation *gen, int m) { +void CodeGen::lt_mode(code_generation *gen, int m) { gen->literal_text_mode = m; }@@ -414,7 +414,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); } @@ -431,7 +431,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; } @@ -457,7 +457,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; diff --git a/docs/final-module/2-vnl.html b/docs/final-module/2-vnl.html index 29dd90f4d..a1a5be0fb 100644 --- a/docs/final-module/2-vnl.html +++ b/docs/final-module/2-vnl.html @@ -197,7 +197,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/2-vo.html b/docs/final-module/2-vo.html index 175665112..175f984d9 100644 --- a/docs/final-module/2-vo.html +++ b/docs/final-module/2-vo.html @@ -398,7 +398,7 @@ not as wasteful as it looks.)-text_stream *VanillaObjects::inner_property_name(code_generation *gen, inter_symbol *prop_name) { +text_stream *VanillaObjects::inner_property_name(code_generation *gen, inter_symbol *prop_name) { text_stream *inner_name = I"<nameless>"; int N = Inter::Symbols::read_annotation(prop_name, INNER_PROPERTY_NAME_IANN); if (N > 0) inner_name = Inter::Warehouse::get_text(InterTree::warehouse(gen->from), (inter_ti) N); diff --git a/docs/final-module/4-fi6.html b/docs/final-module/4-fi6.html index 3883b3978..08dca2d06 100644 --- a/docs/final-module/4-fi6.html +++ b/docs/final-module/4-fi6.html @@ -316,7 +316,7 @@ tweaked. These go at the top of the source code and typically look like this:int I6Target::end_generation(code_generator *cgt, code_generation *gen) { I6TargetObjects::end_generation(cgt, gen); - I6TargetCode::end_generation(cgt, gen); + I6TargetCode::end_generation(cgt, gen); return FALSE; }diff --git a/docs/final-module/4-i6c2.html b/docs/final-module/4-i6c2.html index e02961cb5..e83da01f0 100644 --- a/docs/final-module/4-i6c2.html +++ b/docs/final-module/4-i6c2.html @@ -73,7 +73,7 @@ function togglePopup(material_id) {
To generate I6 routines of imperative code.
-§5. Assembly language. In general, we make no attempt to police the supposedly valid assembly language -given to us here. Glulx has one set, Z another. +given to us here. Glulx has one set, Z another. Any assembly language in the Inter +tree results from kit material; and if the author of such a kit tries to use an +invalid opcode, then the result won't compile under I6, but none of that is our +business here.
The @aread opcode is a valid Z-machine opcode, but owing to the way I6 handles
@@ -336,7 +339,7 @@ As a dodge, we use the Inform 6 statement if (void_context) WRITE(";\n");
}
-
+
§6.2. Storing or otherwise changing values6.2 =
- §6.3. Property value access6.3 =
- §6.5. Control structures6.5 =
- §6.6. Indirect function or method calls6.6 =
- §6.8. The VM object tree6.8 =
- §6.9. Random number generator6.9 =
- §6.2.1. Perform a store6.2.1 =
- §6.2.1.1. Handle the ref using the incomplete-function mode6.2.1.1 =
- §6.2.1.2. Handle the ref with code working either as lvalue or rvalue6.2.1.2 =
- §6.3.1. Write attribute give6.3.1 =
- §6.3.2. Write attribute take6.3.2 =
- §6.3.3. Write property value6.3.3 =
- §6.3.4. Evaluate property value6.3.4 =
- §6.5.3. Generate primitive for return6.5.3 =
- §6.1.1. Here we need some gymnastics. We need to produce a value which the
sometimes shaky I6 expression parser will accept, which turns out to be
quite a constraint. If we were compiling to C, we might try this:
@@ -794,7 +451,232 @@ then the result.
OUTDENT; WRITE(")\n");
§6.5.4. Generate primitive for if6.5.4 =
+ §6.2. Storing or otherwise changing values6.2 =
+ §6.2.1. Perform a store6.2.1 =
+ §6.2.1.1. Handle the ref using the incomplete-function mode6.2.1.1 =
+ §6.2.1.2. Handle the ref with code working either as lvalue or rvalue6.2.1.2 =
+ §6.3. Property value access6.3 =
+ §6.3.1. Write attribute give6.3.1 =
+ §6.3.2. Write attribute take6.3.2 =
+ §6.3.3. Write property value6.3.3 =
+ §6.3.4. Evaluate property value6.3.4 =
+ §6.6. Control structures6.6 =
+ §6.6.1. Generate primitive for return6.6.1 =
+ §6.6.2. Generate primitive for if6.6.2 =
§6.5.5. Generate primitive for ifdebug6.5.5 =
+ §6.6.3. Generate primitive for ifdebug6.6.3 =
§6.5.6. Generate primitive for ifstrict6.5.6 =
+ §6.6.4. Generate primitive for ifstrict6.6.4 =
§6.5.7. Generate primitive for ifelse6.5.7 =
+ §6.6.5. Generate primitive for ifelse6.6.5 =
§6.5.8. Generate primitive for while6.5.8 =
+ §6.6.6. Generate primitive for while6.6.6 =
§6.5.9. Generate primitive for do6.5.9 =
+ §6.6.7. Generate primitive for do6.6.7 =
§6.5.10. Generate primitive for for6.5.10 =
+ §6.6.8. Generate primitive for for6.6.8 =
§6.5.11. Generate primitive for objectloop6.5.11 =
+ §6.6.9. Generate primitive for objectloop6.6.9 =
§6.5.12. Generate primitive for objectloopx6.5.12 =
+ §6.6.10. Generate primitive for objectloopx6.6.10 =
§6.5.13. Generate primitive for loop6.5.13 =
+ §6.6.11. Generate primitive for loop6.6.11 =
§6.5.14. Generate primitive for switch6.5.14 =
+ §6.6.12. Generate primitive for switch6.6.12 =
§6.5.15. Generate primitive for case6.5.15 =
+ §6.6.13. Generate primitive for case6.6.13 =
§6.5.16. Generate primitive for default6.5.16 =
+ §6.6.14. Generate primitive for default6.6.14 =
§6.7. Indirect function or method calls6.7 =
+ §6.9. The VM object tree6.9 =
+ §6.10. Random number generator6.10 =
+
int i6_next_is_a_ref = FALSE, i6_next_is_a_give = FALSE, i6_next_is_a_take = FALSE;
@@ -346,18 +349,17 @@ As a dodge, we use the Inform 6 statement int suppress_terminal_semicolon = FALSE;
inter_tree *I = gen->from;
inter_ti bip = Primitives::to_bip(I, prim_name);
- text_stream *store_form = NULL;
switch (bip) {
Basic arithmetic and logical operations6.1;
Storing or otherwise changing values6.2;
- VM stack access6.4;
- Control structures6.5;
- Indirect function or method calls6.6;
+ VM stack access6.5;
+ Control structures6.6;
+ Indirect function or method calls6.7;
Property value access6.3;
- Textual output6.7;
- The VM object tree6.8;
- Random number generator6.9;
+ Textual output6.8;
+ The VM object tree6.9;
+ Random number generator6.10;
default:
WRITE_TO(STDERR, "Unimplemented primitive is '%S'\n", prim_name->symbol_name);
internal_error("unimplemented prim");
@@ -397,351 +399,6 @@ As a dodge, we use the Inform 6 statement case ALTERNATIVE_BIP: VNODE_1C; WRITE(" or "); VNODE_2C; break;
-
- case STORE_BIP: store_form = I"i7_lvalue_SET"; Perform a store6.2.1; break;
- case PREINCREMENT_BIP: store_form = I"i7_lvalue_PREINC"; Perform a store6.2.1; break;
- case POSTINCREMENT_BIP: store_form = I"i7_lvalue_POSTINC"; Perform a store6.2.1; break;
- case PREDECREMENT_BIP: store_form = I"i7_lvalue_PREDEC"; Perform a store6.2.1; break;
- case POSTDECREMENT_BIP: store_form = I"i7_lvalue_POSTDEC"; Perform a store6.2.1; break;
- case SETBIT_BIP: store_form = I"i7_lvalue_SETBIT"; Perform a store6.2.1; break;
- case CLEARBIT_BIP: store_form = I"i7_lvalue_CLEARBIT"; Perform a store6.2.1; break;
-
-
-
- case PROPERTYEXISTS_BIP:
- I6_GEN_DATA(value_ranges_needed) = TRUE;
- I6_GEN_DATA(value_property_holders_needed) = TRUE;
- WRITE("(_final_provides("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE(", "); VNODE_3C; WRITE("))"); break;
- case PROPERTYADDRESS_BIP: WRITE("(_final_read_paddr("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE("))"); break;
- case PROPERTYLENGTH_BIP: WRITE("(_final_read_plen("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE("))"); break;
- case PROPERTYVALUE_BIP: if (i6_next_is_a_give)
- Write attribute give6.3.1
- else if (i6_next_is_a_take)
- Write attribute take6.3.2
- else if (i6_next_is_a_ref)
- Write property value6.3.3
- else
- Evaluate property value6.3.4;
- break;
-
-
-
-
-
- case PUSH_BIP: WRITE("@push "); VNODE_1C; break;
- case PULL_BIP: WRITE("@pull "); VNODE_1C; break;
-
-
-
- case BREAK_BIP: WRITE("break"); break;
- case CONTINUE_BIP: WRITE("continue"); break;
- case RETURN_BIP: Generate primitive for return6.5.3; break;
- case JUMP_BIP: WRITE("jump "); VNODE_1C; break;
- case QUIT_BIP: WRITE("quit"); break;
- case RESTORE_BIP: WRITE("restore "); VNODE_1C; break;
- case IF_BIP: Generate primitive for if6.5.4; break;
- case IFDEBUG_BIP: Generate primitive for ifdebug6.5.5; break;
- case IFSTRICT_BIP: Generate primitive for ifstrict6.5.6; break;
- case IFELSE_BIP: Generate primitive for ifelse6.5.7; break;
- case WHILE_BIP: Generate primitive for while6.5.8; break;
- case DO_BIP: Generate primitive for do6.5.9; break;
- case FOR_BIP: Generate primitive for for6.5.10; break;
- case OBJECTLOOP_BIP: Generate primitive for objectloop6.5.11; break;
- case OBJECTLOOPX_BIP: Generate primitive for objectloopx6.5.12; break;
- case LOOP_BIP: Generate primitive for loop6.5.13; break;
- case SWITCH_BIP: Generate primitive for switch6.5.14; break;
- case CASE_BIP: Generate primitive for case6.5.15; break;
- case ALTERNATIVECASE_BIP: VNODE_1C; WRITE(", "); VNODE_2C; break;
- case DEFAULT_BIP: Generate primitive for default6.5.16; break;
-
-
-
- case INDIRECT0_BIP: case INDIRECT0V_BIP: case CALLMESSAGE0_BIP:
- WRITE("("); VNODE_1C; WRITE(")()"); break;
- case INDIRECT1_BIP: case INDIRECT1V_BIP: case CALLMESSAGE1_BIP:
- WRITE("("); VNODE_1C; WRITE(")(");
- VNODE_2C; WRITE(")"); break;
- case INDIRECT2_BIP: case INDIRECT2V_BIP: case CALLMESSAGE2_BIP:
- WRITE("("); VNODE_1C; WRITE(")(");
- VNODE_2C; WRITE(","); VNODE_3C; WRITE(")"); break;
- case INDIRECT3_BIP: case INDIRECT3V_BIP: case CALLMESSAGE3_BIP:
- WRITE("("); VNODE_1C; WRITE(")(");
- VNODE_2C; WRITE(","); VNODE_3C; WRITE(","); VNODE_4C; WRITE(")"); break;
- case INDIRECT4_BIP: case INDIRECT4V_BIP:
- WRITE("("); VNODE_1C; WRITE(")(");
- VNODE_2C; WRITE(","); VNODE_3C; WRITE(","); VNODE_4C; WRITE(",");
- VNODE_5C; WRITE(")"); break;
- case INDIRECT5_BIP: case INDIRECT5V_BIP:
- WRITE("("); VNODE_1C; WRITE(")(");
- VNODE_2C; WRITE(","); VNODE_3C; WRITE(","); VNODE_4C; WRITE(",");
- VNODE_5C; WRITE(","); VNODE_6C; WRITE(")"); break;
- case MESSAGE0_BIP: WRITE("_final_message0("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE(")"); break;
- case MESSAGE1_BIP: WRITE("("); VNODE_1C; WRITE(".("); VNODE_2C; WRITE("-->1)(");
- VNODE_3C; WRITE("))"); break;
- case MESSAGE2_BIP: WRITE("("); VNODE_1C; WRITE(".("); VNODE_2C; WRITE("-->1)(");
- VNODE_3C; WRITE(","); VNODE_4C; WRITE("))"); break;
- case MESSAGE3_BIP: WRITE("("); VNODE_1C; WRITE(".("); VNODE_2C; WRITE("-->1)(");
- VNODE_3C; WRITE(","); VNODE_4C; WRITE(","); VNODE_5C; WRITE("))"); break;
-
- case EXTERNALCALL_BIP: internal_error("external calls impossible in Inform 6"); break;
-
-
-
-
-
- case PRINT_BIP: WRITE("print "); CodeGen::lt_mode(gen, PRINTING_LTM); VNODE_1C; CodeGen::lt_mode(gen, REGULAR_LTM); break;
- case PRINTCHAR_BIP: WRITE("print (char) "); VNODE_1C; break;
- case PRINTNL_BIP: WRITE("new_line"); break;
- case PRINTOBJ_BIP: WRITE("print (object) "); VNODE_1C; break;
- case PRINTNUMBER_BIP: WRITE("print "); VNODE_1C; break;
- case PRINTDWORD_BIP: WRITE("print (address) "); VNODE_1C; break;
- case PRINTSTRING_BIP: WRITE("print (string) "); VNODE_1C; break;
- case BOX_BIP: WRITE("box "); CodeGen::lt_mode(gen, BOX_LTM); VNODE_1C; CodeGen::lt_mode(gen, REGULAR_LTM); break;
- case SPACES_BIP: WRITE("spaces "); VNODE_1C; break;
- case FONT_BIP:
- WRITE("if ("); VNODE_1C; WRITE(") { font on; } else { font off; }");
- suppress_terminal_semicolon = TRUE;
- break;
- case STYLE_BIP: {
- inter_tree_node *N = InterTree::first_child(P);
- if ((N->W.data[ID_IFLD] == CONSTANT_IST) &&
- (N->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT)) {
- inter_ti val2 = N->W.data[DATA_CONST_IFLD + 1];
- switch (val2) {
- case 1: WRITE("style bold"); break;
- case 2: WRITE("style underline"); break;
- case 3: WRITE("style reverse"); break;
- default: WRITE("style roman");
- }
- } else {
- WRITE("style roman");
- }
- break;
- }
-
-
-
- case MOVE_BIP: WRITE("move "); VNODE_1C; WRITE(" to "); VNODE_2C; break;
- case REMOVE_BIP: WRITE("remove "); VNODE_1C; break;
-
-
-
- case RANDOM_BIP: WRITE("random("); VNODE_1C; WRITE(")"); break;
-
-
-
- inter_tree_node *ref = InterTree::first_child(P);
- if ((Inter::Reference::node_is_ref_to(gen->from, ref, PROPERTYVALUE_BIP)) &&
- (I6TargetCode::pval_case(ref) != 2)) {
- Handle the ref using the incomplete-function mode6.2.1.1;
- } else {
- Handle the ref with code working either as lvalue or rvalue6.2.1.2;
- }
-
-
-
- inter_tree_node *VP = InterTree::second_child(P);
- int set = NOT_APPLICABLE;
- if (VP->W.data[ID_IFLD] == VAL_IST) {
- inter_ti val1 = VP->W.data[VAL1_VAL_IFLD];
- inter_ti val2 = VP->W.data[VAL2_VAL_IFLD];
- if ((val1 == LITERAL_IVAL) && (val2)) set = TRUE;
- if ((val1 == LITERAL_IVAL) && (val2 == 0)) set = FALSE;
- }
- if ((I6TargetCode::pval_case(ref) == 1) && (set == TRUE)) {
- i6_next_is_a_give = TRUE; VNODE_1C; i6_next_is_a_give = FALSE;
- } else if ((I6TargetCode::pval_case(ref) == 1) && (set == FALSE)) {
- i6_next_is_a_take = TRUE; VNODE_1C; i6_next_is_a_take = FALSE;
- } else {
- WRITE("("); i6_next_is_a_ref = TRUE; VNODE_1C; i6_next_is_a_ref = FALSE;
- if (bip == STORE_BIP) { VNODE_2C; } else { WRITE("0"); }
- WRITE(", %S))", store_form);
- }
-
-
-
- switch (bip) {
- case PREINCREMENT_BIP: WRITE("++("); VNODE_1C; WRITE(")"); break;
- case POSTINCREMENT_BIP: WRITE("("); VNODE_1C; WRITE(")++"); break;
- case PREDECREMENT_BIP: WRITE("--("); VNODE_1C; WRITE(")"); break;
- case POSTDECREMENT_BIP: WRITE("("); VNODE_1C; WRITE(")--"); break;
- case STORE_BIP: WRITE("("); VNODE_1C; WRITE(" = "); VNODE_2C; WRITE(")"); break;
- case SETBIT_BIP: VNODE_1C; WRITE(" = "); VNODE_1C; WRITE(" | "); VNODE_2C; break;
- case CLEARBIT_BIP: VNODE_1C; WRITE(" = "); VNODE_1C; WRITE(" &~ ("); VNODE_2C; WRITE(")"); break;
- }
-
-
-
- i6_next_is_a_give = FALSE;
- WRITE("give "); VNODE_2C; WRITE(" %S", I6TargetCode::inner_name(gen, P)); break;
-
-
-
- i6_next_is_a_take = FALSE;
- WRITE("give "); VNODE_2C; WRITE(" ~%S", I6TargetCode::inner_name(gen, P)); break;
-
-
-
- i6_next_is_a_ref = FALSE;
- WRITE("_final_write_pval("); VNODE_1C; WRITE(","); VNODE_2C; WRITE(","); VNODE_3C; WRITE(", ");
-
-
-
- switch (I6TargetCode::pval_case(P)) {
- case 1: WRITE("("); VNODE_2C; WRITE(" has %S", I6TargetCode::inner_name(gen, P)); WRITE(")"); break;
- case 2: WRITE("("); VNODE_2C; WRITE(".%S", I6TargetCode::inner_name(gen, P)); WRITE(")"); break;
- case 3: I6_GEN_DATA(value_property_holders_needed) = TRUE;
- I6TargetCode::comparison_r(gen, InterTree::first_child(P), InterTree::second_child(P), InterTree::third_child(P), 0); break;
- }
-
-
-
-
-
-void I6TargetCode::comparison_r(code_generation *gen, inter_tree_node *K,
- inter_tree_node *X, inter_tree_node *Y, int depth) {
- text_stream *OUT = CodeGen::current(gen);
- if (Y->W.data[ID_IFLD] == INV_IST) {
- if (Y->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
- inter_symbol *prim = Inter::Inv::invokee(Y);
- inter_ti ybip = Primitives::to_bip(gen->from, prim);
- if (ybip == ALTERNATIVE_BIP) {
- if (depth == 0) { WRITE("((or_tmp_var = "); Vanilla::node(gen, X); WRITE(") && (("); }
- I6TargetCode::comparison_r(gen, K, NULL, InterTree::first_child(Y), depth+1);
- WRITE(") || (");
- I6TargetCode::comparison_r(gen, K, NULL, InterTree::second_child(Y), depth+1);
- if (depth == 0) { WRITE(")))"); }
- return;
- }
- }
- }
- switch (I6TargetCode::pval_case_inner(Y)) {
- case 1: WRITE("("); if (X) Vanilla::node(gen, X); else WRITE("or_tmp_var"); WRITE(" has %S", I6TargetCode::inner_name_inner(gen, Y)); WRITE(")"); break;
- case 2: WRITE("("); if (X) Vanilla::node(gen, X); else WRITE("or_tmp_var"); WRITE(".%S", I6TargetCode::inner_name_inner(gen, Y)); WRITE(")"); break;
- case 3:
- WRITE("_final_read_pval(");
- Vanilla::node(gen, K);
- WRITE(", ");
- if (X) Vanilla::node(gen, X); else WRITE("or_tmp_var");
- WRITE(", ");
- Vanilla::node(gen, Y);
- WRITE(")"); break;
- }
-}
-
-
-
-
-int I6TargetCode::pval_case(inter_tree_node *P) {
- while (P->W.data[ID_IFLD] == REFERENCE_IST) P = InterTree::first_child(P);
- inter_tree_node *prop_node = InterTree::third_child(P);
- return I6TargetCode::pval_case_inner(prop_node);
-}
-
-text_stream *I6TargetCode::inner_name(code_generation *gen, inter_tree_node *P) {
- while (P->W.data[ID_IFLD] == REFERENCE_IST) P = InterTree::first_child(P);
- inter_tree_node *prop_node = InterTree::third_child(P);
- return I6TargetCode::inner_name_inner(gen, prop_node);
-}
-
-text_stream *I6TargetCode::inner_name_inner(code_generation *gen, inter_tree_node *prop_node) {
- inter_symbol *prop_symbol = NULL;
- if (prop_node->W.data[ID_IFLD] == VAL_IST) {
- inter_ti val1 = prop_node->W.data[VAL1_VAL_IFLD];
- inter_ti val2 = prop_node->W.data[VAL2_VAL_IFLD];
- if (Inter::Symbols::is_stored_in_data(val1, val2))
- prop_symbol =
- InterSymbolsTables::symbol_from_id(Inter::Packages::scope_of(prop_node), val2);
- }
- if ((prop_symbol) && (Inter::Symbols::get_flag(prop_symbol, ATTRIBUTE_MARK_BIT))) {
- return VanillaObjects::inner_property_name(gen, prop_symbol);
- } else if ((prop_symbol) && (prop_symbol->definition->W.data[ID_IFLD] == PROPERTY_IST)) {
- return VanillaObjects::inner_property_name(gen, prop_symbol);
- } else {
- return NULL;
- }
-}
-
-int I6TargetCode::pval_case_inner(inter_tree_node *prop_node) {
- inter_symbol *prop_symbol = NULL;
- if (prop_node->W.data[ID_IFLD] == VAL_IST) {
- inter_ti val1 = prop_node->W.data[VAL1_VAL_IFLD];
- inter_ti val2 = prop_node->W.data[VAL2_VAL_IFLD];
- if (Inter::Symbols::is_stored_in_data(val1, val2))
- prop_symbol =
- InterSymbolsTables::symbol_from_id(Inter::Packages::scope_of(prop_node), val2);
- }
- if ((prop_symbol) && (Inter::Symbols::get_flag(prop_symbol, ATTRIBUTE_MARK_BIT))) {
- return 1;
- } else if ((prop_symbol) && (prop_symbol->definition->W.data[ID_IFLD] == PROPERTY_IST)) {
- return 2;
- } else {
- return 3;
- }
-}
-
-
- int rboolean = NOT_APPLICABLE;
- inter_tree_node *V = InterTree::first_child(P);
- if (V->W.data[ID_IFLD] == VAL_IST) {
- inter_ti val1 = V->W.data[VAL1_VAL_IFLD];
- inter_ti val2 = V->W.data[VAL2_VAL_IFLD];
- if (val1 == LITERAL_IVAL) {
- if (val2 == 0) rboolean = FALSE;
- if (val2 == 1) rboolean = TRUE;
- }
- }
- switch (rboolean) {
- case FALSE: WRITE("rfalse"); break;
- case TRUE: WRITE("rtrue"); break;
- case NOT_APPLICABLE: WRITE("return "); Vanilla::node(gen, V); break;
- }
-
-
-
+ case STORE_BIP: Perform a store6.2.1; break;
+ case PREINCREMENT_BIP: Perform a store6.2.1; break;
+ case POSTINCREMENT_BIP: Perform a store6.2.1; break;
+ case PREDECREMENT_BIP: Perform a store6.2.1; break;
+ case POSTDECREMENT_BIP: Perform a store6.2.1; break;
+ case SETBIT_BIP: Perform a store6.2.1; break;
+ case CLEARBIT_BIP: Perform a store6.2.1; break;
+
+
+
+ inter_tree_node *ref = InterTree::first_child(P);
+ if ((Inter::Reference::node_is_ref_to(gen->from, ref, PROPERTYVALUE_BIP)) &&
+ (I6TargetCode::pval_case(ref) != I6G_CAN_PROVE_IS_OBJ_PROPERTY)) {
+ Handle the ref using the incomplete-function mode6.2.1.1;
+ } else {
+ Handle the ref with code working either as lvalue or rvalue6.2.1.2;
+ }
+
+
+
+ inter_tree_node *VP = InterTree::second_child(P);
+ int set = NOT_APPLICABLE;
+ if (VP->W.data[ID_IFLD] == VAL_IST) {
+ inter_ti val1 = VP->W.data[VAL1_VAL_IFLD];
+ inter_ti val2 = VP->W.data[VAL2_VAL_IFLD];
+ if ((val1 == LITERAL_IVAL) && (val2)) set = TRUE;
+ if ((val1 == LITERAL_IVAL) && (val2 == 0)) set = FALSE;
+ }
+ if ((I6TargetCode::pval_case(ref) == I6G_CAN_PROVE_IS_OBJ_ATTRIBUTE) && (set == TRUE)) {
+ i6_next_is_a_give = TRUE; VNODE_1C; i6_next_is_a_give = FALSE;
+ } else if ((I6TargetCode::pval_case(ref) == I6G_CAN_PROVE_IS_OBJ_ATTRIBUTE) && (set == FALSE)) {
+ i6_next_is_a_take = TRUE; VNODE_1C; i6_next_is_a_take = FALSE;
+ } else {
+ WRITE("("); i6_next_is_a_ref = TRUE; VNODE_1C; i6_next_is_a_ref = FALSE;
+ if (bip == STORE_BIP) { VNODE_2C; } else { WRITE("0"); }
+ text_stream *store_form = NULL;
+ switch (bip) {
+ case STORE_BIP: store_form = I"i7_lvalue_SET"; break;
+ case PREINCREMENT_BIP: store_form = I"i7_lvalue_PREINC"; break;
+ case POSTINCREMENT_BIP: store_form = I"i7_lvalue_POSTINC"; break;
+ case PREDECREMENT_BIP: store_form = I"i7_lvalue_PREDEC"; break;
+ case POSTDECREMENT_BIP: store_form = I"i7_lvalue_POSTDEC"; break;
+ case SETBIT_BIP: store_form = I"i7_lvalue_SETBIT"; break;
+ case CLEARBIT_BIP: store_form = I"i7_lvalue_CLEARBIT"; break;
+ }
+ WRITE(", %S))", store_form);
+ }
+
+
+
+ switch (bip) {
+ case PREINCREMENT_BIP: WRITE("++("); VNODE_1C; WRITE(")"); break;
+ case POSTINCREMENT_BIP: WRITE("("); VNODE_1C; WRITE(")++"); break;
+ case PREDECREMENT_BIP: WRITE("--("); VNODE_1C; WRITE(")"); break;
+ case POSTDECREMENT_BIP: WRITE("("); VNODE_1C; WRITE(")--"); break;
+ case STORE_BIP: WRITE("("); VNODE_1C; WRITE(" = "); VNODE_2C; WRITE(")"); break;
+ case SETBIT_BIP: VNODE_1C; WRITE(" = "); VNODE_1C; WRITE(" | "); VNODE_2C; break;
+ case CLEARBIT_BIP: VNODE_1C; WRITE(" = "); VNODE_1C; WRITE(" &~ ("); VNODE_2C; WRITE(")"); break;
+ }
+
+
+
+ case PROPERTYEXISTS_BIP:
+ I6_GEN_DATA(value_ranges_needed) = TRUE;
+ I6_GEN_DATA(value_property_holders_needed) = TRUE;
+ WRITE("(_final_provides("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE(", "); VNODE_3C; WRITE("))"); break;
+ case PROPERTYADDRESS_BIP: WRITE("(_final_read_paddr("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE("))"); break;
+ case PROPERTYLENGTH_BIP: WRITE("(_final_read_plen("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE("))"); break;
+ case PROPERTYVALUE_BIP:
+ if (i6_next_is_a_give) Write attribute give6.3.1
+ else if (i6_next_is_a_take) Write attribute take6.3.2
+ else if (i6_next_is_a_ref) Write property value6.3.3
+ else Evaluate property value6.3.4;
+ break;
+
+
+
+ i6_next_is_a_give = FALSE;
+ WRITE("give "); VNODE_2C; WRITE(" %S", I6TargetCode::inner_name(gen, P)); break;
+
+
+
+ i6_next_is_a_take = FALSE;
+ WRITE("give "); VNODE_2C; WRITE(" ~%S", I6TargetCode::inner_name(gen, P)); break;
+
+
+
+ i6_next_is_a_ref = FALSE;
+ WRITE("_final_write_pval("); VNODE_1C; WRITE(","); VNODE_2C; WRITE(","); VNODE_3C; WRITE(", ");
+
+
+
+ switch (I6TargetCode::pval_case(P)) {
+ case I6G_CAN_PROVE_IS_OBJ_ATTRIBUTE:
+ WRITE("("); VNODE_2C; WRITE(" has %S", I6TargetCode::inner_name(gen, P)); WRITE(")"); break;
+ case I6G_CAN_PROVE_IS_OBJ_PROPERTY:
+ WRITE("("); VNODE_2C; WRITE(".%S", I6TargetCode::inner_name(gen, P)); WRITE(")"); break;
+ case I6G_CANNOT_PROVE:
+ I6_GEN_DATA(value_property_holders_needed) = TRUE;
+ I6TargetCode::eval_property_list(gen, InterTree::first_child(P),
+ InterTree::second_child(P), InterTree::third_child(P), 0); break;
+ }
+
+
+
+
+
+void I6TargetCode::eval_property_list(code_generation *gen, inter_tree_node *K,
+ inter_tree_node *X, inter_tree_node *Y, int depth) {
+ text_stream *OUT = CodeGen::current(gen);
+ if (Y->W.data[ID_IFLD] == INV_IST) {
+ if (Y->W.data[METHOD_INV_IFLD] == INVOKED_PRIMITIVE) {
+ inter_symbol *prim = Inter::Inv::invokee(Y);
+ inter_ti ybip = Primitives::to_bip(gen->from, prim);
+ if (ybip == ALTERNATIVE_BIP) {
+ if (depth == 0) { WRITE("((or_tmp_var = "); Vanilla::node(gen, X); WRITE(") && (("); }
+ I6TargetCode::eval_property_list(gen, K, NULL, InterTree::first_child(Y), depth+1);
+ WRITE(") || (");
+ I6TargetCode::eval_property_list(gen, K, NULL, InterTree::second_child(Y), depth+1);
+ if (depth == 0) { WRITE(")))"); }
+ return;
+ }
+ }
+ }
+ switch (I6TargetCode::pval_case_inner(Y)) {
+ case I6G_CAN_PROVE_IS_OBJ_ATTRIBUTE:
+ WRITE("("); if (X) Vanilla::node(gen, X); else WRITE("or_tmp_var");
+ WRITE(" has %S", I6TargetCode::inner_name_inner(gen, Y)); WRITE(")"); break;
+ case I6G_CAN_PROVE_IS_OBJ_PROPERTY:
+ WRITE("("); if (X) Vanilla::node(gen, X); else WRITE("or_tmp_var");
+ WRITE(".%S", I6TargetCode::inner_name_inner(gen, Y)); WRITE(")"); break;
+ case I6G_CANNOT_PROVE:
+ WRITE("_final_read_pval(");
+ Vanilla::node(gen, K);
+ WRITE(", ");
+ if (X) Vanilla::node(gen, X); else WRITE("or_tmp_var");
+ WRITE(", ");
+ Vanilla::node(gen, Y);
+ WRITE(")"); break;
+ }
+}
+
+
+
+
+ case PUSH_BIP: WRITE("@push "); VNODE_1C; break;
+ case PULL_BIP: WRITE("@pull "); VNODE_1C; break;
+
+
+
+ case BREAK_BIP: WRITE("break"); break;
+ case CONTINUE_BIP: WRITE("continue"); break;
+ case RETURN_BIP: Generate primitive for return6.6.1; break;
+ case JUMP_BIP: WRITE("jump "); VNODE_1C; break;
+ case QUIT_BIP: WRITE("quit"); break;
+ case RESTORE_BIP: WRITE("restore "); VNODE_1C; break;
+ case IF_BIP: Generate primitive for if6.6.2; break;
+ case IFDEBUG_BIP: Generate primitive for ifdebug6.6.3; break;
+ case IFSTRICT_BIP: Generate primitive for ifstrict6.6.4; break;
+ case IFELSE_BIP: Generate primitive for ifelse6.6.5; break;
+ case WHILE_BIP: Generate primitive for while6.6.6; break;
+ case DO_BIP: Generate primitive for do6.6.7; break;
+ case FOR_BIP: Generate primitive for for6.6.8; break;
+ case OBJECTLOOP_BIP: Generate primitive for objectloop6.6.9; break;
+ case OBJECTLOOPX_BIP: Generate primitive for objectloopx6.6.10; break;
+ case LOOP_BIP: Generate primitive for loop6.6.11; break;
+ case SWITCH_BIP: Generate primitive for switch6.6.12; break;
+ case CASE_BIP: Generate primitive for case6.6.13; break;
+ case ALTERNATIVECASE_BIP: VNODE_1C; WRITE(", "); VNODE_2C; break;
+ case DEFAULT_BIP: Generate primitive for default6.6.14; break;
+
+
+
+ int rboolean = NOT_APPLICABLE;
+ inter_tree_node *V = InterTree::first_child(P);
+ if (V->W.data[ID_IFLD] == VAL_IST) {
+ inter_ti val1 = V->W.data[VAL1_VAL_IFLD];
+ inter_ti val2 = V->W.data[VAL2_VAL_IFLD];
+ if (val1 == LITERAL_IVAL) {
+ if (val2 == 0) rboolean = FALSE;
+ if (val2 == 1) rboolean = TRUE;
+ }
+ }
+ switch (rboolean) {
+ case FALSE: WRITE("rfalse"); break;
+ case TRUE: WRITE("rtrue"); break;
+ case NOT_APPLICABLE: WRITE("return "); Vanilla::node(gen, V); break;
+ }
+
+
+
@@ -802,24 +684,24 @@ then the result.
OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
WRITE("#ifdef DEBUG;\n"); INDENT; VNODE_1C; OUTDENT; WRITE("#endif;\n");
suppress_terminal_semicolon = TRUE;
-
-
+
WRITE("#ifdef STRICT_MODE;\n"); INDENT; VNODE_1C; OUTDENT; WRITE("#endif;\n");
suppress_terminal_semicolon = TRUE;
-
-
+
@@ -827,29 +709,31 @@ then the result.
WRITE("} else {\n"); INDENT; VNODE_3C; OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
WRITE("while ("); VNODE_1C; WRITE(") {\n"); INDENT; VNODE_2C; OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
WRITE("do {"); VNODE_2C; WRITE("} until (\n"); INDENT; VNODE_1C; OUTDENT; WRITE(")\n");
-
-
+
WRITE("for (");
inter_tree_node *INIT = InterTree::first_child(P);
- if (!((INIT->W.data[ID_IFLD] == VAL_IST) && (INIT->W.data[VAL1_VAL_IFLD] == LITERAL_IVAL) && (INIT->W.data[VAL2_VAL_IFLD] == 1))) VNODE_1C;
+ if (!((INIT->W.data[ID_IFLD] == VAL_IST) &&
+ (INIT->W.data[VAL1_VAL_IFLD] == LITERAL_IVAL) &&
+ (INIT->W.data[VAL2_VAL_IFLD] == 1))) VNODE_1C;
WRITE(":"); VNODE_2C;
WRITE(":");
inter_tree_node *U = InterTree::third_child(P);
@@ -859,8 +743,8 @@ then the result.
OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
@@ -883,8 +767,8 @@ then the result.
OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
@@ -892,16 +776,16 @@ then the result.
WRITE(") {\n"); INDENT; VNODE_3C; OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
WRITE("{\n"); INDENT; VNODE_1C; OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
@@ -909,25 +793,172 @@ then the result.
WRITE(") {\n"); INDENT; VNODE_2C; OUTDENT; WRITE("}\n");
suppress_terminal_semicolon = TRUE;
-
-
+
VNODE_1C; WRITE(":\n"); INDENT; VNODE_2C; WRITE(";\n"); OUTDENT;
suppress_terminal_semicolon = TRUE;
-
-
+
WRITE("default:\n"); INDENT; VNODE_1C; WRITE(";\n"); OUTDENT;
suppress_terminal_semicolon = TRUE;
-
-
-
+
+
+ case INDIRECT0_BIP:
+ case INDIRECT0V_BIP:
+ case CALLMESSAGE0_BIP: WRITE("("); VNODE_1C; WRITE(")()"); break;
+ case INDIRECT1_BIP:
+ case INDIRECT1V_BIP:
+ case CALLMESSAGE1_BIP: WRITE("("); VNODE_1C; WRITE(")(");
+ VNODE_2C; WRITE(")"); break;
+ case INDIRECT2_BIP:
+ case INDIRECT2V_BIP:
+ case CALLMESSAGE2_BIP: WRITE("("); VNODE_1C; WRITE(")(");
+ VNODE_2C; WRITE(","); VNODE_3C; WRITE(")"); break;
+ case INDIRECT3_BIP:
+ case INDIRECT3V_BIP:
+ case CALLMESSAGE3_BIP: WRITE("("); VNODE_1C; WRITE(")(");
+ VNODE_2C; WRITE(","); VNODE_3C; WRITE(","); VNODE_4C; WRITE(")"); break;
+ case INDIRECT4_BIP:
+ case INDIRECT4V_BIP: WRITE("("); VNODE_1C; WRITE(")(");
+ VNODE_2C; WRITE(","); VNODE_3C; WRITE(","); VNODE_4C; WRITE(",");
+ VNODE_5C; WRITE(")"); break;
+ case INDIRECT5_BIP:
+ case INDIRECT5V_BIP: WRITE("("); VNODE_1C; WRITE(")(");
+ VNODE_2C; WRITE(","); VNODE_3C; WRITE(","); VNODE_4C; WRITE(",");
+ VNODE_5C; WRITE(","); VNODE_6C; WRITE(")"); break;
+ case MESSAGE0_BIP: WRITE("_final_message0("); VNODE_1C; WRITE(", "); VNODE_2C; WRITE(")"); break;
+ case MESSAGE1_BIP: WRITE("("); VNODE_1C; WRITE(".("); VNODE_2C; WRITE("-->1)(");
+ VNODE_3C; WRITE("))"); break;
+ case MESSAGE2_BIP: WRITE("("); VNODE_1C; WRITE(".("); VNODE_2C; WRITE("-->1)(");
+ VNODE_3C; WRITE(","); VNODE_4C; WRITE("))"); break;
+ case MESSAGE3_BIP: WRITE("("); VNODE_1C; WRITE(".("); VNODE_2C; WRITE("-->1)(");
+ VNODE_3C; WRITE(","); VNODE_4C; WRITE(","); VNODE_5C; WRITE("))"); break;
+
+ case EXTERNALCALL_BIP: internal_error("external calls impossible in Inform 6"); break;
+
+
+
+
+
+ case PRINT_BIP: WRITE("print "); CodeGen::lt_mode(gen, PRINTING_LTM);
+ VNODE_1C; CodeGen::lt_mode(gen, REGULAR_LTM); break;
+ case PRINTCHAR_BIP: WRITE("print (char) "); VNODE_1C; break;
+ case PRINTNL_BIP: WRITE("new_line"); break;
+ case PRINTOBJ_BIP: WRITE("print (object) "); VNODE_1C; break;
+ case PRINTNUMBER_BIP: WRITE("print "); VNODE_1C; break;
+ case PRINTDWORD_BIP: WRITE("print (address) "); VNODE_1C; break;
+ case PRINTSTRING_BIP: WRITE("print (string) "); VNODE_1C; break;
+ case BOX_BIP: WRITE("box "); CodeGen::lt_mode(gen, BOX_LTM);
+ VNODE_1C; CodeGen::lt_mode(gen, REGULAR_LTM); break;
+ case SPACES_BIP: WRITE("spaces "); VNODE_1C; break;
+ case FONT_BIP:
+ WRITE("if ("); VNODE_1C; WRITE(") { font on; } else { font off; }");
+ suppress_terminal_semicolon = TRUE;
+ break;
+ case STYLE_BIP: {
+ inter_tree_node *N = InterTree::first_child(P);
+ if ((N->W.data[ID_IFLD] == CONSTANT_IST) &&
+ (N->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT)) {
+ inter_ti val2 = N->W.data[DATA_CONST_IFLD + 1];
+ switch (val2) {
+ case 1: WRITE("style bold"); break;
+ case 2: WRITE("style underline"); break;
+ case 3: WRITE("style reverse"); break;
+ default: WRITE("style roman");
+ }
+ } else {
+ WRITE("style roman");
+ }
+ break;
+ }
+
+
+
+ case MOVE_BIP: WRITE("move "); VNODE_1C; WRITE(" to "); VNODE_2C; break;
+ case REMOVE_BIP: WRITE("remove "); VNODE_1C; break;
+
+
+
+ case RANDOM_BIP: WRITE("random("); VNODE_1C; WRITE(")"); break;
+
+
+
+
+
+text_stream *I6TargetCode::inner_name(code_generation *gen, inter_tree_node *P) {
+ while (P->W.data[ID_IFLD] == REFERENCE_IST) P = InterTree::first_child(P);
+ inter_tree_node *prop_node = InterTree::third_child(P);
+ return I6TargetCode::inner_name_inner(gen, prop_node);
+}
+
+text_stream *I6TargetCode::inner_name_inner(code_generation *gen, inter_tree_node *prop_node) {
+ inter_symbol *prop_symbol = NULL;
+ if (prop_node->W.data[ID_IFLD] == VAL_IST) {
+ inter_ti val1 = prop_node->W.data[VAL1_VAL_IFLD];
+ inter_ti val2 = prop_node->W.data[VAL2_VAL_IFLD];
+ if (Inter::Symbols::is_stored_in_data(val1, val2))
+ prop_symbol =
+ InterSymbolsTables::symbol_from_id(Inter::Packages::scope_of(prop_node), val2);
+ }
+ if ((prop_symbol) && (Inter::Symbols::get_flag(prop_symbol, ATTRIBUTE_MARK_BIT))) {
+ return VanillaObjects::inner_property_name(gen, prop_symbol);
+ } else if ((prop_symbol) && (prop_symbol->definition->W.data[ID_IFLD] == PROPERTY_IST)) {
+ return VanillaObjects::inner_property_name(gen, prop_symbol);
+ } else {
+ return NULL;
+ }
+}
+
+
+
+define I6G_CAN_PROVE_IS_OBJ_ATTRIBUTE 1
+define I6G_CAN_PROVE_IS_OBJ_PROPERTY 2
+define I6G_CANNOT_PROVE 3
+
+
+int I6TargetCode::pval_case(inter_tree_node *P) {
+ while (P->W.data[ID_IFLD] == REFERENCE_IST) P = InterTree::first_child(P);
+ inter_tree_node *prop_node = InterTree::third_child(P);
+ return I6TargetCode::pval_case_inner(prop_node);
+}
+
+int I6TargetCode::pval_case_inner(inter_tree_node *prop_node) {
+ inter_symbol *prop_symbol = NULL;
+ if (prop_node->W.data[ID_IFLD] == VAL_IST) {
+ inter_ti val1 = prop_node->W.data[VAL1_VAL_IFLD];
+ inter_ti val2 = prop_node->W.data[VAL2_VAL_IFLD];
+ if (Inter::Symbols::is_stored_in_data(val1, val2))
+ prop_symbol =
+ InterSymbolsTables::symbol_from_id(Inter::Packages::scope_of(prop_node), val2);
+ }
+ if ((prop_symbol) && (Inter::Symbols::get_flag(prop_symbol, ATTRIBUTE_MARK_BIT))) {
+ return I6G_CAN_PROVE_IS_OBJ_ATTRIBUTE;
+ } else if ((prop_symbol) && (prop_symbol->definition->W.data[ID_IFLD] == PROPERTY_IST)) {
+ return I6G_CAN_PROVE_IS_OBJ_PROPERTY;
+ } else {
+ return I6G_CANNOT_PROVE;
+ }
+}
+
+
void I6TargetCode::end_generation(code_generator *cgt, code_generation *gen) {
@@ -938,7 +969,6 @@ then the result.
WRITE(" t = p-->0; p = p-->1; ! print \"has \", o, \" \", p, \"^\";\n");
WRITE(" if (t == 2) { if (o has p) rtrue; rfalse; }\n");
WRITE(" if (o provides p) {\n");
- WRITE(" if (p == door_to) return o.p();\n");
WRITE(" return o.p;\n");
WRITE(" }\n");
WRITE(" rfalse;\n");
@@ -967,8 +997,7 @@ then the result.
WRITE(" return o.#p;\n");
WRITE("];\n");
WRITE("[ _final_message0 o p q x a rv;\n");
- WRITE(" ! print \"Message send \", (the) o, \" --> \", p, \" \", p-->1, \" addr \", o.(p-->1), \"^\";\n");
- WRITE(" q = p-->1; a = o.q; if (metaclass(a) == Object) rv = a; else if (a) { x = self; self = o; rv = indirect(a); self = x; } ! print \"Message = \", rv, \"^\";\n");
+ WRITE(" q = p-->1; a = o.q; if (metaclass(a) == Object) rv = a; else if (a) { x = self; self = o; rv = indirect(a); self = x; }\n");
WRITE(" return rv;\n");
WRITE("];\n");
WRITE("[ _final_provides K o p holder;\n");
diff --git a/docs/final-module/5-cas.html b/docs/final-module/5-cas.html
index 592a86f8e..1a80c7338 100644
--- a/docs/final-module/5-cas.html
+++ b/docs/final-module/5-cas.html
@@ -289,11 +289,11 @@ function togglePopup(material_id) {
if (val) *val = 0;
}
} else {
- if ((pr == i7_mgl_A_door_to)) {
- if (val) *val = (i7word_t) i7_mcall_0(proc, obj, pr);
- } else {
+// if ((pr == i7_mgl_A_door_to)) {
+// if (val) *val = (i7word_t) i7_mcall_0(proc, obj, pr);
+// } else {
if (val) *val = (i7word_t) i7_read_prop_value(proc, obj, pr);
- }
+// }
}
} else {
i7word_t holder = i7_read_word(proc, i7_mgl_value_property_holders, K);
diff --git a/docs/if-module/3-tm.html b/docs/if-module/3-tm.html
index 78f9f096d..9637fec73 100644
--- a/docs/if-module/3-tm.html
+++ b/docs/if-module/3-tm.html
@@ -518,7 +518,7 @@ Standard Rules. (So there is no need to translate this to other languages.)
<notable-map-properties> ::=
opposite |
- other side
+ leading-through destination
@@ -1074,7 +1074,6 @@ trust that there is nothing surprising here.
P_door = EitherOrProperties::new_nameless(I"door");
- RTProperties::recommend_storing_as_attribute(P_door, TRUE);
P_door_dir = ValueProperties::new_nameless(I"door_dir", K_value);
P_door_to = ValueProperties::new_nameless(I"door_to", K_value);
diff --git a/docs/standard_rules/S-pd.html b/docs/standard_rules/S-pd.html
index 52366a65a..ac635caf5 100644
--- a/docs/standard_rules/S-pd.html
+++ b/docs/standard_rules/S-pd.html
@@ -633,6 +633,9 @@ day, the latter at the very beginning.
To decide which door is door (D - direction) from/of (R1 - room)
(documented at ph_doordirof):
(- DoorFrom({R1},{D}) -).
+To decide which object is the other side of (D - door)
+ (documented at ph_othersideof):
+ (- OtherSideOfDoor({D}, location) -).
To decide which object is the other side of (D - door) from (R1 - room)
(documented at ph_othersideof):
(- OtherSideOfDoor({D},{R1}) -).
diff --git a/docs/standard_rules/S-pwm.html b/docs/standard_rules/S-pwm.html
index 016ed3d00..dfcdf5b46 100644
--- a/docs/standard_rules/S-pwm.html
+++ b/docs/standard_rules/S-pwm.html
@@ -550,16 +550,26 @@ the player is in one of the (possibly) two rooms in which the green
door is present; and then they are defined relative to him.
The leading-through relation is built in to Inform; the other side property, -though, is merely a convenient name we give to the property in which -the relation data is stored at run-time. +
The leading-through relation is built in to Inform. This has to be stored +in the property "door_to", but we don't want to give authors direct access +to this property, since its contents are strictly speaking not typesafe. +(It stores a value to which a message can be sent which must return an object: +but that is not always the same thing as storing an object.) +
+ +Until 2021, the storage property was called "other side", and was useful +in as much as "the other side of D" would helpfully evaluate to the location +on the other side of a door. But that only worked because of a hacky exception +in the code handling property evaluation which made "door_to" a special case, +and this led to other problems. Instead, a new phrase "other side of (D - door)" +has been added to the Standard Rules, and this avoids directly evaluating "door_to".
-A door has an object called other side. -The other side property translates into Inter as "door_to". -Leading-through relates one room (called the other side) to various doors. -The verb to be through means the leading-through relation. +A door has an object called leading-through destination. +The leading-through destination property translates into Inter as "door_to". +Leading-through relates one room (called the leading-through destination) to +various doors. The verb to be through means the leading-through relation.
§28. Containers and supporters. The carrying capacity property is the exception to the remarks above about
the qualitative nature of the world model: here for the first and only time
diff --git a/inform7/Downloads/preform-diagnostics.txt b/inform7/Downloads/preform-diagnostics.txt
index a853abb6d..71f5c39b1 100644
--- a/inform7/Downloads/preform-diagnostics.txt
+++ b/inform7/Downloads/preform-diagnostics.txt
@@ -1,6 +1,6 @@