The compiler appears to generate incorrect code for an expression
combining a routine call and the 'ofclass' and 'or' operators, as in the
last of the four 'if' statements: The four tests should all give the same results for a given object:
YES for C1 and C2, NO for C3. However, test 4 for C2 erroneously prints NO. Here's a patch for veneer.c that fixes this specific problem.
It's hard for me to believe that this is the end of this bug, though,
considering how many of Inform's codes compile to things that
might clobber the global variables Graham used for this case of
'or' with a temporary.
The real fix (to 'or' code output) will be more complicated, and must
be done by somebody who knows the compiler code.
About Patches
Issue C62121
Expressions with routine/ofclass/or mis-evaluate
Submitted by: Roger Firth
Appeared in: Compiler 6.21 or before
Fixed in: Compiler 6.30
Problem
[ Main; Test(c1); Test(c2); Test(c3); ];
[ Test o;
print "Testing ", (name) o, "^";
if (o ofclass X || o ofclass Y)
print "1:YES^"; else print "1:NO^";
if (o ofclass X or Y)
print "2:YES^"; else print "2:NO^";
if (parent(o) ofclass X || parent(o) ofclass Y)
print "3:YES^"; else print "3:NO^";
if (parent(o) ofclass X or Y)
print "4:YES^"; else print "4:NO^";
"";
];
Class X;
X p1;
X -> c1 "C1";
Class Y;
Y p2;
Y -> c2 "C2";
Class Z;
Z p3;
Z -> c3 "C3";
Solution (by Neil Cerutti)
--- veneer_old.c Fri Sep 20 15:37:01 2002
+++ veneer.c Fri Sep 20 15:30:25 2002
@@ -243,13 +243,16 @@
@check_arg_count 7 ?~A__x;y++;@check_arg_count 8 ?~A__x;y++;.A__x;",
"#ifdef INFIX;if (obj has infix__watching) n=1;#endif;\
#ifdef DEBUG;if (debug_flag & 1 ~= 0) n=1;#endif;\
- if (n==1) { n=debug_flag & 1; debug_flag=debug_flag-n;\
- print \"[ ~\", (name) obj, \"~.\", (property) id, \"(\";\
+ if (n==1) {\
+ #ifdef DEBUG;n=debug_flag & 1; debug_flag=debug_flag-n;#endif;\
+ print \"[ ~\", (name) obj, \"~.\", (property) id, \"(\";\
switch(y) { 1: print a; 2: print a,\",\",b; 3: print a,\",\",b,\",\",c;\
4: print a,\",\",b,\",\",c,\",\",d;\
5: print a,\",\",b,\",\",c,\",\",d,\",\",e;\
6: print a,\",\",b,\",\",c,\",\",d,\",\",e,\",\",f; }\
- print \") ]^\"; debug_flag = debug_flag + n; }"
+ print \") ]^\";\
+ #ifdef DEBUG;debug_flag = debug_flag + n;#endif;\
+ }",
"if (id > 0 && id < 64)\
{ x = obj.&id; if (x==0) { x=$000a-->0 + 2*(id-1); n=2; }\
else n = obj.#id; }\
@@ -464,19 +467,21 @@
if (Z__Region(obj) == cla-1) rtrue;\
rfalse;\
}\
- switch(cla)\
- { 1: if (obj<=4) rtrue;\
- if (obj in 1) rtrue;\
- rfalse;\
- 2: if (obj<=4) rfalse;\
- if (obj in 1) rfalse;\
- rtrue;\
- 3, 4: rfalse;\
+ if (cla == 1) {\
+ if (obj<=4) rtrue;\
+ if (obj in 1) rtrue;\
+ rfalse;\
+ } else if (cla == 2) {\
+ if (obj<=4) rfalse;\
+ if (obj in 1) rfalse;\
+ rtrue;\
+ } else if (cla == 3 or 4) {\
+ rfalse;\
}",
"if (cla notin 1) { RT__Err(\"apply 'ofclass' for\", cla, -1);rfalse;}\
- a = obj.&2;\
+ @get_prop_addr obj 2 -> a;\
if (a==0) rfalse;\
- n = obj.#2;\
+ @get_prop_len a -> n;\
for (j=0: j<n/2: j++)\
{ if (a-->j == cla) rtrue;\
}\
@@ -516,7 +521,7 @@
print \"^[** Programming error: \";\
if (crime<0) jump RErr;\
if (crime==1) { print \"class \"; @print_obj obj;\
- \": 'create' can have 0 to 3 parameters only **]\";}\
+ \": 'create' can have 0 to 5 parameters only **]\";}\
if (crime == 32) \"objectloop broken because the object \",\
(name) obj, \" was moved while the loop passed through it **]\";\
if (crime == 33) \"tried to print (char) \", obj,\
@@ -635,13 +640,15 @@
{ /* Cl__Ms: the five message-receiving properties of Classes */
"Cl__Ms",
- "obj id y a b c d x;\
+ "obj id y a b c d e f x;\
switch(id)\
{ create:\
if (children(obj)<=1) rfalse; x=child(obj);\
remove x; if (x provides create) { if (y==0) x..create();\
if (y==1) x..create(a); if (y==2) x..create(a,b);\
- if (y>3) RT__Err(1,obj); if (y>=3) x..create(a,b,c);}\
+ if (y==3) x..create(a,b,c); if (y==4) x..create(a,b,c,d);\
+ if (y>5) RT__Err(1,obj);\
+ if (y>=5) x..create(a,b,c,d,e);}\
return x;\
recreate:\
if (~~(a ofclass obj))\
@@ -649,7 +656,9 @@
Copy__Primitive(a, child(obj));\
if (a provides create) { if (y==1) a..create();\
if (y==2) a..create(b); if (y==3) a..create(b,c);\
- if (y>4) RT__Err(1,obj); if (y>=4) a..create(b,c,d);\
+ if (y==4) a..create(b,c,d); if (y==5) a..create(b,c,d,e);\
+ if (y>6) RT__Err(1,obj);\
+ if (y>=6) a..create(b,c,d,e,f);\
} rfalse;",
"destroy:\
if (~~(a ofclass obj))\
Last updated 17 April 2013.
This site is no longer supported; information may be out of date.
Maintained as a historical archive by the Interactive Fiction Technology Foundation.
Copyright 1993-2018 IFTF, CC-BY-SA unless otherwise noted.
This page was originally managed by Roger Firth.