Had some illusions about the C language shattered recently.
I read an article from 2018 called C Is Not A Low Level Language from ACM Queue. The long and short of it is that C fails to get the programmer “close to the metal” in any meaningful sense because the abstract machine it uses doesn’t faithfully represent anything about modern computer architecture. Instead, it hides the complexity of modern instruction sets and memory arrangements beneath the abstractions which modeled hardware very well in the 1970s.
I, like most people, thought C was the best way to do hardware aside from just writing in assembly or machine code directly. I had assumed, but never checked, that as hardware advanced the work on C development was accounting for this; it appears backwards compatibility won out. This puts us in a weird position where both new hardware design and new C development are both constrained by trying to maintain compatibility with older C. In the case of hardware design, this means limiting the instruction sets of processors so they are comprehensible to C; in the case of C development this means an unyielding commitment to making people write code for the PDP-11 and relying ever more heavily on the compiler to do the real work.
The comments in the Reddit thread were, predictably, overwhelmingly focused on semantics of the high/low level dichotomy, with half claiming Assembler is also a high level language and the other half flatly rejecting the premise of the article or playing defense about how useful C is. I feel this kind of thing misses the point, because what I liked about C is that it helped me to think about what the machine was actually doing. Now I discover I wasn’t thinking about what the machine I was working on was doing so much as thinking about general types of things a machine is expected to do (have one processor, and memory, and disk, and IO). While this is clearly better than not knowing, it left what I thought was the core advantage in the wind.
I therefore did a search, assuming that if old faithful had failed someone else had surely tried to fill the niche. Nothing presented itself in my searches, which combined represent an hour or so of reading. Instead I learned something interesting about programming; it is entirely upward oriented. All the descriptions of every language billed as being either for embedded systems or as “one language to rule them all” advertised themselves entirely of what kind of high-level abstractions they gave access to.
Hence the old saw: dogs cannot look up; computer scientists cannot look down.
Reflecting on the failure of another embedded language to provide exactly what I wanted—a way to reason about what the machine was doing—I looked a little further afield. I know of two candidates for thinking about this problem from different directions.
The first is Verilog (now SystemVerilog), which is a Hardware Description Language (HDL). This does pretty much exactly what I want in terms of reasoning about the machine, but it is for design purposes: you describe how the hardware works, then verify the description does what you want it to, and then eventually it is instantiated in actual, physical hardware. I am not sure how or even if it could be used on existing hardware to learn things about the hardware, or to optimize tasks.
The second is a thing called the Legion Programming System, out of Stanford. This comes from the other end of the scale, targeting High Performance Computing (HPC) applications. It is not a programming language per se; rather it is a model for application development. It identifies the exact same concerns I have about taking into account modern (and future) computing architecture, but it focuses on supercomputers and huge clusters of servers.
So the first option is still looking up the ladder of abstraction, just from beneath where I want to be; the second option mostly looks at high-scale hardware from the side. I suppose the thing that would make me happiest is something like a Legion Programming System but for robotics instead of HPC. The thing I would most be able to take advantage of personally is basically just a C fork with a new abstract machine and compiler which better accounts for modern architecture. Given how much work “basically” is doing, this amounts to a completely different language that uses a C-like syntax, and it seems unlikely if no one is making it already.
Had some illusions about the C language shattered recently.
I read an article from 2018 called C Is Not A Low Level Language from ACM Queue. The long and short of it is that C fails to get the programmer “close to the metal” in any meaningful sense because the abstract machine it uses doesn’t faithfully represent anything about modern computer architecture. Instead, it hides the complexity of modern instruction sets and memory arrangements beneath the abstractions which modeled hardware very well in the 1970s.
I, like most people, thought C was the best way to do hardware aside from just writing in assembly or machine code directly. I had assumed, but never checked, that as hardware advanced the work on C development was accounting for this; it appears backwards compatibility won out. This puts us in a weird position where both new hardware design and new C development are both constrained by trying to maintain compatibility with older C. In the case of hardware design, this means limiting the instruction sets of processors so they are comprehensible to C; in the case of C development this means an unyielding commitment to making people write code for the PDP-11 and relying ever more heavily on the compiler to do the real work.
The comments in the Reddit thread were, predictably, overwhelmingly focused on semantics of the high/low level dichotomy, with half claiming Assembler is also a high level language and the other half flatly rejecting the premise of the article or playing defense about how useful C is. I feel this kind of thing misses the point, because what I liked about C is that it helped me to think about what the machine was actually doing. Now I discover I wasn’t thinking about what the machine I was working on was doing so much as thinking about general types of things a machine is expected to do (have one processor, and memory, and disk, and IO). While this is clearly better than not knowing, it left what I thought was the core advantage in the wind.
I therefore did a search, assuming that if old faithful had failed someone else had surely tried to fill the niche. Nothing presented itself in my searches, which combined represent an hour or so of reading. Instead I learned something interesting about programming; it is entirely upward oriented. All the descriptions of every language billed as being either for embedded systems or as “one language to rule them all” advertised themselves entirely of what kind of high-level abstractions they gave access to.
Hence the old saw: dogs cannot look up; computer scientists cannot look down.
Reflecting on the failure of another embedded language to provide exactly what I wanted—a way to reason about what the machine was doing—I looked a little further afield. I know of two candidates for thinking about this problem from different directions.
The first is Verilog (now SystemVerilog), which is a Hardware Description Language (HDL). This does pretty much exactly what I want in terms of reasoning about the machine, but it is for design purposes: you describe how the hardware works, then verify the description does what you want it to, and then eventually it is instantiated in actual, physical hardware. I am not sure how or even if it could be used on existing hardware to learn things about the hardware, or to optimize tasks.
The second is a thing called the Legion Programming System, out of Stanford. This comes from the other end of the scale, targeting High Performance Computing (HPC) applications. It is not a programming language per se; rather it is a model for application development. It identifies the exact same concerns I have about taking into account modern (and future) computing architecture, but it focuses on supercomputers and huge clusters of servers.
So the first option is still looking up the ladder of abstraction, just from beneath where I want to be; the second option mostly looks at high-scale hardware from the side. I suppose the thing that would make me happiest is something like a Legion Programming System but for robotics instead of HPC. The thing I would most be able to take advantage of personally is basically just a C fork with a new abstract machine and compiler which better accounts for modern architecture. Given how much work “basically” is doing, this amounts to a completely different language that uses a C-like syntax, and it seems unlikely if no one is making it already.