The Luon programming language

1 year ago (github.com)

This is an impressive achievement, given there’s a whole language plus IDE. Kudos to the author. I couldn’t see any indication of what the author plans to use it for - I hope he can share more below?

I’m intrigued by the LeanQt library as well that the IDE uses (https://github.com/rochus-keller/LeanQt) too.

  • > what the author plans to use it for

    Thanks. I e.g. re-implemented the Smalltalk-80 VM in Luon (see https://github.com/rochus-keller/Smalltalk/), and I consider implementing an Interlisp VM (see https://github.com/rochus-keller/gingko/) which uses LuaJIT, which was an important motivation to interrupt my Micron language project to implement Luon.

    • Amazing that you also managed to implement Smalltalk besides Oberon and Luon - all of them with IDEs!

      Wow!

      And by the way the startup speed of the IFE is just insane! it is actually faster than my simple text editor!

    • nice! do you feel like oberon has something that gives it an edge over more currently popular languages, or is it just a matter of personal preference?

      3 replies →

  • Amazing project!

    I get the appeal to write an IDE from scratch, especially if you are already an expert in writing GUIs with your framework of choice! I wonder if it would make more sense to spend that time writing a language server protocol daemon. That way, you could make your language available in any IDEs your users like that support LSP.

    • I'm usually working on older machines on which the IDE's supporting language servers would be much too slow or wouldn't work at all because of incompatibilities. I like lean tools with little dependencies. But there is a parser in moderate C++, so maybe someone else will implement such a daemon.

      5 replies →

    • I am actually glad that this person developed the IDE. Please download the IDE and try it. It is exceptionally fast. When I compare the speed with that of IDEs like Visual Studio Code etc, the difference is night and day.

If you want to hear the music, which I had in my head when I implemented Luon, here is the link: http://rochus-keller.ch/?p=1317 ;-)

  • Wow! That’s impressive. The video at the top of your post really helped me understand the coordination involved. Thank you for sharing.

    I imagine you’ve been playing music most of your life. How long did it take you to bring all of this together and start “one man band” improvising?

    • Thanks. I actually started playing the piano in 1975. But only in the early 2000 I started to play bass on a pedal board. In 2010 I made my first experiments with playing the drums instead of the bass on the pedal board (http://rochus-keller.ch/?p=317). In 2014 I had a dedicated setup simulating a big band and played together with other musicians (e.g. http://rochus-keller.ch/?p=962). In 2022 I bought a Mac mini M1 and since enjoy the excellent sound quality of the new plugin generations. Only this year I managed to play the ride cymble as a real drummer would do it.

> locals can no longer be used before declaration

There's a lot I like about Lua but it so happens that a few days ago I spent longer than I'd like to admit debugging a trivial typo for Advent of Code day 5 that would have been caught by this.

Wondering if Luon will also prohibit or at least warn about storing nil in a table.

  • Luon doesn't directly support tables, but instead supports records, arrays and hashmaps (which internally use tables). Since it's statically typed you can only store nil to a field or element if it is of a structured type.

This looks really good. It seems to fix all the warts and moles in Lua that used to exasperate me and adds type-safety which is a huge enhancement.

Replacing the 'everything is a table' with records, arrays and hashmaps is also a thoughtful improvement IMO.

Just confirming one point to make sure I understand the licensing implications correctly. Since the compiler transpiles to LuaJIT, and since that's just data, using output of the (GPL v2/v3 licensed) Luon compiler (i.e. the LuaJIT output) in a commercial/closed source project without divulging the source of said project should be fully kosher right?

Am guessing the answer is most likely in the affirmative but just making sure.

  • Yes, what the compiler generates (LuaJIT bytecode in the present case) is not affected by the license which applies to the compiler. Usually, the runtime libraries which the generated code automatically depends on, are of bigger concern. Luon offers a GPL exception for the runtime code, as well as an LGPL or MPL license. So you can essentially use the runtime code for any purpose.

Luon looks mostly like Oberon and not so much like Lua, it's not obvious which of the Lua features it incorporated. It didn't seem to have coroutines, for example.

But I am glad that it went with Oberon's 0-based array indices, as opposed to Lua's 1-based table indices.

https://github.com/rochus-keller/Luon/blob/master/specificat...

  • > Luon looks mostly like Oberon and not so much like Lua

    Luon can indeed look similar to Oberon if you use upper-case keywords and semicolons, but there is not need for this. Both - Lua and Luon - have much in common with Modula-2 (given lower-case keywords). There are many elements in Luon which are pretty similar to Lua, e.g. constructors, pcall, most control and loop statements. But there are also significant differences of course, because Luon is a statically typed language and Lua isn't.

    • Modula-2 – a blast from my past. Back in the ‘80s I used it to implement a prototype distributed OS (as designed by a team at JPL) on VAXen. Logitech (!) had a really nice VAX compiler back then. One of the most productive 6-month stretches of my career. Luon looks like an answer to my unspoken prayers. Thank you!

      2 replies →

  • Don't all of Wirth's languages let you use any ordinal as the array index? At leat in Pascal you can declare an integer subtype, say 7..17 and use that as the type of the index of an array. Then the first element is item 7.

    The point being that both the start at 0 and start at 1 camps can have it their own way.

    • > Don't all of Wirth's languages let you use any ordinal as the array index?

      In Oberon, Wirth kicked out everything to the bare minimum, including subrange types. Array indices in Oberon start with 0.

    • >Don't all of Wirth's languages let you use any ordinal as the array index? At leat in Pascal you can declare an integer subtype, say 7..17 and use that as the type of the index of an array. Then the first element is item 7.

      Can confirm that about Pascal, since I had used it a lot earlier.

      Don't know about the other Wirth languages.

      >The point being that both the start at 0 and start at 1 camps can have it their own way.

      Yes, but that is not the only point. Another reason, and maybe the more important one, is that having such custom array index ranges, can more naturally fit the problem domain. In fact you can even use user defined types for the ranges, e.g. so you can define an array with Sunday to Saturday as the indices and the values of (the equivalent of) an enum representing 1) weekdays and 2) weekends, as the corresponding values.

      Then your code involving days and weekdays and weekends, will read more naturally, so will be easier to both read and maintain. And you only have to do those custom definitions once, up front, so it is not much extra work for the benefit gained.

  • I have a really hard time understanding why people like 0 based indexes. They are a relic of C style arrays that are based on and interchangeable with pointers which use offsets that are naturally 0 based. Use in later languages gives us endless off-by-1 issues and rise to "for 0 to count/len/num - 1" or even better range syntax that is start inclusive BUT end exclusive. It is a horrible cludge just to support 1970s language perfomace optimization. Arrays should start and end at whatever start index is required, not at offset 0 of pointer to fist element of array.

    • Hang on. Off by one issues are the argument frequently given in favour of zero-based indices, not the other way around. For example, let's iterate through items placing them in 3 different groups;

      JS:

          for (let i = 0; i < items.length; i++) {
              groups[i % 3].push(items[i]);
          }
      

      Lua:

          for i = 1, #items do
              table.insert(groups[((i - 1) % 3) + 1], items[i])
          end
      

      Don't get me wrong. I like Lua, I've made my own IDE for it, https://plugins.jetbrains.com/plugin/14698-luanalysis, but this is definitely not an argument in favour of 1-based indices.

      14 replies →

    • Having done fairly extensive parsing work in Lua and Julia on the one hand (one-based), and Python, Javascript, and Zig on the other (zero-based), the zero-based semiopen standard makes intervals dramatically easier to calculate and work with. It's really the semiopen intervals which make this the case, but as the Word of Dijkstra makes clear, zero-basis comes along for the ride, to combine semiopen intervals with a one-basis is perverse.

      Naturally it's true that for collections and naïve indexing, 1-based is more natural. But those are rare places for bugs to occur, while interval calculations are a frequent place for them to occur.

      Clearly I'm far from allergic to the other standard, but I come down on the side of the zero basis for that reason.

    • I have a really hard time understanding why people like 1-based indexes! 0 is the smallest unsigned integer in every programming language I know of that supports the concept of unsigned integer. Why shouldn’t an array at the smallest possible index correspond to the beginning of the array?

      It’s also very natural to think of arr[i] as “i steps past the beginning of arr”. With one-based indexing arr[i] has no natural interpretation that I know of. It’s “i-1 (for some reason) steps past the beginning of arr”. The only reason I can think of to prefer that extra -1 in your formula is just because human languages (at least the ones I know of) work this way — the 42nd element of a sequence, in normal colloquial English, means the one 41 steps past the beginning. But I’m not sure if there is any logical justification for that.

      I also, despite being American, find the convention used in many countries of numbering building floors starting with zero to be more logical. I’m on the third floor, how many stories up did I travel to get here? Three.

      15 replies →

    • > [0-based indexes] are a relic of C style arrays

      I don't think this is true. They exist in other disciplines (maths for instance) that have no relationship with C or other programming languages from the 1970s.

      > for 0 to count/len/num - 1

      I will counter saying that such a for...to syntax is a relic of BASIC.

      > or even better range syntax that is start inclusive BUT end exclusive

      I know that your "better" is sarcastic, but I actually find left-inclusive+right-exclusive ranges fantastic. They allow perfect partitioning, easy calculation of lenght, etc.

      > Arrays should start and end at whatever start index is required

      I agree. An accommodating language would let you define both lower and upper bounds of an array, instead of its size.

      3 replies →

    • There are 360 degrees in a circle, and the first entry is 0 degrees. The first time element of a day is 0:00:00(and enough 0s to satisfy whatever resolution you require). These were not established in the 1970s, and somehow pretty much everyone understands and works quite well with these systems.

      7 replies →

    • Some countries consider the 1st floor to be the ground floor, others consider the 1st floor to be the floor above the ground floor, which the formerly mentioned countries consider the 2nd floor… I think 0/1-based indexing is more subjective than simply being a “relic of C” or a “horrible kludge” :P

      1 reply →

    • >They are a relic of C style arrays

      Doesn't it predate that by a good amount? I would think it is a relic of the EEs who built the digital world, those early languages show a great deal more relation to the bare metal than modern languages. Creating an array whose index starts at 1 just doesn't make sense from the discrete logic point of view, you are either wasting an element or adding in an extra step.

      But in this day and age how can a language not have ⎕IO ← 0?

    • I honestly think that most of the problem arises from the fact that we just culturally start counting at 1 when talking about everyday things. As it stands, we're all used to it that way, and then computers come along and show us that counting from 0 is often more useful. So we adjust, but only for computer programming purposes.

      If our species had established counting from 0 as the norm right away (element #n is the one that has n elements before it; you think of the number as the number of steps you have to move away from the starting point), then I suspect the reverse would not be true: I don't think anyone would find a situation in which counting from 1 is so much more convenient that it's worth going against the grain of established norm.

      So in summary, I think we only think of counting from 1 as natural because it's in our culture. And it's in our culture because ancient superstitious humans had an irrational problem with the number 0.

      1 reply →

    • It's funny that nearly half of all comments are below your comment. The topic seems to unsettle people much more than a new programming language. This is also another example of how a downvote button is primarily misused in practice.

      > Arrays should start and end at whatever start index is required

      That's what you were indeed able to do with Pascal and also Modula-2, but with Oberon, Wirth came to the conclusion, that other index ranges than 0..n-1 were not needed. In his 1988 paper "From Modula to Oberon" he considers it "inessential" and providing "hardly any additional expressive power", but causing "a hidden computational effort that is incommensurate with the supposed gain in convenience". I think, in the end, it is in the eye of the beholder.

Is this purely a personal project, or is it supposed to be used by others? You have made so many languages in the Oberon family (great job keeping the traditions alive, by the way), it's hard to know whether they are just a personal experimentation or you are expecting others to use them too.

  • This is not actually a contradicion, and the audience will decide whether the language will be used more widely. It's not my first priority, but there's nothing against it either. What you call "tradition" applies to my experiments with the Oberon Systems and the backward compatibility with their source code (for practical reasons, otherwise I would not be able to compile them), but my interest is actually in the language adapted for today's meaning of simplicity, which I call Oberon+ (or Luon, or Micron), and which would definitely have the potential for further adaptation if you look at what kinds of new languages are popular at the moment.

I confess I was worried, until I read the name explanation, that it was named after Lululemon's marketing term for its preferred elastane/cotton blend

  • Funny; it's actually surprisingly hard to find information; but Perplexity told me, that Lululemon's Luon is a material which has great flexibility and maintains its shape over time, wicking away sweat, and good coverage; all good features for my programming language ;-)

Why not using brackets to replace begin and end ?

  • Right, looks like terrible unreadable mess to me. Somehow even worse than Python, but hey, it could be worse, it could have significant whitespace (though I'm sure the SV Python fetishist """data scientist""" mafia this site is filled with disagrees...)