racket / algol60

Other
11 stars 14 forks source link

Internal error compiling the "man or boy" test #4

Open LiberalArtist opened 2 years ago

LiberalArtist commented 2 years ago

This program (by Donald Knuth):

begin real procedure A(k, x1, x2, x3, x4, x5);
  value k; integer k;
  real x1, x2, x3, x4, x5;
  begin real procedure B;
    begin k := k - 1;
          B := A := A(k, B, x1, x2, x3, x4)
    end;
    if k <= 0 then A := x4 + x5 else B
  end;
  printnln(A(10, 1, -1, -1, 1, 0))
end

fails to compile, producing the following error:

val: unbound identifier;
 also, no #%top syntax transformer is bound
  context...:
   #(43855 intdef) [common scopes]
  other binding...:
   local
   #(-6132 module base) #(-6129 module) [common scopes]
  common scopes...:
   #(43766 module top-level) #(43776 local) #(43777 intdef)
   #(43781 local) #(43783 intdef) #(43786 local) #(43787 intdef)
   #(43788 local) #(43793 intdef) #(43795 local) #(43796 intdef)
   #(43815 local) #(43816 intdef) #(43818 local) #(43819 intdef)
   #(43822 local) #(43823 intdef) #(43824 local) #(43829 intdef)
   #(43831 local) #(43832 intdef) #(43846 local) #(43847 intdef)
   #(43854 local) in: val
LiberalArtist commented 2 years ago

Hm, well, it does that when it's a DrRacket language. With #lang algol60, it compiles, but running it produces a different error, bad value: expected a number, got #<undefined>. DrRacket helpfully draws some arrows explaining the source of the error:

Screenshot of DrRacket

samth commented 2 years ago

Testing the #lang algol60 version, it has failed that way at least since Racket 6.5.

mflatt commented 2 years ago

The last time I looked into this, I concluded that it was due to an ambiguity in the grammar, where algol60 chooses a different parse than the example intends. I don't remember how I arrived at that conclusion, though.

bg-hub2 commented 2 months ago

You may wish to slightly modify the man-or-boy example to get it work with Racket Algol 60. The following works for me:

#lang algol60
begin
  comment
    *  Man or Boy
    *  A well-known example program, written by D. Knuth
    *  The expected value to be printed is  -67.0
    ;
  real procedure A(k, x1, x2, x3, x4, x5);
    value k; integer k;
    real x1, x2, x3, x4, x5;
  begin
    real procedure B (arg);
      Boolean arg;
    begin k := k - 1;
          B := A := A(k, B(true), x1, x2, x3, x4)
    end;
    if k <= 0 then A := x4 + x5 else  B(true)
  end;
  printnln(A(10, 1, -1, -1, 1, 0))
end

The point is that Racket seemingly fails to call the parameterless function B. In the code shown above I introduced a dummy parameter to enforce the function call.

soegaard commented 2 months ago

Since the "Man or boy test" is meant to test Algol implementation, it feels like cheating modifying it.

https://en.wikipedia.org/wiki/Man_or_boy_test


The man or boy test was proposed by computer scientist Donald Knuth as a means of evaluating implementations of the ALGOL 60 programming language. The aim of the test was to distinguish compilers that correctly implemented "recursion and non-local references" from those that did not.[1]

There are quite a few ALGOL60 translators in existence which have been designed to handle recursion and non-local references properly, and I thought perhaps a little test-program may be of value. Hence I have written the following simple routine, which may separate the man-compilers from the boy-compilers.

— Donald Knuth[2]