Paging @akkartik, he wrote this, and it’s gone through some significant changes in the past 3 years.
Ack :) Happy to answer any questions here.
Given your experience with Arc and your desire to eventually build something similar for Mu, what do you think of Bel?
I like it a lot! I read drafts of it a couple of months ago, and my major feedback was that the description failed to do justice, right up top, to everything that’s great about Bel.
I might try to build Bel as level 3 atop Mu in a few months time. It seems like a good fit since it pays such close attention to what it needs from lower levels.
I’m also considering Oil, since it would nice to have a real programming language that is also designed to be ergonomic for the commandline. But it doesn’t have to be either-or. As I said in OP, there’s plenty of room for trying out different HLLs here.
It’s a follow up to Arc, by the author of Arc, which is a Lisp dialect: https://lobste.rs/s/5rxzrf/bel_new_dialect_lisp
Do you know anything about Forth and the Forth philosophy?
@akkartik: How do you reconcile your goal of wanting people to be able to easily understand the entirety your project with your goal of also using your own literate programming and build tool?
I am not affiliated with the Mu project officially, but my understanding of it is that he wants people to be able to stack from Machine Code to HLL, relatively easily compared to doing the same for existing programming languages.
Right now, to understand the entire computing stack in a way that you can make changes at any level requires you know understand Compilers, machine code, how optimizations work, operating systems and kernels, event driven code, and sooooo many more layers.
Mu isn’t optimizing for “I can read this code at a glance”, as much as it’s optimizing for building a comprehensible stack, where if you build an understanding of it, that understanding gives you access to the whole stack.
Part of that is lots of testing and making things mockable at lower levels than most people think of mocking, like the filesystem, or keyboard and so on. Another part is optimizing for re-writable code, that is amenable to being moved between projects. Another part is reducing dependencies to a minimum, so that you can understand the whole system.
At least, that’s what I’ve understood from conversations about it in the past.
I could have sworn I responded to this, but maybe I forgot to hit submit.
@yumaikas gives a lot of the reasoning. I’ll just add a meta reason.
An implicit assumption of the question seems to be that for something to be comprehensible it has to be familiar. That assumption basically invalidates my whole project :)
I believe the fundamental skill of programming is being able to switch between notations and abstractions. Unfortunately this essential complexity is often drowned out when we learn to juggle all the myriad details of our baroque stacks today. Backwards compatibility imposes chains on our brains that atrophies our fluencies around switching notations.
I’d rather learn 10 elegant notations that are each internally consistent than a single eldritch monstrosity that has accumulated bolted-on features over time. Forget the multiple different eldritch monstrosities we tend to have to put up with these days.
(It may seem like this opinion grants license to go off and come up with new notations all the time. It doesn’t. What it does grant is license to throw out eldritch monstrosities.)
@akkartik why you decided to not add syntax sugar for function prologue & epilogue? In Mu, or even in SubX?
Also, one thing is not so clear to me: in SubX, do you typecheck the instructions? I.e., does it have some builtin table with info which instruction has what operands? you seem to hint so in the article? If yes, does the SubX binary have an option to dump this table as a “help” page? ideally with comments on instructions? :)
I do have implicit function prologue and epilogue in level 2. See the final section (“wrap up”) in http://akkartik.name/post/mu-2019-2. But yeah, not in SubX.
I do check the argument types in SubX, make sure that an opcode doesn’t unexpectedly have an imm32 argument and so on. There’s some fairly terse online help. Check out subx help opcodes. The rm32 here implies a family of arguments, with slash-metadata. Check out subx help rm32. But really for new SubX code you can just use syntax sugar and avoid directly specifying argument types altogether. This isn’t well-documented yet. Perhaps this is the best reference: https://github.com/akkartik/mu/blob/master/apps/sigils.subx#L7
subx help opcodes
subx help rm32
Ahhh, sorry, I somehow glanced over the “⇒” in the final example and got confused to think that the final listing (after the “⇒”) is also Mu. Get it now, thanks! :)
The subx help opcodes link looks super cool! :) This, together with knowing that there’s typechecking, changes a lot in the impression of user-friendliness. The sigils.subx syntax sugar sounds even more interesting, though I don’t really understand it yet from the link; do you have example fragments of real SubX code using it?
Regarding an example of all the syntax sugar available so far, check out mulisp.subx. There isn’t much there yet, all that program does at the moment is print back out what you type in. But the first 20 lines there are my first sketch of what idiomatic level-1 code will look like.
I hope to have a lot more examples soon. I sketched out a design for μLisp there, but moved on to other projects (i.e. level 2). (If someone wanted to take over μLisp, that would be awesome! You’d have as much creative control and as much collaboration as you want.)
I just uploaded 4 versions of a program to compute the factorial, each with different levels of syntax sugar, that may be interesting to compare: 1 2 3 4
In 4, on line 25, why you still have to type r/32/esp, when the other arg is sugared as %ebp??
Yeah, because the sugar only expands to arguments for the reg/mem operand. There’s no sugar for /r32.
I agree that it is weird to refer to registers with two different syntaxes. But a new syntax for /r32 seems less useful. There’s no addressing mode and so on.
Thank you! I’m very glad to hear it. Let me think about how to make this clearer in OP. If you have any suggestions I’d really appreciate them.
Hm, I think maybe best would be to show an example of typing an opcode with incorrect args, and what error is then displayed.
Also, I would mention the help opcodes command you told me about in the OP and/or readme, and actually even dump the contents (or at least fragment) in one of the places - it’s not really that big.
Great idea! Added an example to the section “Error-checking”.