(EDIT: I was able to simplify the demonstration code, and I realized that I missed some steps in my previous trace, resulting in serious confusion. This version connects more dots and removes unwarranted speculation.)
I ran into this on 6M62 but confirmed that it also happens in 10.1.2.
It’s probably easiest to just start with the demo code:
“Pile RTP”
A pile is a kind of thing. A pile has a number called count. The initial appearance of a pile is "Strewn about here are [count in words] shiny rock[s]."
Place is a room.
There is a pile in Place. It has count 12.
A supporter called a platform is in Place.
Test me with "abstract pile to platform / look / abstract pile to place / look".
From what I can tell, the particular code causing it is found in the initial appearance on supporters
rule:
For printing a locale paragraph about a supporter (called the tabletop)
(this is the initial appearance on supporters rule):
repeat with item running through not handled things on the tabletop which
provide the property initial appearance:
if the item is not a person and the initial appearance of the item is not "" [<-- here]
and the item is not undescribed:
now the item is mentioned;
say initial appearance of the item;
say paragraph break;
continue the activity.
The I6 version of this code (6M62 output) is (with comments added):
! For printing a locale paragraph about a supporter ( called the tabletop ) ( this is the initial appearance on supporters rule ):
[ R_94
tmp_0 ! Let/loop value, e.g., 'tabletop': supporter
tmp_1 ! Let/loop value (deallocated by end of phrase)
tmp_2 ! Let/loop value (deallocated by end of phrase)
;
if ((((tmp_0 = parameter_value, (((parameter_value ofclass K6_supporter) && (tmp_0=(parameter_value), true))))) || (tmp_0 = 0,false))) { ! Runs only when pattern matches
if (debug_rules) DB_Rule(R_94, 94);
! [2: repeat with item running through not handled things on the tabletop which provide the property initial appearance]
for (tmp_1=Prop_7(tmp_0,tmp_0,tmp_0,0), tmp_2=Prop_7(tmp_0,tmp_0,tmp_0,tmp_1): tmp_1: tmp_1=tmp_2, tmp_2=Prop_7(tmp_0,tmp_0,tmp_0,tmp_2))
{! [3: if the item is not a person and the initial appearance of the item is not ~~ and the item is not undescribed]
if ((((~~((tmp_1 ofclass K8_person))))) && ((((~~(( BlkValueCompare(GProperty(10, tmp_1,initial), EMPTY_TEXT_VALUE) == 0))))) && (((~~(((Adj_64_t1_v10(tmp_1))))))))) ! <-- BlkValueCompare() generates RTP?
{! [4: now the item is mentioned]
(Adj_67_t2_v10(tmp_1));
! [5: say initial appearance of the item]
say__p=1;! [6: initial appearance of the item]
ParaContent(); @push self; print (TEXT_TY_Say) GProperty(10, self=tmp_1,initial);@pull self; .L_Say22; .L_SayX22;! [7: say paragraph break] ! <-- compare GProperty() arguments here
say__p=1;! [8: paragraph break]
ParaContent(); DivideParagraphPoint(); new_line; .L_Say23; .L_SayX23;}
}
! [9: continue the activity]
rfalse;
RulebookSucceeds(); rtrue;
} else if (debug_rules > 1) DB_Rule(R_94, 94, 'action');
rfalse;
];
The RTP ultimately must result from a call to WhetherProvides()
. That is the only routine that calls RunTimeProblem()
with parameter RTP_UNPROVIDED
, which results in the message seen.
From the tracing that I did, it seemed that somehow the value of self
as evaluated while printing the initial appearance of the pile
was incorrect. The routine that is compiled to print the initial appearance
is (with comment added):
[ R_TX_S_134 ;
#ifdef DEBUG; if (suppress_text_substitution) { print "~Strewn about here are [count in words] shiny rock[s].~"; rtrue; }
#endif; ! DEBUG
! [1: ~Strewn about here are [count in words] shiny rock[s].~]
say__p=1;! [2: ~Strewn about here are ~]
ParaContent(); print "Strewn about here are ";! [3: count in words]
ParaContent(); @push self; print (number) say__n=(GProperty(OBJECT_TY, self=self,p15_count));@pull self; ! [4: ~ shiny rock~] ! <-- self set wrong here?
ParaContent(); print " shiny rock";! [5: s]
ParaContent(); STextSubstitution();! [6: ~.~]
ParaContent(); print "."; .L_Say470; .L_SayX468;rtrue;
];
To try to prove this, I built a modified version of the initial appearance on supporters rule
:
To force self to (O - object):
(- self = {O}; -).
To decide which object is current self:
(- self -).
For printing a locale paragraph about a supporter (called the tabletop)
(this is the alternate initial appearance on supporters rule):
repeat with item running through not handled things on the tabletop:
if item provides the property initial appearance:
if the item is not a person:
if the item is not undescribed:
if the initial appearance of the item is not empty:
now the item is mentioned;
let saved self be current self;
force self to item;
say initial appearance of the item;
force self to saved self;
say paragraph break;
continue the activity.
The alternate initial appearance on supporters rule is not listed in any rulebook.
The alternate initial appearance on supporters rule substitutes for the initial appearance on supporters rule.
This change gets rid of the RTP.
The I7 compiler sets the value of self
at many points, but the place at which it is set to the platform
in this case appears to be
[ ProcessActivityRulebook rulebook parameter rv;
@push self;
if (parameter) self = parameter; ! <-- HERE
rv = FollowRulebook(rulebook, parameter, true);
@pull self;
if (rv) rtrue;
rfalse;
];
when the printing a locale paragraph about
activity is being run with a parameter
of the platform
. As seen in the generated I6 for the initial appearance on supporters rule
above, this value of self
is usually temporarily overwritten when printing the initial appearance of item
:
@push self; print (TEXT_TY_Say) GProperty(10, self=tmp_1,initial);@pull self;
The same temporary override does not occur when evaluating whether the initial appearance of item
is empty:
BlkValueCompare(GProperty(10, tmp_1,initial), EMPTY_TEXT_VALUE) ! <-- should temporarily override self as in preceding example?
The chain of calls to get from this point to the RTP appears to be:
BlkValueCompare() ! receives the initial appearance "text" (really a routine) for the pile as retrieved by GProperty() result used as argument
TEXT_TY_Compare() ! by way of KOVSupportFunction(), with COMPARE_KOVS task
TEXT_TY_Compare_Inner()
TEXT_TY_Temporarily_Transmute()
TEXT_TY_CastPrimitive() ! suspends RTP
PrintI6Text() ! executes the initial appearance "text" in a context where (self == platform)?
R_TX_S_134() ! invocation of initial appearance "text" routine; sets (self = self) when calling GProperty(), leaving undisturbed (self == platform)
GProperty() ! called with arguments self/platform and count property
WhetherProvides() ! generates RTP because platform does not have count property, but not displayed because RTPs are suspended
The tracing gets a bit tangled there, so I’m not 100% sure that I have it right, but it does seem that this may be the explanation for observed symptoms.