[comp.sys.apollo] The wonderful Pascal compilier...

mth@cci632.UUCP (Michael Hickman) (11/13/90)

I have upgraded all of our machines to 10.3.  Last night a user tried running
a program I had written that generates a cross reference list of nets on a PCB. 

After the program ran all night (should have taken < 15 mins.) I killed it
figuring it needed to be recompiled under 10.3.  The program compiled fine,
but when I ran it, it barfed with an 'reference to illegal address (OS/MST 
manager)' on this:

    while not((this_net = nil) or 
              ((this_net^.plusminus = net.plusminus) and
               (this_net^.net_name  = net.net_name))) do

Looks like it tried evaluating the expression after the 'or' when the pointer 
was nil.  I changed it to this:

    while ((this_net <> nil) and 
       not((this_net^.plusminus = net.plusminus) and 
           (this_net^.net_name  = net.net_name))) do

It liked this, and the program ran.  However, another function that uses the EXACT
same line as example #1 above works fine with no changes.  Compilier optimization
level made no difference.

It bothers me that it worked fine before, but doesn't now.  I'm certainly no programming
guru, so if anyone can shed some light on this, please do.  Otherwise, this is just
another example of Apollo's great compilier technology.....


Michael T. Hickman     mth@cci.com
CAE/CAD Systems Administrator
Computer Consoles Inc.     
Rochester, NY            
(716)482-5000 x2913

rees@pisa.ifs.umich.edu (Jim Rees) (11/14/90)

In article <43023@cci632.UUCP>, mth@cci632.UUCP (Michael Hickman) writes:

  It bothers me that it worked fine before, but doesn't now.  I'm certainly
  no programming guru, so if anyone can shed some light on this, please do.
  Otherwise, this is just another example of Apollo's great compilier
  technology.....

It doesn't take a programming guru to realize that when you de-reference a
null pointer, you get what you deserve, and it isn't going to be the same
thing from machine to machine or even release to release of the same
operating system.

There are plenty of things to rag on Apollo about, but this isn't one of
them.

nazgul@alphalpha.com (Kee Hinckley) (11/14/90)

In article <43023@cci632.UUCP> mth@cci.com (Michael Hickman) writes:
>    while not((this_net = nil) or 
>              ((this_net^.plusminus = net.plusminus) and
>               (this_net^.net_name  = net.net_name))) do
>
>Looks like it tried evaluating the expression after the 'or' when the pointer 
>was nil.  I changed it to this:
...
>guru, so if anyone can shed some light on this, please do.  Otherwise, this is just
>another example of Apollo's great compilier technology.....

I wouldn't knock Apollo's compilers quite so fast.  The generate
pretty good code, even if they do take forever to do it.  But
any way, I believe you have run into a feature of Pascal.  Namely
that the order of expression evaluation is not guaranteed.  It's
been a while, but I believe that Apollo's Pascal has an 'andthen'
operator for just such cases, I assume there's something equivalent
for 'or', but I don't recall what.  Presumably 10.3 added some
compiler optimization or some such that made it decide it was
faster to interpret the expression some other way.

Now why you went into an infinite loop is another problem.  That
definitely sounds like a bug somewhere.

-- 
Alphalpha Software, Inc.	|	motif-request@alphalpha.com
nazgul@alphalpha.com		|-----------------------------------
617/646-7703 (voice/fax)	|	Proline BBS: 617/641-3722

I'm not sure which upsets me more; that people are so unwilling to accept
responsibility for their own actions, or that they are so eager to regulate
everyone else's.

kumorek@apollo.HP.COM (James Kumorek) (11/14/90)

In article <43023@cci632.UUCP>, mth@cci632.UUCP (Michael Hickman) writes:
|> 
|> I have upgraded all of our machines to 10.3.  Last night a user tried
running
|> a program I had written that generates a cross reference list of nets
on a PCB. 
|> 
|> After the program ran all night (should have taken < 15 mins.) I killed it
|> figuring it needed to be recompiled under 10.3.  The program compiled fine,
|> but when I ran it, it barfed with an 'reference to illegal address (OS/MST 
|> manager)' on this:
|> 
|>     while not((this_net = nil) or 
|>               ((this_net^.plusminus = net.plusminus) and
|>                (this_net^.net_name  = net.net_name))) do
|> 
|> Looks like it tried evaluating the expression after the 'or' when the
pointer 
|> was nil.  I changed it to this:
|> 
|>     while ((this_net <> nil) and 
|>        not((this_net^.plusminus = net.plusminus) and 
|>            (this_net^.net_name  = net.net_name))) do
|> 
|> It liked this, and the program ran.  However, another function that
uses the EXACT
|> same line as example #1 above works fine with no changes.  Compilier
optimization
|> level made no difference.
|> 
|> It bothers me that it worked fine before, but doesn't now.  I'm
certainly no programming
|> guru, so if anyone can shed some light on this, please do. 
Otherwise, this is just
|> another example of Apollo's great compilier technology.....

I don't think that Pascal defines the order in which a logical expression
is evaluated (unlike C, which defines the order to be from left to
right).  Thus,
in the code 'if (foo_ptr <> nil) and (foo_ptr^.boolean_value) then...', if the
compiler descides that it is more efficient to generate code for the
second part 
of the logical expression first, then that's what it will do.  Note that the
optimiser changes from compiler release to compiler release, so that it may put
out code in different orders from earlier releases.

In order to get around this deficiency in the Pascal language, Apollo
defined the
operators 'AND THEN' and 'OR ELSE'.  These operators ensure that the
evaluation order
is from left to right.  Thus, to recode my little example:

    if (foo_ptr <> nil) and then (foo_ptr^.boolean_value) then ...

One could argue that the compiler could have been smart enough to realize that
other parts of the expression were dereferencing the pointer that is
being checked
in the first part of the expression;  however, there are probably lots of less
'ovious' cases where this would be difficult.  Also, the more checks
that the compiler
tries to do against 'incorrect' uses of language 'features', the slower
the compiler
will be, and I suspect the last thing our customers want is even slower
compilers! :->

Hope this helps....

Jim Kumorek
Apollo Computer, Inc. - A subsidiary of Hewlett Packard
kumorek@apollo.hp.com

rehrauer@apollo.HP.COM (Steve Rehrauer) (11/14/90)

In article <43023@cci632.UUCP> mth@cci.com (Michael Hickman) writes:
>I have upgraded all of our machines to 10.3.  Last night a user tried running
>a program I had written that generates a cross reference list of nets on a PCB. 
>
>After the program ran all night (should have taken < 15 mins.) I killed it
>figuring it needed to be recompiled under 10.3.  The program compiled fine,
>but when I ran it, it barfed with an 'reference to illegal address (OS/MST 
>manager)' on this:
>
>    while not((this_net = nil) or 
>              ((this_net^.plusminus = net.plusminus) and
>               (this_net^.net_name  = net.net_name))) do
>
>Looks like it tried evaluating the expression after the 'or' when the pointer 
>was nil.  I changed it to this:
>
>    while ((this_net <> nil) and 
>       not((this_net^.plusminus = net.plusminus) and 
>           (this_net^.net_name  = net.net_name))) do
>
>It liked this, and the program ran.  However, another function that uses the EXACT
>same line as example #1 above works fine with no changes.  Compilier optimization
>level made no difference.
>
>It bothers me that it worked fine before, but doesn't now.  I'm certainly no programming
>guru, so if anyone can shed some light on this, please do.  Otherwise, this is just
>another example of Apollo's great compilier technology.....

Lord knows I'm no Pascal semantics guru.  However, your code looks a
bit bogus.  Pascal OR & AND boolean operators will evaluate both operands.
Even though your intent was clearly to say "If non-NIL pointer, then if...",
this isn't how your program will be interpreted by the compiler.  In many
circumstances, the compiler will be able to determine that evaluation of
the second operand is unnecessary, but you aren't guaranteed that behaviour.

Since you've upgraded to sr10.3, and presumably have an 8.7 Pascal compiler,
though, there is hope. :-)  Rather than standard OR & AND operators, you could
"OR ELSE" & "AND THEN", which *do* guarantee short-circuited evaluations.
For example, this Pascal snippet:

   IF ( ( ptr = NIL ) OR ELSE ( ptr^.intval <> 0 ) ) THEN

is intuitively the same as (but more compact to write than!):

   IF ( ptr <> NIL ) THEN
      IF ( ptr^.intval <> 0 ) THEN

Or, the example could've been written with "AND THEN", as:

   IF ( ( ptr <> NIL ) AND THEN ( ptr^.intval <> 0 ) ) THEN

If I were to attempt to rewrite your example snippet using "OR ELSE"
& "AND THEN", it'd probably come out looking like:

   WHILE ( ( this_net <> NIL ) AND THEN
           ( ( this_net^.plusminus = net.plusminus ) AND
             ( this_net^.net_name = net.net_name ) ) ) DO

Hope that helps.
--
"I feel lightheaded, Sam.  I think my      | (Steve) rehrauer@apollo.hp.com
 brain is out of air.  But it's kind of    | The Apollo Systems Division of
 a neat feeling..." -- Freelance Police    |       Hewlett-Packard

beierl_c@apollo.HP.COM (Christopher Beierl) (11/14/90)

In article <43023@cci632.UUCP> mth@cci.com (Michael Hickman) writes:
>                                            ...  The program compiled fine,
>but when I ran it, it barfed with an 'reference to illegal address (OS/MST 
>manager)' on this:
>
>    while not((this_net = nil) or 
>              ((this_net^.plusminus = net.plusminus) and
>               (this_net^.net_name  = net.net_name))) do
>
>Looks like it tried evaluating the expression after the 'or' when the pointer 
>was nil.  I changed it to this:
>
>    while ((this_net <> nil) and 
>       not((this_net^.plusminus = net.plusminus) and 
>           (this_net^.net_name  = net.net_name))) do
>

Pascal does NOT guarantee short-circuit evaluation of Boolean expression
in an IF statement as C does.  You MUST use the second form at all times
to avoid the possibility of attempted to dereference a nil pointer.

See "Domain Pascal Language Reference", Chapter 4 "Code", p4-93 which
talks about the IF statement.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 Christopher T. Beierl  Internet: beierl_c@apollo.HP.COM;beierl_c@apollo.com
 Apollo Computer, Inc.      UUCP: {mit-eddie,yale,uw-beaver}!apollo!beierl_c
 A Subsidiary of Hewlett-Packard                       Phone: (508) 256-6600

rehrauer@apollo.HP.COM (Steve Rehrauer) (11/15/90)

In article <4e00f7c8.20b6d@apollo.HP.COM> rehrauer@apollo.HP.COM (Steve Rehrauer) writes:
>For example, this Pascal snippet:
>
>   IF ( ( ptr = NIL ) OR ELSE ( ptr^.intval <> 0 ) ) THEN
>
>is intuitively the same as (but more compact to write than!):
>
>   IF ( ptr <> NIL ) THEN
>      IF ( ptr^.intval <> 0 ) THEN

Oh, sigh -- let me try again.  This:

   IF ( ( ptr = NIL ) OR ELSE ( ptr^.intval <> 0 ) ) THEN
      { statements }

is the same as this:

   IF ( ptr = NIL ) THEN
      { statements }
   ELSE IF ( ptr^.intval <> 0 ) THEN
      { statements }

Read the manual for details.  (Do what I mean, not what I say. :)
--
"I feel lightheaded, Sam.  I think my      | (Steve) rehrauer@apollo.hp.com
 brain is out of air.  But it's kind of    | The Apollo Systems Division of
 a neat feeling..." -- Freelance Police    |       Hewlett-Packard