Incidentally, Wirth developed a language called ā€˜Algol 68 Sucks’ (actually it is called Pascal) and the United Stated Department of Defense funded development of another language called ā€˜Algol 68 Sucks’ (actually it is called Ada).

Neither of these languages sucks.

Pascal as originally developed is a whole program only language, mind you. Not a separate compiler. You must understand that to understand the language. Everything is nested within ā€˜program’.

It is with Modula that things get more serious in that line of development. (Not with Object Pascal aka Turbo Pascal, in which was written the worst computer code I have ever seen or worked on.)

I am fond of safety but also of simplicity.

It must be admitted, for instance, that ATS (any version of it) is a complicated language. It is much simpler than an Adriaan van Wijngaarden would have made it. It surely is simpler and much more practical than, say, Agda (which is a hugely moving target, anyway), which attempts to be ā€˜theoretical’ whilst ATS does not.

So we want ATS-like safety but we also want simplicity. Can that be done with an ā€˜orthogonal’ language and Pratt parsing?

Note, for instance, the problem of buffer overruns. But there is another problem with arrays that is addressed by ATS, which is NOT addressed widely otherwise: aliasing. The problem of entries in arrays being aliased, because it is easy to refer to an array in two place.

ATS solves both problems by making an array a linear type that is typechecked via a ā€˜view’. A view has a particular length in entry types. The entry type can be changed, and so the length with that, but let us ignore that.

A view can also be split in mutually exclusive twos or threes (or more if need be). Whilst split, it becomes that many arrays. Then these must be joined together again at some time, because the types are linear. They must be consumed.

These are all typechecking operations, but they must be written by the programmer or put in subprograms.

Thus, to read or write an array entry, you must split the array into two or three parts and also somehow transform the one entry into an ordinary variable.

Then you have to join it all back together.

But none of this steals from your code speed, because it is all typechecking code. So you end up with safe array access that requires no runtime bounds checking!

The question is, can we achieve something similar by being ā€˜orthogonal’ with a Pratt parser? That is, can we do it by adjusting the SYNTAX of the language?

How about if we make fundamental syntactic operations on arrays be splitting and joining?

We can also make assignment and evaluation be entry-wise in the manner of Fortran and Matlab, rather than require it be reduced to a proper variable as in ATS. This way we still avoid the aliasing problem.

For example, if we do a quicksort, the two parts of the array are still fed separately to the two parts of the algorithm. Neither subprogram call can touch the other subprogram call’s subarray.

But we have done it with the Pratt parser, so have done it ā€˜orthogonally’, not via semantics. And we have done it without writing an unreadable report.

Mind you, this requires that splitting an array CONSUME the original array, and that the array must be rejoined if it is to be recovered.

We do not have to enforce linear typing, only that splitting and joining be destructive operations.

But that’s just control of your symbol tables and such. That’s just more syntax. You could probably even go full linear through syntax.

It likely does mean you aren’t going to be happy with the classic ā€˜orthogonal’ syntax example, if it should appear as an initialization:

(if b then x else y fi) := 3

Still, if assignment to an initialized variable implies consumption of the previous value, then it is okay if not an initialization.

Oh, let’s write that in Dijkstra’s nondeterministic if-fi:

(if b => x | ~b => y fi) := 3

because let us say we want to use that, if only to introduce a new generation of programmers to it.

The big difference here is there is no sequence of operations. The code takes any one of the branches in the if-fi, it is not specified. The only thing that decides which branch is actually taken is the guard.

(I read stuff here in the Fediverse that makes me think, ā€˜These people have no idea what ā€œnondeterminismā€ and ā€œdeterminismā€ even mean’.)

Of course the compiler could have decided ~b is the negation of b and so produced the same code as ā€˜if x then x else y fi’. But that is for the compiler writer to decide.

Meanwhile, the programmer actually has a simpler situation with which to do proofs. To do proofs with the earlier, non-Dijkstra formulation, one first usually throws away part of the information and mentally transforms to the Dijkstra formulation.

Also, suppose I left out the ~b guard. Then there would be no specified operation for if b were false. There is no fallthrough. The program is erroneous and presumably will terminate with an error message.

The program would have been erroneous in this case, anyway, because you cannot assign to ā€˜nothing’. But the principle is more general.

Absence of a guard is a common cause of nondeterminism in the Mercury language, though in Mercury I think guards are gone through in sequence.

Obviously, if the guards cover all the cases and are mutually exclusive, then the program is ACTUALLY deterministic. And a compiler may be able to confirm this.

As indeed a Mercury compiler has to be able to do, for the Mercury language, though there I believe the cases do not have to be mutually exclusive. In one’s mind, one assumes earlier tests that pass are actually excluded from later tests, and does proofs by using the Dijkstra formulation.

Strictly speaking, however, the order of the expressions is a part of the information that is not included in the proofs and yet is relevant, and bits of code that would break the proper functioning, if the order were changed, are not explicitly accounted for.

I am merely trying to make an ā€˜orthogonal’ language. I can let the program terminate with an error if there is a case left out. At least I need not REQUIRE that a program be deterministic. In fact I think it silly to REQUIRE that a program be deterministic, and most programming languages in fact do not require this.

Indeed, they are happy to let you have, for instance, a loop despite that one has failed to prove it either terminating or nonterminating.

ATS, incidentally, has but one method for proving a recursion or loop terminating, which is ā€˜termination metrics’. It involves having a typechecking variable, or a tuple of typechecking variables, move progressively towards zero without passing zero, on each iteration of the recursion or loop. It is mathematical induction mapped to counting backwards, although the counting can be by leaps and bounds (division, for instance).

ATS2 has both recursions and loops. Loops are poorly documented, tho’.

In a way it matters little, though, because recursions can be done with reference variables and so tail recursions effectively resemble loops closely. But, as I say, these can be written as loops more properly, resembling C loops, except with a lot of proof notations.

The following occurs to me:

If you start with bytes as the basic type, you can make EVERY type in the language be an array. And that includes records. For accessing a record is merely splitting of an array.

And a multidimensional array is also merely splitting of an array. This is already how it is done in Fortran. Indeed, in Fortran you can change the shape of an array simply by calling a subprogram that refers to the array differently.

In ATS things CAN be done this way in typechecking.

To some degree they are. The sizes of types and of objects are always measured in bytes. So you need to essentially treat each type as if it were an array of bytes. And you can actually make it so for typechecking, but it is a LINEAR cast, and so you must use ONLY that type until you convert it back to the original.

So it would be with our SYNTAX system. You can use only one SYNTAX at a time.

That would be different from Algol 68, I am sure. So we start with an array of 8 bytes...

And it has to be aligned on a proper boundary. Your x86 programmers forget about that! It has to be aligned on a proper boundary.

But we will merge the 8-array of BYTE into a 1-array of LONG REAL (or some such name). And that (as it really can in C) can be shorthanded as just a variable of LONG REAL. (*p and p[0] mean the same thing in C.)

A few little details that might be unusual.

Maybe we don’t use the usual ā€˜indexing by default starts at 1 (or 0) but you can change that.’ Maybe instead we just use ICON INDEXING.

This goes from 1 to n+1, with an equivalent scale from -n to 0. You would not believe how useful this is.

OTOH maybe one could say that what you devise has an equivalent scale of the kind.

Thus if you say there is a 0 to n scale, then you automatically also get -n-1 to -1. But this will not behave as Python people expect. -1 will mean ONE PAST THE END, not the last entry.

Well, so be it.

Another possibility, of course, is implicitly using modular types for indices. This might not be desirable, especially as for Fortran subprograms you often actually specify the modulus, or rather the stride for multiple dimensions. The compiler for my language might have disagreed with what you needed for Fortran.

In Fortran really all arrays are just vectors and the compiler has support for accessing them with arbitrary column major strides.

C programmers are used to row major but I think column major is perhaps very slightly better in some tiny way that obviously is unimportant and so we should forget about it.

Ada can do it either way but defaults to row major. I believe. I haven’t used arrays in Ada much.

@chemoelectric Hey, long time no online here :/ Memory wise, and as an assembly language programmer not a C programmer, I get row major. But note that this is just a cheap sequential file where rows are records. I don't remember enough of what little maths I knew to know if column major is better for those domains.

@troi I always presumed it was row major in C simply because the notation made it look like a multidimensional array was an array of arrays. In D it actually does MEAN that, in general! Same in some assembly languages, no doubt, but my experience is mostly little Z80.

Otherwise it is mostly immaterial. In Fortran or Ada there is no notational reason.

The tiny advantage of column major might be that it keeps the data of matrix columns close together. Columns usually matter more than rows do.

@troi D has C matrices, which are really just vectors with a stride-based ā€˜view’. But the default matrices in D are heap-allocated vectors of heap-allocated vectors. So it really is vectors of vectors.

I forget what such a matrix is called. I used to think it was called a dope vector, but that’s actually something else.

@troi C is very much, and on purpose, like assembly language programming. It was of course a substitute for using PDP-11 assembly language, in its early main use.

(On the PRIME they used FORTRAN in a similar way! Which I can understand, because I used FORTRAN for minor systems programming on the TRS-80. Older versions and standards of Fortran let you get at the system in practically any old way. About the only thing missing is a stack for recursion! Which can be added as an extension.)

@chemoelectric I know the origin there, but the PDP-11 and later Vax systems had a beautiful "Macro" for assembly as they called it. I love the S360 -> early S390 architectures, 6809, and if I'd had more opportunity to use it, the PDP-11's assembly language. I think of C in this specific case as a step backward. (TBH, I always think C is a step backward, but that's just me).

@troi C sucked. It is just starting to be usable with C23. It still needs nested functions, for instance. GNU C has nested functions but they suck. Fortran has better nested subprograms than GNU C does, if what I have read is true.

Also I do not know why everyone things they have to use trampolines. GNAT does not use trampolines. ATS does not use trampolines for nested functions, and they nest without end, form closures, and compile to C. That’s right, they form closures.

@troi You can do a lot by lambda lifting. Someone invented lambda lifting long ago. You can handle nested functions by lambda lifting them, for instance. And you can do closures without trampolines and such by simply implicitly adding an argument.
@troi I’ve used only PDP-11 Forth assembler and only very little. It was very easy to add a definition of ā€˜SELF’ (do a recursion) to PDP-11 fig-FORTH by using the PDP-11 assembler. I did this while at someone’s home for the evening, playing with the LSI-11 machine there.
@troi I did a TINY bit of x86-64 programming for the Unicon project and discovered it was actually MUCH better than x86. AMD did a far better job IMO than Intel did.

@chemoelectric For reasons I attribute to terminology I never got into segment register addressing used in the 16 bit Intel. It should have been dead simple for someone who mastered the mainframe base-and-displacement addressing. Many years later I tried to get into the X86-64 assembly but I just don't like Intel. Big effing code museums on a chip that they can't keep track of anymore.

In my limited experience with ARM assembly I find it almost beautiful.

@troi I never mastered any of that and my worst grade in graduate school was in computer architecture class. I am dead serious about that. I’m a high level programmer, not a kernel programmer. My brain is stuck on the TRS-80, which didn’t even use the Z80 port addressing. Except that I used the port addressing for a joystick I designed and made from a minimum of parts.
@troi Oh, yes, I have only 2 credit hours in CS, but my major subject was electrical engineering. So I have graduate credits in computer architecture.
@troi But I sucked at it and made the professor frown.
@troi He won’t speak to me, anyway, for good reasons that are more personal. I let him down on account of my OCD.
@troi However, if you look at the code for CWEB, there may still be #if entry for 80286 huge model in Borland C. Take a wild guess who submitted that patch. :)
@troi The 1802 is a very interesting architecture, extremely ā€˜orthogonal’, and you can buy them on eBay. I think they are even still made by an outfit or two, because p-well CMOS is unusual and is radiation resistant.
@troi It is just the sort of thing you would expect from old RCA: dirt simple and hard as nails against radiation.
@troi But we had their 1802-based video game system and it was a dog. :) You could get those at giveaway prices.
@chemoelectric Yeah, I think I've seen those. Your later comment reminds me of (poorly remembering the phrasing) that the Voyager probes weren't built with an "estimated life", the were just built to keep on working.

@troi If I try to use the terminology of lifespans, the people who are technically trained in that stuff will choose either to be polite or to be assholes and they usually choose to be the latter. So I will not even BOTHER to try to come up with a technical term! It does not matter. Whatever estimate they come up with is WRONG. It is usually based on conventional statistics, which is just a bunch of hooey.

Truly, the field of statistics is a bunch of ad hoc hooey that actually means nothing.

@troi I was at Cape Canaveral as a 14-year-old there with tickets to still-under-construction-WaltDWorld given freebie to my family via my great uncle who had gotten them from someone, and saw not Voyager but Viking II on the pad a few days before its launch. But in those days I am sure they were using RCA CMOS chips for a lot of the electronics. Not just the microprocessors but the gate chips as well.

Milspec chips packaged in a ceramic sandwich that looked like a Hydrox cookie.

@troi I just turned on the Artemis mission. I’m against it, though. No reason to send people outside the van Allen belt if you have no scientific research in mind that cannot be done by a machine.

An idiot congressman just called them up at the capsule. I’m going to turn it off and switch to Monty Python reruns.

@chemoelectric to the real Don? <insert "we're unworthy" Wayne's World GIF here>. That's the second time Wayne's World has come to mind this morning. I don't know if you've seen the C64 retro-resurrection project going on. I ordered one before I got that bad pathology report. I never owned one, Tandy CoCo guy here, I just like to support such efforts. Instant on BASIC was a great learning tool and Python and other REPLs just aren't the same for most people.

Oh, yeah, I mentioned Wayne's World and then drove into a ditch ... there's an unboxing video posted today I think at commodore.net or .com with Tia Carrera (Cassandra) and I guess her hubby. I did not know she had any geek tendencies.

@troi Friend in Ottawa, Ontario, had a C128 that I used when visiting. For dialup.

Friend of the family back in N.J. had retired from his work with his portfolio of patents on food additives and sold rights to use the stuff. He did his business computing on a CoCo. But I had a Model I.

My FiL had a collection of Model III and IV but by the time I knew him they had already quit working. The 4116 DRAM chips had limited lifespans, really. Probably you could simply have replaced those.

@troi I have looked at 1802 chips and thought, ā€˜Maybe’. And I just saw kits for some old microprocessor, and briefly thought, ā€˜Maybe’. But, nah.

I have had a Chinese Arduino clone kit for years, and all I have done with it is run the built in LED-blink program. And I have a Raspberry Pi Pica kit, have done even less. It’s because I am disabled. I cannot use an ordinary keyboard. Even using a laptop requires I hook up one of my DataHands to it. And they haven’t made those in years. It is a mess.

@troi Plus my hand tremor is mild but greater than average. It is the same kind of essential tremor that Katherine Hepburn had more severely and that most people have very mildly. I have it badly enough that my electrical construction work is not good.

Which made my modified TRS-80 a sloppy piece of work!

@troi I could use an Arduino to help me make machines that duplicate the results of the Aspect experiment, you know.

One of the problems with my ā€˜Stern-Gerlach’ mechanical devices, which behave like Stern-Gerlach magnets, is that they have to be fed with falling objects that are uniformly distributed in space.

It is easy to provide objects distributed according to a bell curve. There is a device with no moving parts called a Galton box, which can be used for that...

@troi But how do I drop beads in a uniform distribution?

I do not know. I am not so clever. Or more likely simply have not tinkered or done semi-geometric calculations enough, because disabled both physically and mentally, and for lack of experience in mechanical work.

But with an Arduino I could use servo motors. And I did not study control engineering—I studied digital signal processing, though never worked in the field—but I can understand moving a bead into a random position!

@troi (Having studied digital signal processing is why I am puzzled that someone like Lov Grover, who seems from the paper he wrote about his stupid algorithm to be a DSP person, could actually fall for J.S. Bell’s nonsense. My conclusion is that Stanford University gives the PhD to obedient tools, not to people who actually exercise their innate intelligence.

Grady Booch, to speak of another tool, is these days working for IBM, touting ā€˜AI’.)

@troi (See, the thing is, when you study digital signal processing, you are taught how to analyze random processes. And you DO NOT do what John S. Bell did. You are very much taught NOT TO DO what John S. Bell did.

Yet Lov Grover and some other dipshits at Bell Labs fell for it.)

@troi (Speaking of Bell Labs, in grad school we played a little with an AT&T DSP chip that you programmed like microcode. Each line of code ended with the address of the next instruction.

At the undergrad level we taught and I had been taught on a Texas Instruments DSP chip that was unusual amongst microprocessors, aside from having a ā€˜delay register’ instruction set, in that it was a Harvard architecture. That is, instructions and data on separate memory buses. Typical for DSP, though.)

@troi (End of semester I came into DSP lab with the chip programmed to change the sign of every sample. This has the effect of converting low frequencies to high and high frequencies to low.

One of the undergrad students just KNEW I would do something weird and so had brought in a cassette of the Beatles White Album. So we played that through the filter. :) )

@troi (You can do this on your computer. You need a DSP chip only to do it in real time efficiently. And this was in the 1980s, anyway.)

@troi (BTW the 2022 remix of the Beatles Revolver is absolutely splendid.

This is a random insertion to the thread. I have a special attachment to ā€˜Revolver’ because it was my first non-kids’ record. My father must have brought it home for me. I was a fan of the Beatles sing-along cartoon program for kids. So I had the bowdlerized Capitol Records version which was still the Beatles’ first really whacked out album.

The remix is in a way worse: two of the three Lennon songs Capitol removed suck.

@troi But of course it is still better to have the album restored, and also ā€˜Dr. Robert’ is now my ringtone. Plus they also remixed both sides of the ā€˜Paperback Writer’ single.

In my Grado 125 headphones you can make out every word.

In my Grado 80e headphones it still sounds almost as it used to, though. So headphone magnets really do make a difference.)