programming_languages

This magazine is from a federated server and may be incomplete. Browse more on the original instance.

Toes, in Help me find my new "MIDI Assembly" a new name!

Compiled MIDI, cmid

MIDI bytecode / Musical Bytecode, .MBC

MIDI Replay, .rmid

Whatever the magic number of your file are .gif

demesisx,
@demesisx@infosec.pub avatar

Midi bytecode gets my vote.

mrkeen, in Meta, a Human-Friendly Programming Language

@armchair_progamer

Awful naming. Forgetting the fortune 500 company you're already thinking of, there's already a Meta Lang, abbreviated to ML.

Besides that, does it have any 'meta' features? E.g. Homoiconicity?

kakes, in Meta, a Human-Friendly Programming Language

For anyone curious, FizzBuzz:


<span style="color:#323232;">Meta [
</span><span style="color:#323232;">	Title:   {Fizz Buzz math "game"}
</span><span style="color:#323232;">	Author:  "Kaj de Vos"
</span><span style="color:#323232;">	Rights:  "Copyright (c) 2021,2022 Kaj de Vos"
</span><span style="color:#323232;">	License: {
</span><span style="color:#323232;">		PD/CC0
</span><span style="color:#323232;">		http://creativecommons.org/publicdomain/zero/1.0/
</span><span style="color:#323232;">	}
</span><span style="color:#323232;">	Notes: {
</span><span style="color:#323232;">		https://en.wikipedia.org/wiki/Fizz_buzz
</span><span style="color:#323232;">		https://wiki.c2.com/?FizzBuzzTest
</span><span style="color:#323232;">		https://www.rosettacode.org/wiki/FizzBuzz
</span><span style="color:#323232;">	}
</span><span style="color:#323232;">]
</span><span style="color:#323232;">
</span><span style="color:#323232;">For counter 100 [                                   ; Count to 100
</span><span style="color:#323232;">    Third?: unless modulo counter 3 [write "Fizz"]  ; Display "Fizz" every third count; remember whether we did
</span><span style="color:#323232;">
</span><span style="color:#323232;">    Any [
</span><span style="color:#323232;">        unless modulo counter 5 [write "Buzz"]      ; Display "Buzz" every fifth count
</span><span style="color:#323232;">        third?                                      ; Remember earlier result
</span><span style="color:#323232;">        write counter                               ; Display the number if not third or fifth
</span><span style="color:#323232;">    ]
</span><span style="color:#323232;">    Write " "                                       ; Separate the displayed items
</span><span style="color:#323232;">]
</span><span style="color:#323232;">Write new-line                                      ; Return the text cursor to the start of the line
</span>
hardkorebob, (edited ) in Meta, a Human-Friendly Programming Language

Awesome! Much better layout than the other post made ;) Thanks for the assist. Oh and matrix.to/#/:gitter.im

ChubakPDP11, (edited ) in Compiling higher order functions with GADTs

I think by ‘GADTs’ you mean an AST (could be mistaken). In that case, it would not be a bytecode interpreter, it would be a tree walker. In most languages, an AST is translated down to bytecode, and passed to a VM execution engine. How this engine deals with closures is highly compliant on the architecture of the AST.

First, keep this in mind: A closure is just a closure at the higher-level. Job of the AST is to translate it down to ta more abstract form, thus, a closure would most probably be inlined. Otherwise, it will be a global subroutine defined somewhere on the stack. It never makes sense not to inline closures, unless that closure is a ‘hotzone’, e.g. frequently used, in whcih case you should most obviously define as a subroutine, and if possible, JIT.

A VM lke NekoVM has a higher-order, terse IR with which you can handle closures like you do in JS.

Don’t conflate higher-order constructs with intermediate representations. If you are interested to see a VM development in progress, star my RuppVM. Still early though. But i tend to work on it actively.

Thanks.

ChubakPDP11, (edited ) in Should I continue making my own VM, or scrap it for some preexisting solution?

Are you specifying everything beforehand? If not, I’d recommend locking in on an ISA with stack effect pre-determined. Also, minimize as much as you can.

First off: Read Xia-Feng Li’s excellent book if you have not.

Then.

Here are some minimization tips I am doing for my RuppVM. I just began working on it less that 24 hours ago. But the tips are based on over 6 months of off-and-on trying to make a VM, and failing. I am sure this one will take, because of these minimization efforts:

  • Everything is a word: When you are reading the bytecode stream, read word-by-word, and by word I mean machine word. Don’t waste your time on floats, you can implement IEEE-745 floats as a module, it will be good for practice. There’s a good book for it here.
  • No complex datatypes, BLESS!: So I said everything is a word, what about arrays? Structs? Basically, you need to ‘bless’ chunks. Blessing means taking a routine and turning it into a structure, see: Perl.
  • No OS-level threads, BIND!: Just make ‘green’ threads, as I am doing in RuppVM. You can use the FFI to bind them to OS threads.
  • Stop the World GC + Arena Allocation: Don’t waste time on intricate GC, Just do stop-the-world mark and sweep, on arena-allocated memory (see my code).
  • Super Basic FFI: Take a look at my ISA.txt file, look at what I am doing for FFI. You don’t need intricate type mappings for the FFI. Just register a ‘hook’ to an address in memory (or ELF).
  • Avoid JiT/AoT for now: Don’t focus on it at the beginning.

These variables are not exactly portable, but you can use them, abuse them, etc:

  • extern etext -> First address past the text segment;
  • extern edata -> First address past the initialized data segment;
  • extern end -> end of bss

I think there are portable libraries for handling ELFs and PEs. You could also write your own Assembly code for it. For loading functions from files, for the FFI, these help a lot.

EDIT: I looked, there does not seem to be any ‘portable’ libraries for handling PE and ELF with the same interface. I guess ther can’t be, two different beasts.

Another aspect you should implement is a ‘signal trampoline’. This trampoline will help handle signals from the OS, and hook it to your green threads.

Now, don’t take these as gospel. I am sure you know most of these already. But in case there’s new info, feel free to adapt it.

Star RuppVM, I will be adding a lot of stuff to it soon.

porgamrer, in Should I continue making my own VM, or scrap it for some preexisting solution?

If you want to do anything other than long-term blue sky VM research, don’t write your own VM. That’s my advice. Same goes for programming languages, game engines, etc.

Always do the unambitious thing that seems like it should take one weekend, and probably set aside a month for it >_>

Also admit to yourself that things like bloat and binary size are not real problems, unless they intrude on your daily workflow. They are just convenient distractions from harder tasks.

I say this as someone who is constantly failing to complete any projects for all these reasons.

sxan, in Should I continue making my own VM, or scrap it for some preexisting solution?
@sxan@midwest.social avatar

I’m not sure that you’re describing the same thing, but this very experience you’re having with Lua is what drove me away from Ruby, and ultimately from all non-statically compiled PLs.

Instability in the VM, but more so in libraries, meant upgrades became projects to fix things that broke because libraries introduced regressions, API changes, and new bugs. For any non-trivial application, something would break. This was entirely unacceptable for services; entire suites would go down because of a regression in one popular library, and you get to find these things out at runtime.

Eventually, I went back to entirely statically compiled languages - I’d encountered the same usage with bytecode VM languages like Java, to a lesser degree. But with PLs like Go, once I have a binary, it’ll work until someone breaks libc. Not impossible, but that happens years or decades apart, not monthly like it did with Ruby.

Now I make do with zsh, or bash if I plan on sharing, with help from the usual ask/ser/grep crowd. If I start feeling cramped, I know my program is getting too big for scripting and switch to a reliable language. The short-term convenience is not worth the long term grief.

ZILtoid1991,

Once I fixed the load function (which in my case, involved looking up how that function worked and what I needed to call to get things working), I had a very similar issue without any error messages or whatsoever, things just didn’t work, and before that, I already had issues with using Lua functionalities like Metatables, due to the clunky nature of its API.

I need at least some bytecode, since I need some way to get some OS and CPU-independent loadable code (scripts). Sure, I could use DLL files (and their other OS equivalents), but then I introduce a massive hurdle of having to compile scripts for each CPU architecture and OS combinations (as well as potential for more serious security issues), even if it had a lot of speed benefits.

I think I’ll try to continue pushing forward with it, but restrict my time spent on it as a “lower priority” project. I did try to look up whether there’s a way to use LLVM as a host for scripts, because no way I’m going to touch WASM with a 10 meter long pole (TL;DR: I have started learning programming during the whole “web app” and “the web is the future” craze, seeing other libraries for “app portability” and the teaching optimization being abandoned in favor of electron and “there will be a big strong server on the backend” really broke my heart.)

sxan,
@sxan@midwest.social avatar

I don’t have enough experience yet with WASM; ultimately, it’s bytecode, right? So the same rules apply. Note I didn’t make an exception for dynamically linked programs; the more components in your stack that are variable, the more instability you have.

But it sounds like you’re doing a sort of plug-in system, and that involves instability by design. Using WASM seems far easier that implementing a bespoke Lua VM.

bitcrafter,

because no way I’m going to touch WASM with a 10 meter long pole

I think that you should look into WASM a little more closely because it is not web-specific at all; it is more like an alternative to the JVM that is a bit lower level and designed to be interpreted/JIT compiled more efficiently. You do not need to embed a web browser or anything similarly heavy into your app to use it; you can just use via Wasmtime, which is a library written in Rust with bindings to other languages that is officially supported by the maintainers of the WASM standard.

KindaABigDyl, in The search for easier safe systems programming (blog post + language)
@KindaABigDyl@programming.dev avatar

It’s kinda like arenas in C

ericjmorey, in The search for easier safe systems programming (blog post + language)
@ericjmorey@programming.dev avatar

This seems to address the criticisms people have with using rust for prototyping. Simplifying the mental model of lifetimes and ownership, incorporating what amounts to a manually called garbage collector, and making the level of compiler enforced strictness flexible for different phases of development all sounds promising. I look forward to what this project develops into and what use of the language reveals about software development.

sxan, in The search for easier safe systems programming (blog post + language)
@sxan@midwest.social avatar

Easy as Go, with Rust’s runtime, would be a dream.

tarix29, in Jolie, the service-oriented programming language
cbarrick,

Service-oriented architecture does not imply SaaS.

Obviously plenty of FOSS software uses servers. IRC, Mastodon, Email, NTP, X11… There are plenty of good uses for service-oriented architecture in FOSS.

lung, in Jolie, the service-oriented programming language
@lung@lemmy.world avatar

That’s a cool idea, though obviously you need functions and objects to actually make services do useful stuff. And lots of libraries. I achieve most of what they describe quite easily using GRPC/protobufs with Go, and so I have doubts that this is going to be better. Plus GRPC/protobufs have the benefit of working seamlessly with other languages, and with some small added code, you can add annotations that handle auth, routing, validation, etc

porgamrer, in LLVM, MLIR (or any ready-made IR) are not a good fit for learners. Roll your own backend pls if you wanna learn (same shit with LP generators!)

My criticism is almost the opposite. I think LLVM is pretty easy and quite a good way of learning about low-level stuff in an incremental way. I just think it sucks to have it as a critical dependency in a mature product.

When I see a new language that is built around llvm I know the build time is going to be terrible.

As an aside, if I were teaching a compilers class I’d look quite seriously at wasm as a target. It’s pretty much the only target that is open-ended, high performance, and portable.

I’ve never used it though, so I don’t know how easy it would be for beginners to make sense of.

ananas,

It’s pretty much the only target that is open-ended, high performance, and portable.

I wouldn’t call wasm really portable. And webassembly doesn’t call itself portable either.

Limiting out everything non-little-endian, requiring IEEE754-floating points and forward-progress guarantees is not really portable anymore.

porgamrer,

Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

This is front and centre on the homepage…

It makes assumptions about the native architecture for the sake of performance, but it’s still portable because you can implement all that behaviour in a VM if necessary. The important thing is that the behaviour is well defined.

It’s not perfect but I don’t think the situation is any worse than in Java, C#, Lua, etc. If your hardware has non-standard floats you’re going to have a bad time with any VM.

ananas, (edited )

This is front and centre on the homepage…

I stand corrected.

It makes assumptions about the native architecture for the sake of performance, but it’s still portable because you can implement all that behaviour in a VM if necessary. The important thing is that the behaviour is well defined.

It doesn’t have to be native architecture, just the execution environment (i.e. you can emulate it).

But I don’t see why by that logic any turing-complete language wouldn’t be in the group “portable”, including any hardware-specific assembly. Because you can always implement a translator that has well defined-behaviour? e.g. is 6502 assembly now portable that C64 and NES emulators are commonplace? (And there even is transpiler from x86 asm to 6502 asm). I do not think many of us see this as a good definition for portability since it makes the concept meaningless, except in cases where the translation layer is not feasible due to available processing power or memory.

It’s not perfect but I don’t think the situation is any worse than in Java, C#, Lua, etc. If your hardware has non-standard floats you’re going to have a bad time with any VM.

I mostly agree here. But I think portable language is not the same thing as a portable VM, and that portability of a language target is different from VM portability.

porgamrer, (edited )

But I don’t see why by that logic any turing-complete language wouldn’t be in the group “portable”, including any hardware-specific assembly. Because you can always implement a translator that has well defined-behaviour?

What matters is the practical reality. Generally, languages are not portable when they don’t have well-defined behaviour, and when this causes their implementations to differ.

And thanks to this low standard for portability, a lot of VMs and high level languages are portable until you get to the FFI.

e.g. is 6502 assembly now portable that C64 and NES emulators are commonplace?

I would say yes! It’s just that portability is not the only thing required to make a VM spec useful.

But if you lacked other options, you could theoretically build gcc for 6502 assembly once, and then use the same binary to bootstrap the gcc on lots of different platforms, specifically thanks to the proliferation of NES emulators.

This would also only work if there is a standard NES API available in all the emulators that is rich enough to back a portable libc implementation. I have no idea about that part.

ananas, in LLVM, MLIR (or any ready-made IR) are not a good fit for learners. Roll your own backend pls if you wanna learn (same shit with LP generators!)

Good opener!

These toolchain are created for experts to create industrial-level compilers. Even if you think you got a syntactic design concept that is such hot shit that you can’t wait to get it bootstrapped, even if hell, it proves Rice’s theorem wrong, please, write a simple interpreter for it to prove your syntax works. In fact, I think one way you can test your language’s design is to have it mooch off an established VM like JVM, CPython’s VM or CLR.

I agree in principle, but mooching off established VMs will affect your overall language design since and significantly push you towards language “grammar” those VMs are built to deal with. Syntax is pretty irrelevant early on and should be made easy to change anyways.

But if you wanna ‘learn’ compiler design, I beg you to roll your own backend. You don’t need SSA or any of that shit. You don’t need to super-optimize the output at first try. Just make a tree-rewrite optimizer and that’s that.

I don’t think I really agree with this. Of course, if your goal is just to learn how everything works, rollng your own is the best option. But if you want to do more than that I think not taking advantage of tools available (such as LLVM) is suboptimal at best. It might be fine if you are unemployed or can slack off enough to spend copious amounts of time on your language, but you will spend your time on rewriting tiny details over and over that might be fun to make, but it won’t help with getting your language into usable state. There’s plenty of optimisations you can (and should) do even before you pass on anything to LLVM if the goal is to think about those.

Same is true with LP generators. From Yacc to ANTLR, they just make the experience harder and less rewarding. I know hand-rolling LP is hard in a language like C, in which case, don’t fucking use it lol. There’s honestly no inherent worth in using C in 2024 for compiler design.

I’m not sure I got your point correctly here, but if I did, I heavily disagree. Like it or not, unless you plan to write everything from hardware up from scratch in your language, you need to adhere to a lot of C stuff. Whatever your system C ABI is, that is the layer your language needs to be able to talk to. And that, for better or worse, requires to take C heavily into account.

But there’s still use for C in being the subject of your compiler. It’s a very simple, straightforward and more importantly, standardized language, you don’t need to write a runtime for it, because when it comes to both UNIX and Windows, runtime is OS itself! Just make sure you add a syscall interface and then C runtimes like glibc and CRT can be easily strapped.

Heavily disagree with C being either simple or straightforward, but totally agree with the important part that it is standardised.

I know my point about using LP generators is preaching to the choir and most people despise them — but I just don’t understand why people love to use IRs/ILs when doing so teaches you shit.

I recommend beginning to design your language with the IR – your IR.

Anyways tell me what you think about my ‘take’ on this. Of course I am not saying you are ‘less knowledgeable’ for using LLM or MLIR, I’m just saying, they don’t teach you stuff.

Still, some people just use LLVM and MLIR as a final ‘portable’ interface, having done the optimization on graphs and trees. i think there should be some sort of ‘retargatble assembly’ language. Like something with fixed number of registers which… oh wait that’s just a VM!

I mean, you answer your own questions here. People love to use IRs/ILs because things like LLVM IR are the closest thing we have to portable assembly we have, and it makes it simpler to get into running state. Most compilers have their own internal IR (maybe even more than one) anyways, regardless or not if they use something like LLVM. Understanding how LLVM/MLIR/whatever IR is designed is pretty important before you start rolling your own if you want it to be useful.

Also you don’t need to necessarily translate to a super super low-level language. Just target C. GNU C to be exact. Cyclone does that, in fact, I am planning to bootstrap my functional language, which I named ‘Xeph’, based on Zephyr ASDL, into GNU C as a test. Or I might use JVM. I dunno. JVM languages are big these days.

Targeting C is completely valid. Though I see no reason to use GNU C – just use the actual standardised versions. And I think what you target should be part of your language design and suit what your language’s purpose is, not stuff to pick at random whenever.

PS: Do you guys know any cool VMs I can target beside CPython and JVM? Something with AoT perhaps?

Besides BEAM VM that was already mentioned, Lua VM is pretty interesting to target (not AoT though) if that’s your thing.

ChubakPDP11,

I actually started work on a tool similar to Forth’s VMGEN. It will generate Stack VM’s in several languages leveraging m4, just like Bison. The difference between it, and VMGEN would be that it actually adds GC and threading. Based on Xiao-Feng Li’s book.

ananas,

That sounds interesting, I probably want to take a look at the book too.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • programming_languages@programming.dev
  • DreamBathrooms
  • everett
  • osvaldo12
  • magazineikmin
  • thenastyranch
  • rosin
  • tester
  • Youngstown
  • Durango
  • slotface
  • ngwrru68w68
  • kavyap
  • mdbf
  • InstantRegret
  • megavids
  • ethstaker
  • tacticalgear
  • cubers
  • normalnudes
  • Leos
  • cisconetworking
  • khanakhh
  • GTA5RPClips
  • modclub
  • provamag3
  • anitta
  • JUstTest
  • lostlight
  • All magazines