Inform - Support - Patches

About Patches  

Compiler  
Library  

DM4 Errata  

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

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:

  [ 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";

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.

Solution (by Neil Cerutti)

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.

--- 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 web site has not been fully supported since April 2008. Information may be out of date. This page was originally managed by Roger Firth.