/r/ProgrammingLanguages
This subreddit is dedicated to the theory, design and implementation of programming languages.
This subreddit is dedicated to the theory, design and implementation of programming languages.
Be nice to each other. Flame wars and rants are not welcomed. Please also put some effort into your post, this isn't Quora.
This subreddit is not the right place to ask questions such as "What language should I use for X", "what language should I learn", "what's your favourite language" and similar questions. Such questions should be posted in /r/AskProgramming or /r/LearnProgramming. It's also not the place for questions one can trivially answer by spending a few minutes using a search engine, such as questions like "What is a monad?".
/r/ProgrammingLanguages
Hi! I’m diving into building small programming languages and currently exploring how to implement interpreters. While reading about threaded-code interpreters (for example https://www.complang.tuwien.ac.at/forth/threaded-code.html ), I came up with the following idea: instead of generating bytecode, the compiler could produce an array of function references (or an array of functions-as-values, depending on the terminology of the host language), like this:
// pseudocode
instructions = [function(*VM)]{
const(5), const(5), sum,
dup, // duplicate value on stack
print(1), // => pop 1 value from stack and print it
const(10),
jmpe(2), // != 10 => jump to +2 instruction
halt,
const("that's all, folks!"),
print(1)
}
for vm.i = 0; vm.i < instructions.len; vm.i++ {
instructions[i](vm)
}
This isn’t threaded-code, but it’s somewhat similar.
Implementing this approach is much simpler than parsing bytecode, and there’s no overhead for deserializing instructions.
However, there are a couple of drawbacks: • These instructions are hard to serialize (except maybe as source code in the host programming language). • Debugging is a bit trickier because naive implementations lack a string representation of the instructions. That said, in my experience, interactive debuggers handle this problem well.
I’m currently working on a Lisp-like language using this kind of interpreter, and so far, I’m really enjoying the results. It’s very easy to create “super-instructions,” and writing them feels simpler overall.
I’d appreciate it if you could recommend any resources on similar interpreter techniques, or share your experiences or thoughts on this approach! I’m curious if there are potential pitfalls I might have missed or ways to optimize this further.
Sorry, my english grammar is not very good but i tried as possible to write this post understandable.
Hello and I am currently working on my new version of my programming language and after learning a lot of Parser. But I am here to ask how do I implement multiple variable assignment because the current variable assignment expression only take 1 identifier.
expr : IDENTIFIER ASSIGN expr
I want both variable assignment and object attribute editing. So I was thinking it would be like this:
expr : expr_list ASSIGN expr_list
expr_list : expr (COMMA expr)*
But I don't know how to implement like "am i just get the list of expressions by the way?" I just need some help about implementing multiple variable assignment.
I don't think this post would be all what I trying to ask so if there is something wrong please ask me to fix it!
For people who don't know what C3 is, it's a C-like language which aims to be an evolution on C rather than a whole new language.
With that out of the way:
Monthly releases of 0.6.x is continuing for C3. This summer the development of C3 will turn 6 years old. When mentioned as a C language alternative, C3 is referred to as a "young" language. Just so that you other language creators can know what to expect!
By April, version 0.7.0 will be released, removing deprecated code. The plan is to have one "dot one" release each year until 1.0 is reached (and if everything goes according to plan, the version after 0.9 will be 1.0).
This release had some language changes:
MyFoo.from_ordinal(x)
/ foo.ordinal
instead of (MyFoo)x
and (int)foo
.void!
is deprecated since it led to rather poor coding practices. This also simplifies the language. Test and benchmark functions get a similar change.$foreach
now iterates over string literals, which was missing.The standard library is also seeing some incremental improvements, including foreach
-compatible iterators for HashMap
.
In terms of bug fixes, it sees a fairly large amount of bug fixes, mostly on more obscure parts of the language.
For 0.6.7 compile time mutation of compile time arrays will finally be permitted. And perhaps enums might finally have the missing "enums-with-gaps" resolved (currently, enums are strictly numbered 0 and up).
More importantly though, is that C3 will see the beginning of work to prune unused features from the language, which will then eventually be removed with 0.7.0.
Blog post with the full changelog: https://c3.handmade.network/blog/p/8983-another_monthly_release__c3_0.6.6_is_here
Link to the C3 homepage: https://c3-lang.org
Finding it on Github: https://github.com/c3lang/c3c
Object oriented language that is transpiled to C and can seamlessly integrate with C
Hey, while I love working with C sometimes i miss having some niceties like containers and async, as a joke I programmed an object oriented library in c, so I can create lambdas, interfaces, functions, etc in c and then I was getting bogged down with the boilerplate, so I decided to make a language out of it. It kinda looks like dart but has an extern keyword that allows me to implement some function, method or even an entire class (data struct + methods) in C. I already made every pass until the ir and started working on the C backend. This way I can structure my program, async stuff, etc with an high level language but perform the business logic in C + and call code from either language in either language. For the memory model I am thinking on using refcounting with either an microtask based cycle detection that checks the object pool + on allocation failure or placing this responsibility on the programmer, using weak refs. While I am making it, I can't stop thinking that it probably is fast as fuck (if I get the memory model right), and it kinda left me wondering if someone already tried something like this. Anyways, I wanted to get some feedback from people more experienced, I always wanted to make an programming language but this is my first one. Also if anyone has an idea of name, I would be glad to hear! I don't have an name for it yet and I'm just naming the files .fast
Hey, I'm looking for people (ideally >= graduate level), who use HDLs or HLS somewhat regularly as part of their job/research: I'm a Masters student working on adding tensor/multidimensional array processing features to the SUS language, and as part of my project I would like to spend some time talking to you about your/an open source codebase, identifying what kinds of new features and abstractions would or wouldn't be valuable to you, in the context of the goals of the SUS language.
Although this is a Masters project, my goal here is primarily to make the experience interesting for you: this is not a survey link, but an invitation to spend an hour or so discussing some relatively weird/esoteric possible language features. The benefit to me is to draw on your experience, informing the language features I end up with.
If you're interested, please send me a DM here, and I can arrange a conversation on whatever platform you would prefer.
hello world program execution
Ever thought of combining chess and programming? Meet e2e4, an esoteric programming language interpreted and implemented in Perl.
a1K - Place King at a1.
a1b1 - Move King from a1 to b1.
I just made it for fun after all!
source code: https://github.com/hdvpdrm/e2e4
I'm implementing a small programming language, statically typed, but with automatic memory management (basically with a GC of any sort).
I'd like my programs to run both natively and on a browser, but the latter is the main focus. The two main backend options I see are transpiling to JavaScript (to run natively in the browser or in V8 outside of it) or compiling to LLVM and from there generate Wasm for the browser (and an elf for native binaries). The JavaScript approach would consists of mapping my values into native JavaScript ones as much as possible (I'd use JS's `Array` to implement my lists, `Object` to implement my structs, `string`, `number` etc). I don't have the energy to implement both right now.
The main points I see in favor of LLVM (and from there to Wasm) are:
While in favor of JS I see these points:
Generated code would be much simpler to debug, using the tools built for JS and source maps.
On the web it might actually run faster (the Wasm built from efficient languages with manual memory management, like C++ or Rust, is only ~30% faster than JS code, isn't it?).
It would be much easier to wrap JS libraries so that my programs can use them.
Transpilation and JITting would be faster and arguably simpler.
I wonder: are all my points correct? And am I forgetting anything?
Has anyone faced similar decisions? Tried both approaches?
Which way would you recommend and why?
So, about the language that i was talking in my last posts.
After discussing with some redditors, I understood that this sub i not the right scope to talk about what i wanted to show with my concept of agnostic language (as it is a bigger concept that refers to compiler, libraries and other tools and not simply the language), so i'm not here anymore to talk about this concept. I only need some criticism about my language syntax for now.
The language name is Abstract (don't ask me why, i just came with it it months ago and it sticks for sufficient time to just be it).
I already planned some good amount of documentation. Incomplete, but still a good amount.
The complete documentation can be found here: Abstract's documentation page (expect lots of english errors, it's not my main language but i'm trying lol)
Some pages can have syntax errors caused by changes during development so i will be very happy in explaining any doubt or confusion.
If you don't want to read it entirely, i also bring some syntax examples:
import from Std.Console
@public func !void main() {
let i8 myByte = 8
let i16 myShort = 16
let i32 myInt = 32
foo(myByte) # foo(i8) -> void
foo(myInt) # foo(i32) -> void
foo(myShort) # foo(i32) -> void
}
# Overloads of the function 'foo'
@public func void foo(i8 value) {
writeln("The value is a byte and it is \{value}!")
}
@public func void foo(i32 value) {
writeln("The value is a int32 and it is \{value}!")
}
let i32 value = 10
if value == 0
Std.Console.writeln("value is exactly 0!")
elif value == 1
Std.Console.writeln("value is exactly 1!")
elif value < 5
Std.Console.writeln("Value is lower than 5 but greater than 1!")
elif value >= 10
Std.Console.writeln("Value is equal or greater than 10!")
elif value > 11
Std.Console.writeln("Value is greater than 11!")
if value == 11
Std.Console.writeln("Value is exactly 11!")
else
Std.Console.writeln("Value is not 11")
# Another option to use conditionals syntax
if (value > 30) Std.Console.writeln("Value is greater than 30!")
elif (value < 30) Std.Console.writeln("Value is lesser than 30!")
else {
Std.Console.writeln("Certainly,")
Std.Console.writeln("the value is")
Std.Console.writeln("exactly 30!")
}
After seeing some of the (really bad lol) feedback on my last post, i saw how i could not show anything that i tried to, sow now i want to contextualize a little more.
in this post i will be answering some common doubts on the last post and showing about my language and the development environment around it.
(First of all, the text will be really big so sorry for bad english, it's not my main language)
As a counter part of the language-agnostic programming paradigm concept, this idea should describe a language that can be used FOR everything and IN everything.
In comparison, the Java language is what is possible to be called a system-agnostic language as it can run in any system (with exceptions obviously but this is the java concept).
We cal also take C as a example of a agnostic language as a C program can be targeted for practically everything with the right compilers (native programs, kernel, web, front and back end services, etc.).
(First of all, programming language is and aways will be a personal thing. I can't force you to use X or Y as you can't force me to use X or Y. Based on it, i'm ignoring any of kind of these suggestions as a "use X instead" answer as my question is how i can inprove MY programming language and not what language i should use.)
I already used some of these languages (C# and Java, Zig😍, C and C++) and tried to learn others to use in the future or just for inspiration (Runst, and really barelly List and OCaml). I personally love all programming languages, but i as everyone needs to admit that some languages are more usefull for some thing than others are for other thing.
Sometimes this isn't even a problem of the language design itself, as happens with C by being a really old program language (fuck, C is older than my mom lol) or C# and Java, that are designed mainly by big compaines (Microsoft and Oracle) that for much times diverged of their main objectives (yes i'm talking about you, microsoft >:( ).
In another side, we have the newer and better system laguages, Rust and Zig. (Yes, i know zig isn't ready yet, but it is still well structured and functional to be criticised about) Those two languages are designed and used with a basic and good reason: replace C. And yes, they do it very well. both are actually safeer and faster than C itself and are being replaced for lots of systems that used to be writen in C.
But still, both are not perfect. Rust and Zig are made for replace C and it means be used where C is used. And don't undestand me wrong, it's not a limit at all, as C is and can be used anywere, but the point is that it is still not designed to be.
C was not made for be used in web, was not made for be used in all the systems and operating systems that we have nowdays and mainly was not made to do be used on modern operating systems. C, AT MY PERSONAL VIEW, is just a extension of assembly, and Rust and Zig, AT MY PERSONAL VIEW are just extensions of C.
(disclaimer: i'm not saying Rust, Zig, C or any other language are bad languages, it's only MY view about their environment and capability and not a real criticism about their utility.)
"If you don't like 'C extension' languages, why not Python, javascript (with nodejs) or any other extremelly higher-level language?"
well, because they don't have the same capability of the languages based on C and assembly.
It's possibly to see the dilema now?
All these languages can be used for anything, but they're not designed to be used for ANYTHING. They have a scope and you need to go really further to get out of it.
Well, none of them. All programs are already solved with the giand plethora of languages that we have and you can use how many you want in your system to do whatever you need to do. I want do be clear here that this project is a hobbie of mine and not a big tech revolutionary project.
Clarified this, the main objective of the language is: Build complex systems with only one language instead of how much you want.
Just it, nothing much complex. i just want i language that i can use for build a kernel, as to build a website and a desktop or mobile program, don't minding the intrinsics of the language designs or having to import weird spaguetti libraries to glue everything toguether.
To make things clear, i want to explain how the idea of the project started: I, i young computer and software enginner, was trying to start with OS dev to understand better how hardware and sorftware works. As every bigginer OS dev project, i started with real mode (16-bts) and BIOS. everything was perfect, except the fact that i was spending too much time writing and reading complex things in assembly. I personally love all assembly languages and assembly probgramming in general, but i need to accept that it's not practical. So i decided to do what any other person whould do: use C instead. And here was the beggining of my main problem: not every C compiler is made to export things to raw binary. Like, obviously. no one use raw binary nowdays. modern CPUs even use BIOS anymore. but what should i do? give up mith my learning about OS dev?
And them a light came on my head: i can build a simple compiler to a language that have direct acess to inline assembly but i can also write things in a rich and good syntax. annnd this project scalated more than i actually can describle here lol.
Now that i covered the basics, let's back o the main question:
I'm really tired of writing things in lots of diferent lanugages. the main problem that i want to solve is as i alread said is: One language for everything, or a "agnostic language".
Memory management is a big problem on every low-level environment. Languages like C, C++ and Zig allow you to do whatever you want with the memory, allocating and deallocating it as your free-will, but still giving you some responsability about it, like leaks and cleanup.
Rust as a counterpart, have the famous lifetime and borrowing system. Very good for memory management, do shit and it will clean the shit for you, but also very limited. Rust don't allow (at least as default) you to fuck the memory and it is a problem. In my vision, a language should never force you to do anything, even when it can cause a bug or a complex program. So the main pseudo-philosophy for my language is: "do anything i don't care, but i will still support you to don't do it".
Also, as a fully-agnostic language, memory management can be a problem and unecessary in lots of cases (like the higher level ones), so i want to still have a automatic memory management system but that can aways be manipullable by the user (i will bring more about memory soon).
As i said before, in my vision a programming language should never force you to do anything, and i belive this syntax is also a thing. Obviously, we need limitations. One problem that i want to don't have on my language is the macro system of C/C++ (really it's just stuppid how it work). So i want a language that allow me to do metaprogramming, overload operators and functions, shadow references and eveything, but still limiting me to don't make the language unreadable.
A readable and recognizeable syntax is what mainly makes a language good and useable. Because of this, i want to desigin the lanugage with the best syntax based on my opinion and general opinion, also with some verbosity to make sure that everything is self documented.
The main point of a agnostic lanugage is that it should be really modular to work everywere. This is not just a thing in the language, but on the compiler and env itself. because of this, i designed to the language a way to manipulate the compiling and linking system from inside the language. It include locking and creating local and global references, static references that can be globally used by everything and as well be manipulated by the user and a compile time execution system.
I think it's just it (i'm really tired of writing all of it lol). I think this can show better the view that i have about the language idea and environment and maybe help me to receive some better and usefull criticism about.
Thanks for readding :3
Hello, I hope this question is okay for this community, but I have been trying to get an idea of the kinds of data structures typically _used_ to build parsers and interpreters for bytecode-virtual-machine languages. I hope to offer a more specific question below, but first for some background on where the question comes from...
Firstly, I've been working my way through _Crafting Interpreters_ (a book I am really enjoying), implementing the lox language in Rust. The first section with a tree-walk interpreter was relatively straightforward to implement (probably because I've done a little bit of work on interpreters operating over an AST before). However, when I got to the second section of the book, I found that I kept making fitful starts, and the thing that was pretty hard for me was that I couldn't "see" in my head the ultimate data structure the book is building out of code and evaluation objects (which makes it pretty hard for me to anticipate _where_ I'm going to need to park lifetimes for my rust data structures; I can't simply copy the C, in other words). I imagine you all will probably know this, but Nystrom has a parser which loads bytecode into `chunk`s, but those chunks form something like a linked-list (not a tree)? This section jumps around a lot, and I think I should probably be looking at finished implementations to see the whole structure and to be able to build rust data structures with lifetimes that make the most sense.
Secondly, I recorded a podcast episode a couple of weeks ago on Frances Allen, who worked at IBM and contributed research on compiler optimizations using graphs. A whole bunch of the compiler optimizations she first wrote about in the 70s are still widely used. It was super interesting, but then when I started thinking again about the data structures, it seemed like my Rust bytecode VM from _Crafting Interpreters_ is going to skip over building a graph. I am probably getting confused here between a compiler which produces LLVM IR and an interpreter which probably needs like a values stack and an some kind of evaluation context for each frame (for function calls, closures, etc.)
Lastly, I have some familiarity with CPython, which builds up a linked list of PyFrame objects (I think it's a doubly-linked list if I remember right) which include their own evaluation stacks and these point to the bytecode objects. There's a "values stack" used in CPython: before invoking a function call, it will push the args-count onto the values stack and then the function will pop them off to operate on them?
Thus, this is my confusion (and I apologize for the long question):
- What are the commonly used data structures in these bytecode VMs (stacks for evaluation, for instance, but frames that relate to each other somehow).
- What are the relationships (ex: Python has a values stack and a frame object and the code object)
If this question is too long to answer here, I'll happily take further reading suggestions or even examples to actual implementations instead. I'm really curious about the most common solutions.
Many languages let you check if an instance matches to another type let you use it in a new scope
For instance Rust has `if let`
if let Foo(bar) = baz {
// use bar here
}
Or Java
if (baz instanceof Foo bar) {
// use bar here
}
I would like to use this principle in my language and I'm thinking of an operator but I can't come up with a name: match, cast (it is not casting) and as symbol I'm thinking of >_
(because it looks like it narrowing something?)
baz >_ {
bar Foo
// use bar here
}
Questions:
What is this concept called? Is it pattern matching? I initially thought of the `bind` operator `>>=` but that's closer to using the result of an operation.
The release note is in r/seed7.
Summary of the things done in the 2025-01-11 release:
Some info about Seed7:
Seed7 is a programming language that is inspired by Ada, C/C++ and Java. I have created Seed7 based on my diploma and doctoral theses. I've been working on it since 1989 and released it after several rewrites in 2005. Since then, I improve it on a regular basis.
Some links:
Seed7 follows several design principles:
Can interpret scripts or compile large programs:
Error prevention:
Source code portability:
Readability:
Well defined behavior:
Overloading:
Extensibility:
Object orientation:
Multiple dispatch:
Performance:
No virtual machine:
No artificial restrictions:
Independent of databases:
Possibility to work without IDE:
Minimal dependency on external tools:
Comprehensive libraries:
Own implementations of libraries:
Reliable solutions:
It would be nice to get some feedback.
Recently i'm working on a project related to a programming language that i created.
I'm trying to design it around the idea of something fully agnostic, allowing the same language to be compiled, interpreted or shared to any target as possible.
As it's already a thing (literally every language can do this nowdays) i want something more. My idea was improve this design to allow the same language to be used as a system language (with the same software and hardware control of assembly and C) as well as a high level language like C#, python or javascript, with security features and easy memory management, abstracting the most the access to the hardware and the OS.
As my view, this is what could be a fully agnostic programming language, a language that can control any hardware and operating system as well as allows the user to build complete programs without needing to bother about details like memory management and security, everything in the same language with a simple and constant syntax.
When i try to show the image of what i want to create, is hard to make people see the utility of it as the same as i see, so i want some criticism about the idea.
I will bring more about the language in future posts (syntax, resource management and documentation) but i want some opinions about the idea that i want to share.
anyway thanks for reed :3
Compiling an implicational propositional logic proof to an SKI calculus involves translating each logical step of the proof into a corresponding SKI combinator. In implicational logic, the axioms (such as P -> (Q -> P)
and (P -> (Q -> R)) -> ((P -> Q) -> (P -> R))
) are represented by simple combinators like K (which ignores its second argument) and S (which applies a function to two arguments). Each application of these combinators directly encodes the logical structure of the proof in SKI calculus. For instance, the proof of an implication such as P -> (Q -> P)
would be represented by the K combinator. By systematically replacing axioms and applying inference rules, the entire proof can be reduced to a sequence of SKI combinators, yielding a program that is both a valid logical proof and an interpretable functional program in SKI calculus.
Such programs in SKI calculus offer several key advantages:
In essence, SKI programs constructed from theorems are reliable, predictable, and verifiable due to their foundation in constructive logic and formal reasoning.
I made a minimal prototype of such a compiler, and you can test it as one of the examples in the online Symbolverse playground: https://tearflake.github.io/symbolverse/playground/
Hello Everyone,
I always wanted a very simple and well defined computer architecture to play around with, so I made one. SVC16 aims to bring you part of the fun of building for a retro-console without having to understand hardware from the 1980s. Don't get me wrong, old hardware is cool, but I wanted something that has no undefined behavior. There is also a benefit to being a bit different: It takes away the temptation to copy someone else's compiler or tools.
I posted about this project a month ago and received a lot of feedback, so I thought I should give an update. - The details have now been finalized.
- There is now a document that contains everything you need to know to get started.
- I built a more advanced example game.
- Improvements of the emulator (gamepad support, scaling etc.)
Lately I've been thinking about implementing a typechecker by simply evaluating the entire program from top to bottom but with some notion on an "abstract value".
i.e most expressions will just return something like (int, *) instead of an actual (int, 10).
Expressions should still be able to catch type errors in this case.
Is there an actual name for this so I can find more literature?
Hello, i’m new to this language dev. I am trying to write a compile that will compile the program to run CUDA, how do I that?
Do i produce c++ code that uses cuda? What other options do i have? What kinda of knowledge do i need to know on top of this?
This is my first time writing a compiler and doing this generally and just wanna learn. Thank you for answering
Python is slow (partially) because it has an automatic garbage collector. C is fast (partially) because it doesn't. Are there any languages that have a gc but only run when called? I am starting to learn Java, and just found out about System.gc(), and also that nobody really uses it because the gc runs in the background anyway. My thought is like if you had a game, you called the gc whenever high efficiency wasn't needed, like when you pause, or switch from the main game to the title screen. Would it not be more efficient to have a gc that runs only when you want it to? Are there languages/libraries that do this? If not, why?
This is more curiosity than anything, though Toy's repo does have the sponsor stuff enabled.
Is there some kind of group that goes around boosting promising languages? Or is it a grass-roots situation?
Flaring this as a discussion, because I hope this helps someone.