It appears that both legacy Pascal compilers I have access to (for the BESM-6) contain a bug: they would happily produce code for

program test(output);(* may have to omit (output) depending on the platform *)
function f: integer; (* entering the function sets R2 as the frame pointer *)
begin f := 7 end;    (* assigning 7 to 3(R2) - the value return location *)
begin f := 11 end.   (* assigning 11 to 3(R2), where R2 has not been initialized yet *)

Both compilers were derivations from one CDC 6600 version or another, up to the data structures and the order of the subroutines. As the bug is in the machine-independent part, which logic would be transcribed unchanged, I suspect that it would exist in all Pascal implementations derived directly from the same CDC 6600 source by bootstrapping.

Could anyone please verify that on a CDC 6600 emulator, if one exists, or using a Pascal compiler known to be a port of the original?


Newer Pascal compilers written in C using YACC do error out on the test case above.

Free Pascal complains, on line 4, Error: Argument cannot be assigned to (why "Argument", though?).

UCB Pascal on BSD 2.11 is more lucid, saying function f found where variable required.

One other I could find online, Turbo Pascal, however, fails with some kind of an internal error: Error: can't cast from 70 to 76 ("11", line 4).

  • 1
    Compare the source code of the func branch of the selector routine in the P2 compiler (search for "IMPL. RELAT. ADDR. OF FCT. RESULT" to find the relevant line) and in the P4 compiler. In the latter there is an error check complaining if a function name is assigned to outside its body. (In adding the check, an odd begin-end pair was left, as noted in Daniels and Pemberton's book about P4). – texdr.aft Jun 3 at 0:29
  • 2
    The error code displayed by P4 is 177 ("You may only assign to the identifier of a function in the body of that function", see homepages.cwi.nl/~steven/pascal/book/…), which was not included in the list of error codes at the end of the Pascal user manual, so I would propose that the answer to your question is yes. – texdr.aft Jun 3 at 0:35
  • 1
    @texdr.aft I was just a few minutes behind you; having run that experiment myself after spending some time fixing the C source of P4. The high error code was a hint. But it would be instructive to see an independent compiler with the bug in action. – Leo B. Jun 3 at 0:49
  • 1
    (1) Yes, homepages.cwi.nl/~steven/pascal/p4c.tar.gz (2) Right; Although judging by the timeline (the first BESM-6 compiler was released in 1976), they could be based on the P-series rather than the original. – Leo B. Jun 3 at 0:58
  • 1
    I found an explanation for the strange Turbo Pascal error: news.ycombinator.com/item?id=6573092 – texdr.aft Jun 5 at 8:02

If the compilers you have were based on the P-series, then I believe that there was indeed a bug.

In the P-series compilers after P2, the destination of an assignment is determined by a routine named selector, which branches on the klass field of fcp, a variable that holds information about a relevant identifier. When the klass is func, i.e., when the identifier is the name of a function, P2 does this:

        DPLMT := 0   (*IMPL. RELAT. ADDR. OF FCT. RESULT*)

There is an assumption here that an assignment to a function identifier will happen only within the function's body, but no explicit check. In P4, this bit of code was changed to

if pfdeckind = standard then
  begin error(150); typtr := nil end
    if pfkind = formal then error(151)
      if (pflev+1<>level)or(fprocp<>fcp) then error(177);
      begin access := drct; vlevel := pflev + 1;
        dplmt := 0   (*impl. relat. addr. of fct. result*)

Here, pflev is a field of fcp, representing the level of nesting at which fcp was declared; level is a global variable holding the current depth of nesting; fprocp is a parameter of block, which is non-nil if the block is the body of a function or procedure. Thus the newly-added line ensures that we are (1) in the body of a function and (2) allowed to perform the assignment. Error 177 is new to P4, and means

You may only assign to the identifier of a function in the body of that function.

There are other early compilers whose source code survives, which were the progenitors of the P-series compilers; none of them, except for the 1984 version, seem to include the check for assignment validity.

You might have noticed the strange begin and end in the P4 excerpt. This was also pointed out by Pemberton and Daniels (the third item in the Notes section below). The effect is that code for the assignment is generated, even though it is erroneous; presumably there is an else missing.

  • 1
    One compiler is most likely based on a P-series compiler or their direct predecessor. After decompilation, some scalar constant names and subroutine names were correlated with a P-series source. The overall code structure matches closely. However, contents of the analog of the "selector" routine (called "parseLval", line 5030) based on relative location and overall function, diverge substantially. – Leo B. Jun 3 at 6:30
  • 1
    The other compiler, not yet restored to good readability, looks much different: there are no individual token scalars; there is just one all-encompassing record type "identifier" for all named objects; expression trees are not constructed, instruction chains for subexpressions are merged during recursive descent, etc. – Leo B. Jun 3 at 6:31
  • 1
    I'd like to attract your attention to another question of mine about Pascal implementation specifics: retrocomputing.stackexchange.com/q/10976/4025 - here the P-series are of no help as a reference because they do not support procedural parameters at all. – Leo B. Jun 3 at 8:17
  • 1
    @LeoB. The best way to answer that question, as well as your previous one about in, is probably to go through the "implementation notes" sections of Pascal Newsletter issues. – texdr.aft Jun 3 at 21:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.