The idea of this series is that we'll learn how to grow your own APL (or not-APL). At the beginning I think it will be something like a study group for Aaron Hsu's new array-based compiler ideas.
So to get us started I will explain some of the first steps I took on my BQN compiler (which is nowhere near a full compiler). We'll be trying to parse a simple APL sentence, essentially.
@JeffZeitlin They wouldn't apply to a very pure interpreter like is typically used for APL, but there's a continuum from interpreters to compilers and this is one of the first things you'd do to be more compiler-like.
We will probably look at interpreter techniques in other APL Seeds sessions.
Maybe that is a discussion for another time but it is completely beyond me what it means to write a compiler for a language in its own language... especially when the language is still being developed...
@AviF.S. The interface I just linked to has a backtick keyboard. Unfortunately that makes it impossible to type a backtick, which we will be using, so you have to copy-paste that character.
The other note is that BQN differentiates between characters, which are not arrays, and strings, which are rank-1 arrays. Strings use double quotes and characters use single ones, like in C.
Anyway, the idea for the nesting code is that the nesting level is the number of open parentheses before a character minus the number of closed ones. If those numbers are equal then every parenthetical has been closed and we're back at the bottom level.
this is definitely reminding me of Aaron Hsu's thesis. I went thru it a couple months ago and pulled out the tree manipulation equations and translated it to gnu apl. Am keeping notes in a repo that will likely include the relevant ones.
To pair parentheses, the thing we need to notice is that at a particular nesting level, open and closed parentheses must alternate, so that the open-close pairs are all right next to each other.
@Adám Sorry for the tangent - my last thought on the matter is that any serious version of this should be hand-writable and speakable (dictatable) and that "arg"→"𝕩" and "param"→"𝕨" is intolerable
Based on the way we computed the nesting depth, our opening parens are one higher than the closing ones. We could adjust it, but it turns out not to matter.
@AviF.S. it already copies the link (there's also a shortcut - alt+s for the button, alt+e returning to the editor, among other things. i should add tooltips)
@Adám Ah, I don't know much about these things! Just an idea, but I of course leave it to the implementor to decide what's easiest, or otherwise preferable
Since in a valid parenthesized statement there are the same number of each type (open or closed) at every depth, we can pair all parentheses at once by sorting by their depth.
If we have multiple kinds of brackets, we could then confirm that the [{]} think Adam mentioned doesn't happen by comparing the types of corresponding parens.
@RichardPark That would get the format you showed ⟨⟨0,18⟩,⟨1,4⟩,⟨7,11⟩⟩. But that format doesn't actually fit with the array compiler style, so I wouldn't use it.
Right now, my compiler uses the permutation that transforms open paren locations to match closed paren locations.
@Marshall I see, to be fair although the parens matching for parsing in this context I get, I am generally lost on the details since I'm not an implementer
@RichardPark I do hope to show in this series that one way to "be an implementer" is just to know the right APL programming techniques. We have to start somewhere so not all the details will be clear, but we'll get to them.
@Adám That was translated to BQN from Richard's ↓⍉↑.
Time's up so I'll stop now, but a good exercise is to do the validation I talked about (say, with APL's ()[]{}). You need to check that the total number of open/closed brackets match, that each open bracket corresponds to a closed one of the same type, and that open brackets come before the corresponding closed ones.
Self-hosting is the use of a computer program as part of the toolchain or operating system that produces new versions of that same program—for example, a compiler that can compile its own source code. Self-hosting software is commonplace on personal computers and larger systems. Other programs that are typically self-hosting include kernels, assemblers, command-line interpreters and revision control software.
If a system is so new that no software has been written for it, then software is developed on another self-hosting system, often using a cross compiler, and placed on a storage device that...
@RGS Well, a compiler transforms source code written in some language (right now, a subset of BQN) to code in another language (WebAssembly). This is purely manipulation of data, so you can do it in any language.
@Marshall ok... but this feels like a chicken and egg problem; if you are writing a compiler for BQN in BQN, how will you run that compiler for the first time to compile itself..?
I know you have been using BQN2NGN but how does that piece fit into this puzzle?
@RGS Not with your own compiler, of course. This is called "bootstrapping": you need some other implementation of the language to start with. Which I happen to have.
In computer science, bootstrapping is the technique for producing a self-compiling compiler — that is, compiler (or assembler) written in the source programming language that it intends to compile. An initial core version of the compiler (the bootstrap compiler) is generated in a different language (which could be assembly language); successive expanded versions of the compiler are developed using this minimal subset of the language. The problem of compiling a self-compiling compiler has been called the chicken-or-egg problem in compiler design, and bootstrapping is a solution to this problem.Many...
@RGS - Like @Adám said, your first, minimalist version is written in another language -- or in a subset of your language that happens to have the same meaning in another language.