I came across an old thread with an interesting relation, and I tried to construct a similar one:
Place is a room.
Viewability relates a room (called A) to a room (called B) when a door (called D) is adjacent to A and D is adjacent to B. The verb to be viewable from means the viewability relation.
A door called a glass door is east of Place.
Other Place is east of glass door.
A door called a grille is east of Other Place.
Yet Another Place is east of grille.
Every turn:
showme whether or not Place is viewable from Other Place;
showme whether or not glass door is adjacent to Place;
showme whether or not glass door is adjacent to Other Place;
showme whether or not glass door is adjacent to Yet Another Place;
showme the list of rooms viewable from the location.
Test views with "z / e / e".
The relation does not work in either 6M62 or 10.1.2. The transcript looks like:
Place
You can see a glass door here.
>z
Time passes.
"whether or not Place is viewable from Other Place" = truth state: false
"whether or not glass door is adjacent to Place" = truth state: true
"whether or not glass door is adjacent to Other Place" = truth state: true
"whether or not glass door is adjacent to Yet Another Place" = truth state: false
"list of rooms viewable from the location" = list of rooms: {}
>e
(first opening the glass door)
Other Place
You can see a glass door and a grille here.
"whether or not Place is viewable from Other Place" = truth state: false
"whether or not glass door is adjacent to Place" = truth state: true
"whether or not glass door is adjacent to Other Place" = truth state: true
"whether or not glass door is adjacent to Yet Another Place" = truth state: false
"list of rooms viewable from the location" = list of rooms: {}
>e
(first opening the grille)
Yet Another Place
You can see a grille here.
"whether or not Place is viewable from Other Place" = truth state: false
"whether or not glass door is adjacent to Place" = truth state: true
"whether or not glass door is adjacent to Other Place" = truth state: true
"whether or not glass door is adjacent to Yet Another Place" = truth state: false
"list of rooms viewable from the location" = list of rooms: {}
Some digging into the generated I6 (6M62 version) shows three routines are important here:
TestAdjacency()
Relation_71()
Prop_35()
TestAdjacency()
is part of the world model template/kit:
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! WorldModel.i6t: Adjacency Relation
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
[ TestAdjacency R1 R2 i row;
if (R1 ofclass K9_region) RunTimeProblem(RTP_REGIONSNOTADJACENT, R1);
else if (R2 ofclass K9_region) RunTimeProblem(RTP_REGIONSNOTADJACENT, R2);
row = (R1.IK1_Count)*No_Directions;
for (i=0: i<No_Directions: i++, row++)
if (Map_Storage-->row == R2) rtrue;
rfalse;
];
When invoked directly by the code for the every turn
rule, it behaves as expected:
! [3: showme whether or not glass door is adjacent to place]
#ifdef DEBUG;
print "~whether or not glass door is adjacent to Place~ = truth state: ",
(DA_TruthState) ((((TestAdjacency(I125_place,I126_glass_door))))), "^"; ! <-- call to TestAdjacency() correctly evaluates true
#endif;
Note that the order of arguments in the preceding block is flipped from the order in the I7; glass door is adjacent to Place
becomes TestAdjacency(I125_place,I126_glass_door)
. This is because the verb to be adjacent to
is defined as the reversed adjacency relation
by the Standard Rules.
The other two routines work together to decide whether the viewability relation
holds:
! Routine to decide if viewability(t_0, t_1)
[ Relation_71
t_0 ! Call parameter 'A': object ! <-- room A mapped to t_0
t_1 ! Call parameter 'B': object ! <-- room B mapped to t_1
tmp_0 ! Let/loop value, e.g., 'D': door ! <-- door D mapped to tmp_0
;
if (~~(t_0 ofclass K1_room)) rfalse;
if (~~(t_1 ofclass K1_room)) rfalse;
return ((((
(Prop_35(t_0) && (tmp_0=deferred_calling_list-->0, true)) || ! <-- handles test for room A, always fails!
(tmp_0 = 0,false)
))) && (((TestAdjacency(t_1,tmp_0))))); ! <-- as I7 would be "door D is adjacent to room B"
];
! True or false?
! [ Exists x : door(x) & room(x) & called='d'(door)(x) & adjacent-to(const_0, x) ] ! <-- door(x) but also room(x)???
[ Prop_35
const_0 ! Implied call parameter ! <-- assigned value of t_0 parameter in Relation_71(), i.e. room A
x ! internal use only
x_ix ! internal use only
;
;
for (x=IK1_First: x: x=x.IK1_Link){ ! <-- iterates through ROOMS, not DOORS
if ((x ofclass K4_door) && ! <-- can never be true!
(TestAdjacency(const_0,x))){ ! <-- as I7 would be "iterated room is adjacent to room A"
deferred_calling_list-->0 = x;
rtrue;
}
}
rfalse;
];
So the reason that this relation fails is that Prop_35()
always fails, and the reason that Prop_35()
always fails is that the loop is iterated through the wrong kind (i.e. rooms
, not doors
).
Based on the shorthand representation in the leading comment and the ofclass
test inside the loop, the compiler clearly understands (on some level) that the routine should be dealing with a door
. The logic of the generated code works correctly if the for
loop parameters are adjusted manually to iterate through doors
. So why is the code being generated this way?