[comp.lang.pascal] Pointer problem ?

frisk@askja.UUCP (Fridrik Skulason) (07/23/87)

Can anyone tell me if this program fragment is supposed to compile or not.
Turbo Pascal refuses to compile it, but VAX/VMS Pascal does.

program t;
type 
  p1 = ^p1;
  p2 = ^p1;
  p3 = ^p2;

var p : p1;
    r : p3;
begin
    p := r;
end.
-- 
Fridrik Skulason  Univ. of Iceland, Computing Center
       UUCP  ...mcvax!hafro!askja!frisk                BIX  frisk

                     "This line intentionally left blank"

ayac071@ut-ngp.UUCP (William T. Douglass) (07/23/87)

In article <254@askja.UUCP> frisk@askja.UUCP (Fridrik Skulason) writes:
>Can anyone tell me if this program fragment is supposed to compile or not.
>Turbo Pascal refuses to compile it, but VAX/VMS Pascal does.
>
>program t;
>type 
>  p1 = ^p1;
>  p2 = ^p1;
>  p3 = ^p2;
>
>var p : p1;
>    r : p3;
>begin
>    p := r;
>end.
>-- 
>Fridrik Skulason  Univ. of Iceland, Computing Center
>       UUCP  ...mcvax!hafro!askja!frisk                BIX  frisk

Since p1 is of type "pointer to p1" while p3 is type "pointer to p2", I would
guess that the compiler is justified in rejecting the assignment.  Even though
they point to the same object, the language defines them as differing type,
and prevents the assignment.

I'm curious about you need for "seperate but equal" types here.  Is this purely
a theoritical discussion, or is the above construct necessary in some way.
Obviously, there are ways around this barrier in Turbo Pascal, if the problem
is a real-world one.

Hope I've not just been stating the obvious.

Bill Douglass
ayac071@ngp.UUCP (or whatever)

philip@axis.fr (Philip Peake) (07/24/87)

In article <254@askja.UUCP>, frisk@askja.UUCP (Fridrik Skulason) writes:
| Can anyone tell me if this program fragment is supposed to compile or not.
| Turbo Pascal refuses to compile it, but VAX/VMS Pascal does.
| 
| program t;
| type 
|   p1 = ^p1;
|   p2 = ^p1;
|   p3 = ^p2;
| 
| var p : p1;
|     r : p3;
| begin
|     p := r;
| end.

With a REAL pascal compiler this should NOT compile.
P1, p2 ans p3 are different types. The whole idea of typing things is to
catch errors in programming. It may be obvious to you and to the compiler
that these things are in fact identical, but if that is so LOGICALY
within your program, why did you give them different types.

I suggest that you ask DEC to mend their compiler.

Philip

dyck@sfu_halley.cs.sfu (07/25/87)

>Can anyone tell me if this program fragment is supposed to compile or not.
>             |
>program t;   | Even though the first two type definitions have the same
>type         | RHS, section 6.4.1 of the Standard says that each
>  p1 = ^p1;  | occurrence of a new-type (e.g. each of the two 
>  p2 = ^p1;  | occurrences of ^p1) shall denote a type that is distinct
>  p3 = ^p2;  | from [the type denoted by] any other new-type. So p1 and
>var p : p1;  | p2 (and p3) denote distinct types.
>    r : p3;  | The assignment-compatibility rules (section 6.4.6) as 
>begin        | applied to pointer-types require that in the asmt-stmt,
>    p := r;  | the variables denoted by p and r possess the same type.
>end.         | They don't, so the program violates the Standard.
>--           |
>Fridrik Skulason  Univ. of Iceland, Computing Center
>       UUCP  ...mcvax!hafro!askja!frisk                BIX  frisk
              |
	      | Mike Dyck, Simon Fraser University, BC
	      | 

ken@rochester.arpa (Ken Yap) (07/25/87)

Nobody has pointed out that the declaration

type
	p1 = ^p1;

introduces a type which can have nothing done to it except being
assigned nil and compared with nil. It is this "loop" which may the
cause of the compiler bug.

	Ken

gore@nucsrl.UUCP (Jacob Gore) (07/26/87)

/ nucsrl:comp.lang.pascal / dyck@sfu_halley.cs.sfu / 12:57 am  Jul 25, 1987 /
>program t;   | Even though the first two type definitions have the same
>type         | RHS, section 6.4.1 of the Standard says that each
>  p1 = ^p1;  | occurrence of a new-type (e.g. each of the two 
>  p2 = ^p1;  | occurrences of ^p1) shall denote a type that is distinct
>  p3 = ^p2;  | from [the type denoted by] any other new-type. So p1 and
>var p : p1;  | p2 (and p3) denote distinct types.

When was "the Standard" established?  I don't think Wirth initially specified
whether Pascal used structure-compatible or name-compatible types. 

I am well (and painfully) aware that the VMS Pascal compiler uses
structure-compatibility, but I would not be surprised if that compiler
predates "the Standard."  They can't "fix" it now, since they need to maintain
backward compatibility with previous versions of the compiler.  To many older 
programs would be broken if they did.

Jacob Gore				gore@EECS.NWU.Edu
Northwestern Univ., EECS Dept.		{gargoyle,ihnp4,chinet}!nucsrl!gore

khayo@MATH.UCLA.EDU (07/26/87)

=In article <254@askja.UUCP>, frisk@askja.UUCP (Fridrik Skulason) writes:
= Can anyone tell me if this program fragment is supposed to compile or not.
= Turbo Pascal refuses to compile it, but VAX/VMS Pascal does.
= 
= program t;
= type 
=   p1 = ^p1;
=   p2 = ^p1;
=   p3 = ^p2;
= 
= var p : p1;
=     r : p3;
= begin
=     p := r;
= end.
=
   I somehow fail to see the problem. The statement "p1 = ^p1" is an
obvious attempt at driving the compiler nuts - like saying that "zero"
equals "the set consisting of zero". If your compiler doesn't protest,
get it fixed (I don't know about other languages, but in Pascal this
*definitely* shouldn't be allowed, the whole idea of the language being
to avoid illogical tricks - whether you agree with the philosophy or not).
   Even if the first declaration is somehow (mis?) understood, the third
one would make "r" a *handle* (or even a *pointer to a handle* {!!!}) to p1,
and how can you expect p and r to be compatible is beyond me.
   Am I being totally fer sure stupid???
                                               Eric

ragerj@nucsrl.UUCP (John Rager) (07/26/87)

Jacob Gore comments:

>When was "the Standard" established?  ... I would not be surprised if that 
>compiler predates "the Standard."  

The ISO standard dates from 1980.  The VMS Pascal compiler is almost
certainly older than that.

>I don't think Wirth initially specified
>whether Pascal used structure-compatible or name-compatible types. 

Just for the interested, I quote Wirth (from the second edition of the
Report, p. 149), talking about assignment:

The variable (or the function) and the expression must be of identical type,
with the following exceptions being permitted:

1. the type of the variable is real, and the type of the expression is
integer or a subrange thereof.

2. the type of the expression is a subrange of the type of the variable, 
or vice-versa.

John Rager				ragerj@EECS.NWU.Edu
Northwestern Univ., EECS Dept.		{gargoyle,ihnp4,chinet}!nucsrl!ragerj

abcscnuk@csun.UUCP (Naoto Kimura) (07/26/87)

In article <254@askja.UUCP> frisk@askja.UUCP (Fridrik Skulason) writes:
>Can anyone tell me if this program fragment is supposed to compile or not.
>Turbo Pascal refuses to compile it, but VAX/VMS Pascal does.
>
>program t;
>type 
>  p1 = ^p1;
>  p2 = ^p1;
>  p3 = ^p2;
>
>var p : p1;
>    r : p3;
>begin
>    p := r;
>end.
>-- 
>Fridrik Skulason  Univ. of Iceland, Computing Center
>       UUCP  ...mcvax!hafro!askja!frisk                BIX  frisk
>
>                     "This line intentionally left blank"

    The variables "p" and "r" are of different types.  "P" is a pointer
to an object of type "p1" while "r" is a a pointer to an object of type
"p2", which is a pointer to an object of type "p1."  Even though "p" and
"r" are both pointer to something, they won't be the same, because they
point to different types of objects ( ^p1 <> ^^p1 ).  If you want to get
pointers to an arbitrary data object, you'll have to fiddle around with
variant record types:

--
	program foo;
	type
	    foo : record
		  case 1..5 of
		    1 :(intptr  : ^integer);
		    2 :(charptr : ^char);
		    3 :(realptr : ^real);
		    4 :(boolptr : ^boolean);
		    5 :(fooptr  : ^foo)
		  end;
	var
	    p,
	    r  : foo;
	    s  : ^char;
	begin
	    new(s);
	    s^ := 'a';
	    p.charptr := s;
	    p.intptr := q.intptr;
	end.
--
    There is a problem with using things like this, alignment, since
char, boolean, real, integer, etc. will have different storage
requirements and restrictions, especially on word addressed machines.
--
                //-n-\\					Naoto Kimura
        _____---=======---_____				(csun!abcscnuk)
    ====____\   /.. ..\   /____====
  //         ---\__O__/---        \\	Enterprise... Surrender or we'll
  \_\                            /_/	send back your *&^$% tribbles !!

tainter@ihlpg.ATT.COM (Tainter) (07/27/87)

> When was "the Standard" established?  I don't think Wirth initially specified
| whether Pascal used structure-compatible or name-compatible types. 
| 
| I am well (and painfully) aware that the VMS Pascal compiler uses
| structure-compatibility, but I would not be surprised if that compiler
| predates "the Standard."  They can't "fix" it now, since they need to maintain
| backward compatibility with previous versions of the compiler.  To many older 
| programs would be broken if they did.
> Jacob Gore				gore@EECS.NWU.Edu

You will also find that UCSD Pascal and its derivatives (i.e. HP Pascal,
Turbo Pascal) use structure equivalence rather than name equivalence.

--j.a.tainter

mdella@polyslo.UUCP (Marcos R. Della) (07/28/87)

Another problem that you might find is that in your type
statment, you have p1 = ^p1; This is valid, but makes for difficult
referencing as a pointer points to itself... etc... This allows for
no outside references other than  to the created opointers of p1
and everything pointing to itself...
 
Does that make sense?


-- 
    ...!lll-crg ---> !csustan --\                    | Whatever I said doesn't
...trwrb!csla34 --<              >->!polyslo!mdella  | mean diddly as I forgot
      ...!ihnp4 ---> !csun -----/                    | it even before finishing
                  ...!dmsd ----/                     | typing it all out!!!

tgl@zog.cs.cmu.edu (Tom Lane) (07/31/87)

The people who knew what they were talking about on this subject haven't
made themselves very clear, so I'll have a go at it.  Hit 'n' if you're
bored...

The issue here is whether two Pascal types are assignment compatible.
There are two different rules for determining compatibility, called "name
equivalence" and "structure equivalence".  In the original example (which
was simplified to the point of uselessness), we had:

	type 
	  p1 = ^p1;
	  p2 = ^p1;
	  p3 = ^p2;

Under the "structure equivalence" rule, type p2 is "the same as" p1,
because both are pointers to the same thing.  Then by induction, p3 is
also "the same as" p1.

Under "name equivalence", all three types are distinct.  You can only
get equivalence of two types under this rule by saying
	type p2 = p1;
i.e. only by equating the second type to the name of the first.

Hence the example program compiles under structure equivalence and is
rejected under name equivalence; there's no compiler bug involved.

There are some exceptions dealing with subranges and real-to-integer
conversion, but that's the basic idea.

Now, why have you got one compiler that enforces name equivalence and one
that enforces structure equivalence?  Basically, because Wirth screwed up.
His Revised Report on Pascal was a bit vague, but SPECIFIED name
equivalence.  (I think... it depends on what you assume "identical type"
means.)  But Wirth's original, widely distributed Portable P-compiler
IMPLEMENTED structure equivalence.  Nearly all its descendants, including
UCSD Pascal, Turbo Pascal, and most flavors of Pascal for the Macintosh,
still contain that code.  Various other people wrote compilers from scratch,
following the Report.  Most of them implemented name equivalence; that's
what you get if you use the simplest meaning of "identical type" within the
compiler's symbol table.

The new ISO Standard clearly specifies name equivalence.  Aside from being a
whole lot easier to implement, it is stricter, hence "safer" in the view of
strong-typing-makes-better-programs proponents.  (I tend to agree, but there
is room for argument.)  I believe Wirth himself argued for name equivalence
in the Standard, blithely ignoring his own large contribution to the existence
of the other interpretation.

So there you have it.  The compilers that have structure equivalence aren't
likely to change, because of all the existing programs they'd break.  Name
equivalence is officially sanctioned, so *those* compilers aren't going to
change either.  The people who lose are the ones who try to compile
structure-equivalence-needing programs with name-equivalence-enforcing
compilers.  I presume the original question came from someone who got bitten
that way...

About the only thing you can do is to make sure your own programs are
written to the name-equivalence standard; then they'll compile on both
kinds of compilers.

There's a moral here somewhere about the dangers of defining something
in two ways (in this case, Pascal was defined by both a book and a
widely-given-away compiler).  By the time you notice the discrepancies,
it's too late to give up EITHER definition without inflicting pain.

				tom lane
-----
ARPA: lane@ZOG.CS.CMU.EDU
UUCP: ...!seismo!zog.cs.cmu.edu!lane
BITNET: lane%zog.cs.cmu.edu@cmuccvma