• Michael Brutsch (unregistered)

    I spent 10 years working in M(UMPS), and all I can say is, Thank FSM for Perl! It amazes me that Cache still exists.

  • DOA (unregistered)

    The horror... the horror...

  • (cs)

    Wow. What a trip down memory lane.

    OK, I'm not a regular visitor to WTF, so I just encountered this one, but I have to tell my experience with MUMPS (which also brings in PL/1 and microcode).

    Back in the mid '80's, I was hired by a major hospital information system vendor to work on their MUMPS interpreter. I had lots of experience writing interpreters, but I hadn't actually encountered MUMPS before - I just knew that it was common in medical infomatics.

    So, I helped write the MUMPS interpreter. What was the language used?

    Why, PL/1, of course. What else would you write an interpreter in? PL/1 is what you would get if you tried to make C look like COBOL (except it predated C). For instance, there was no bitwise AND, OR, XOR or NOT functions. Instead, there was the BOOL operator (I think it was - it's been over 20 years) that took a 4 bit argument that you used on two (or one, for NOT) arguments. That gave you 16 DIFFERENT boolean possibilities. Think about that for a second - how many different bitwise boolean operations can you thing of? I'll bet it's less than 16.

    But I digress.

    First, however, there is another digression. All of this was done on Data General MV20000 superminis. The PDP-11 was the most elegant 16-bit architecture ever created, with 16 registers that were almost completely orthogonal, where every operation could do the same thing in memory, regardless of which register was used. DG had the Nova architecture which had 4 registers, each of which was special purpose. Ugh.

    When minis first went 32 bit, DEC dropped the PDP-11 and created the VAX, a bloated monstrosity that drove people into the ARMs of RISC (that was an obscure inside joke, folks). DG, on the other hand, kept the Nova architecture for their superminis.

    That meant there were FOUR (count them) special purpose registers. You actually spent more time moving stuff from one register to another than in actually doing operations on the data.

    Under the hood, however, there were sixteen 32 bit registers available. But only to microcode.

    If you ever read Soul Of The New Machine, you might remember the Microkids, programmers who worked on microcode until they got completely burnt out and became goat farmers. I wasn't there at the creation of the MV series, but I did come to think seriously about what a career with milk goats might be like after writing code in four different microcode architectures (two Vax variations, the DG MV20K, and some custom Fairchild stuff).

    To develop the MUMPS compiler (I'm still getting to that), I would write a wrapper in PL/1, to invoke an assembly language routine, that would call the microcode that did the dirty work. Also, the symbolic debugger didn't show any addresses and the absolute debugger didn't show any symbols.

    So my development workflow went like this. I wrote the code and the carefully checked it by hand before firing off a very elaborate shell script. This script would compile, link, and load the symbolic debugger, which would load the absolute debugger, which would load the microcode debugger, and then load the actual object code. This process took about 45 minutes.

    And then there was MUMPS.

    OMG, absolutely the WORST programming language ever conceived. The outline in the story above gives you a flavor, but I can assure you there is a LOT more.

    I finally decided I had to bail when some Systems Analyst types came to visit me in my office. They had written an automatic program generator that churned out MUMPS code, but they had a bug somewhere in their generator. They had narrowed it down to a single line of code. Would I help them debug it?

    Sure, I replied foolishly.

    And they thumped down about 1/2 inch of fanfold paper.

    Which was for ONE line of code. ~32K of source code on one line.

    But it was better than that.

    You see, each operator can be abbreviated to one or two characters. And each operator has a default operand. So if the first character is followed by a single space followed by a single character followed by a space followed by two spaces followed by another character (and so on), that is a command followed by a function followed by a command that invoked its default function followed by a command (and so on).

    To make this more interesting, all control structures have to begin and end on the same line (except for GOTO). Of course, in order for this schema to work, the lines can be of unlimited length.

    Which is how I ended up with 1/2" of fanfold paper that was printed 80 columns wide with one and two character with one and two spaces going on and on and on and on.

    And the two Systems Analysts both sat down and waited for me to read the 32K of that single line of code and tell me where the bug was.

    I gave notice shortly thereafter.

    Ya know, I just don't get programming assignments like that any more.

    Thanks for the space to tell the story. As an Olde Pharte in this industry, there are fewer and fewer folks left to tell stories like this to. Most just go, "Huh?"

  • JamesNSC (unregistered)

    Someone finally knows my pain. A had the "pleasure" of "securing" M code for HIPAA compliancy - that's two years of my life I'll never get back. The one line of M that keeps haunting me is dubious in it's simplicity, it was simply:

    d d d

  • NOSMADAR (unregistered)

    Code can be written that is hard to read and equally dificult to maintain in any langaage in existence. And, with the proper discipline and standards, code which is maintainable and easy to read can also be written in any language in existence...including M.

    I work with M. We have many installations that are up and running 24/7 that stay up and running 24/7.

    One of the big advantages of M is that it only requires small amount of memory per process. When I moved from my previous employer to the one I"m with now, we had a VAXcluster running software written in COBOL that could support at most 120 or so concurrent users. But the same cluster could support 4 - 5 times as many M processes.

    I will grant you it takes a while to read. But most of the examples I've seen posted here or excerpted from Wikipedia are just examples of how NOT to program in M. With proper use of function calls and structured design, it is possible to create robust code in M. What you do need though, is really good source control, which is something that was probably lacking in most shops up to the mid '90s.

    Actually the weirdest thing about M is the heirarchical database struture. So it is a challenge of adding the SQL based relational layer on top of that, but it does work. And applications can be built purely in the relational model.

  • (cs) in reply to RonBraithwaite
    RonBraithwaite:
    For instance, there was no bitwise AND, OR, XOR or NOT functions. Instead, there was the BOOL operator (I think it was - it's been over 20 years) that took a 4 bit argument that you used on two (or one, for NOT) arguments. That gave you *16* DIFFERENT boolean possibilities. Think about that for a second - how many different bitwise boolean operations can you thing of? I'll bet it's less than 16.
    For two binary input operands there are 4 possible input values (00, 01, 10 and 11). For each input value(s) there are two possible results (0 and 1). That's 2^4 = 16 possible operations.

    Did I miss something?

  • Andy (unregistered)

    My first full-time gig was working with the world's only real-time multitasking APL system... For those who don't know, APL uses a non-ascii character set, and our system even stripped out comments. Genuinely write-only code!

Leave a comment on “Classics Week: A Case of the MUMPS”

Log In or post as a guest

Replying to comment #:

« Return to Article