Close

99 Bottles of Recursive Pascal Beer on Humpty Dumpty's Wall

A project log for Rubidium 2.0

This is an all in one spectrum and logic analyzer, robotics control platform, and modular synthesizer with audio in and sheet music out!

glgormanglgorman 10/21/2021 at 11:230 Comments

As you probably know time travel is probably impossible, at least for practical purpose, no matter what Calvin Klein says.  Neither are you likely to be unbreaking an egg anytime soon, no matter how hard all of the kings horses and all of the kings men may hope for.  On the other hand, as far as tricking  a C++ compiler into chowing down on Pascal programs with "only" minimal modification; well that one might not nearly be as difficult as inventing time travel or warp drive might actually turn out to be in practice.  Now one of the problems with getting a C++ compiler to chow down on Pascal source is the fact that Pascal allows for so called "nested procedures or functions" which means that PROCEDURE A can have PROCEDURES B and C declared inside A, and also maybe PROCEDURES D and E declared inside A in such a way that A can call B which calls C, which then calls B over and over again recursively, which might be used create a "wall object" and 99 "beer" objects using recursion on the stack (if so desired) through recursion, and then have B or C call A again in a re-entrant fashion, so that A can now call procedures D and E, when then operate recursively to pull down some of the bottles and pass them around., at least until an "out of beer exception occurs."  Not that you can't do that in C++, but can it be done with DEEPLY nested and mutually recursive functions - and in such a way that when you look at the source code it looks like a Pascal program has been converted to use nested namespaces - which is allowed - just not nested functions.  Now let's make it even harder, AND not add any new passed parameters to the original functions, since one of the nice features about Pascal nested procedures, is that the inner nested procedures have access to the outer procedure's local variables, that is to say without having to de-reference any passed pointers, and then otherwise use a WITH statement, (which would be "evil", and which also doesn't exist in C++.

Now to throw another log on the fire, although a template based on 99 bottles of recursive Pascal beer might be useful for implementing fun things like editors with 99 levels of undo, or Tiny-OS kernels that support up to 99 or more concurrent processes; there are actually even bigger fish to fry.

Even bigger fish to fry?  How about the fact that Pascal allows for some very nasty, even though it is not quite Halloween yet, yet here is some code that looks like it just might have come straight out of some "sequel that never got made to the Rocky Horror Picture Show" like data structures.  Like this one from the Pascal source of UCSD Pascal: (So yeah, "Let's do the time warp again!")

IDENTIFIER = RECORD
    NAME: ALPHA; LLINK, RLINK: CTP;
        IDTYPE: STP; NEXT: CTP;
            CASE KLASS: IDCLASS OF
                KONST: (VALUES: VALU);
                FORMALVARS,
                ACTUALVARS: (VLEV: LEVRANGE;
                VADDR: ADDRRANGE;
                CASE BOOLEAN OF
                    TRUE: (PUBLIC: BOOLEAN));
                      FIELD: (FLDADDR: ADDRRANGE;
                        CASE FISPACKD: BOOLEAN OF
                    TRUE: (FLDRBIT,FLDWIDTH: BITRANGE));
                      PROC,
                      FUNC:  (CASE PFDECKIND: DECLKIND OF
                        SPECIAL:  (KEY: INTEGER);
                        STANDARD: (CSPNUM: INTEGER);
                        DECLARED: (PFLEV: LEVRANGE;
                        PFNAME: PROCRANGE;
                        PFSEG: SEGRANGE;
                              CASE PFKIND: IDKIND OF
                                  ACTUAL: (LOCALLC: ADDRRANGE;
                                  FORWDECL: BOOLEAN;
                                  EXTURNAL: BOOLEAN;
                                  INSCOPE: BOOLEAN;
                              CASE BOOLEAN OF
                                  TRUE: (IMPORTED:BOOLEAN))));
                    MODULE: (SEGID: INTEGER)
                    END;

 Now I know why they call it the "Dragon Book", but this is another story.  Still does this mean that the compiler has to use mutually recursive nested functions in order to correctly parse variant record types which themselves might contain a whole zoo of variant sub records, which themselves contain nested variant records? 

 And in other news, using not much more than "stone knives and bear skins" I have managed to convert about 4000+ lines of UCSD Pascal to C++, while "somehow" finding a way to allow it to at least appear that I am converting some highly nested and potentially mutually recursive procedures into what looks like mutually nested recursion in C++, by using "only" namespaces (and perhaps some snake oil along with the right source of smoke and mirrors in other places like my earlier Pascal style in C++ WRITELN  hack).

Don't believe me?  Well, it does compile, so far up though and including the DECLARATIONPART and UNITPART segments.  Once BODY is done I will have a compiler that will be able to be run on the Propeller or the Arduino, among other things, maybe even a NOR computer.  Check out "declaration1.cpp" if you don't believe it!  Warning!  Not only is this software "GNU" and without warranty, along with any other applicable restrictions, I can pretty much guarantee that not only does it have bugs, but it probably has a few more bugs that it didn't have in it when first released in 1979 or thereabouts.    

Discussions