Kedr programming language - Feedback wanted

I am making a programming language for games, and would like to get some feedback.

It is statically typed, with automatic and manual memory management. Compiles into C.

https://denismarkelov.codeberg.page/book

2 Likes

Wow, that’s an ambitious project! I do not question your motives, it’s probably quite fun to design a new language, but what is your motivation? What do you feel is lacking in other languages such as Lua, Zig, Rust, C etc (I do not keep tabs on new languages so there’s probably newer and more hyped languages out there). What are the problems you are solving with Kedr that others fail to solve?

4 Likes

How I see the current situation.

Lua is good while the game is small. Zero build time and hot reload would still be its advantages over Kedr. For bigger games, the type system and performance become more important, and Lua is no longer viable. Teal pushes the boundary slightly.

Zig and Rust have facilities to make low-level programming safer. But game logic is more about high level, which was never a goal for them.

C++ was a proper language for games at first. It is fast and has objects. Natural improvement could be a language with the same strengths, automatic memory management and more safety. Since such language wasn’t available, C# served as a temporary replacement. Temporary, because it has GC and runtime.

That is where Kedr comes in.

Some languages almost fit, like Swift or Nim. But there are risks. For example, what if reference counting ends up taking too much time? In Kedr any type can be switched into manual mode, just for this case, because it is made for games specifically.

1 Like

Not to object to your project, it sounds fun, but just to prevent misinformation on the internet :joy::

a) LuaJIT is in some cases just as fast as C (at least on my machine) and overall is quite fast.

b) Don’t Starve (for one well-known example) is primarily written in Lua, so clearly it is perfectly viable for bigger games (whether any individual programmer or company sees it as attractive for their own use is their personal choice of course).

Have fun!

3 Likes

Don’t Starve has its core written in C++. Like the most critical part, which Lua would a bad choice for.
At it was released a long time ago, Lua was basically the only option if you wanted your custom engine to be scriptable by users. So saying it’s perfectly viable for bigger games based on that example is misleading.

I fully support the development of new interesting languages. Personally I like Jai and Odin at the moment. I think they are suited very well for gamedev. Some companies who have resources develop their own scripting languages, mostly with static typing (luau, Daslang/daScript) so there is a demand for sure.

One of the big struggles I experience as a developer working on other’s projects is when I am given a huge Lua codebase and I have to figure out what the hell is going on there. It takes a lot of time. No static type system makes finding bugs in such codebases a nightmare, and very often it is type missmatch bugs. Heavy use of messaging also contributes to the overall chaos when you don’t know what code follows which.

Even when I’m working on my Lua projects with type annotations I still have to be very careful with the types and remember to update annotations during refactoring or just simply throughout object’s lifetime. It takes a lot of my cognitive resources which I’d much rather spend elsewhere during development.

3 Likes

Yes, exactly like any game made with Defold.

Perhaps I got a bit colloquial there. I didn’t say “perfect”, I said “perfectly viable”, meaning: “viable to a complete or adequate extent”.


Regardless of the advantages of more strict languages, most of the problems you describe aren’t limited to them. Those are just universal programmer errors, symptoms of poor code or lack of documentation.


One of my personal gripes with more strict and structured languages is that they often assume that you are using a specific (and generally humongous) IDE and/or other tools. Sometimes it seems like it’s more about the tools rather than the language itself. You try using them with a simple code editor with only syntax highlighting…:man_shrugging:. Not many people want to rewrite their own versions of those tools, so you end up with a sort of monopoly and you’re stuck with only a very few options. A language shouldn’t come with a required text editor.


“Content of a function is indented by four spaces.”

Four-space indentation isn’t actually enforced in Kedr, is it?!

I am also writing an IDE. Right now it is a code editor with syntax highlighting, which can run a compiler and navigate to errors.

Four spaces are enforced.

Nim has manual memory management as well

Personally, I feel a static type system on a scripting language is misguided.

Gradular typing gives the coder the freedom to choose quick iterations at the beginning and static types as the complexity increases.

I suggest something like Julia’s type system: You can do 100% static typing, 100% with explicit annotations, 100% inferred, 100% dynamic, or a mix of all that and more, and basically at any time.

The only exception is when you use multiple dispatch: Since you dispatch on type signatures, you explicitly type your code when your code becomes so complex that multiple dispatch becomes needed.

If any type system at all (I prefer Clojure, and even untyped Lua with good documentation and functional programming techniques), I would give Julia a good look, for inspiration.

A language that enforces typing is a no-no for me now (after 7 1/2 years of F#, and exclusively looking for enforced typed languages) especially so for a scripting language.

Also see this: https://www.youtube.com/watch?v=8Ab3ArE8W3s

1 Like

Good talk! Thank you for sharing!

1 Like

It really depends on the usage and preferences. Small scripts - sure, Lua is fine, Python as well. When the code base becomes large enough, the problems start to appear. So the new languages try to cover that niche. And then there are preferences - someone likes to avoid static typing and that helps with quick prototyping or readability, someone likes to avoid typeless code even in simple scripts (like me), one of the reasons is as the software develops or time passes the context is getting lost, static typing helps to preserve intentions, helps understanding the code by other developers and catches bugs early when APIs change. Gradual typing is a good compromise but it introduces inconsistency and the fear of not knowing what’s under the hood, for instance your code might be typed but a library that you are using is not, or you might to forget to type one piece of your code somewhere deep inside and it would be hard to find out, that leads to uncertainty. When you are coding with certainty (are the types sound, does a function mutate the data or not, are there side effects or the function is clean, are any exceptions possible, error handling of execution, can it be null, do I have to perform bound checks) it frees your mind to worry about more important things - your actual algorithms.

4 Likes

Gradual typing is a good compromise but it introduces inconsistency and the fear of not knowing what’s under the hood, for instance your code might be typed but a library that you are using is not, or you might to forget to type one piece of your code somewhere deep inside and it would be hard to find out, that leads to uncertainty.

Thats when its wonderful, that you can simply add a simple macro at the main function, and all the inferred types are type checked.

When you are coding with certainty (are the types sound, does a function mutate the data or not, are there side effects or the function is clean, are any exceptions possible, error handling of execution, can it be null, do I have to perform bound checks) it frees your mind to worry about more important things - your actual algorithms.

Sure, coding with certainty is awesome. And not having the types stand against me at every step of the way, is one part that I like to be certain about. So I can focus on the actual algorithms.

I feel like a core part of why dynamic languages become too cumbersome to deal with in larger codebases, is because they are simply not well architected, documented, and maintained.

All things considered, I prefer spec or malli for the purposes that I used types before, since they are more flexible by offering e.g checks on ranges, they can define and enforce constraints at runtime, verify not just types, but also the shape and semantics of data, and they allow you to define custom validation logic, and so on.

They offer more functionality and restrict me less.

2 Likes

Just random thoughts from a random guy…

What would make people choose Kedr over C? What real world problems will it help to solve and at what cost? Does pros outweigh the cons? How big or low will be the entry barrier (developer experience, debugging, tooling, interoperability with C libraries)?

A programming language is just tip of the iceberg. Usually, when people choose one language over another in most cases they choose everything that comes with the language, but not the language itself. In example, when people choose between let’s say Go, Ruby, Elixir, Rust… they are not just choosing a syntax or dynamic vs static typing or abstraction level (low vs high). They are also choosing what they value more: good performance, big amount of libraries, developer experience, concurrency, memory safety, etc.

In example, staying in Defold context… there is Lua and there is Teal. Teal does solve a problem with dynamic types. There is a compiler and type checking. On the other hand it introduces other problems. So will it make sense for everyone to jump onto it? Depends on one’s priorities. Will Kedr solve more problems than Lua or Teal without introducing too many other problems?

I am also writing an IDE. Right now it is a code editor with syntax highlighting, which can run a compiler and navigate to errors.

This will be one more entry barrier to adopt the language. Most devs would not be sacrificing their favorite editor for a new language. Implementing an LSP might help lowering the entry barrier.

3 Likes

I’ve been browsing for a “better C” language, and what I miss in how they are often presented is the day-to-day experience of working in them using the tooling that’s available.

The common case for someone evaluating Kedr, I imagine, would be a solo dev or small team with a set of already existing 1st and 3rd party C/C++ libraries, a framework or engine, and a set of tools and scripts for writing, refactoring, building, debugging, testing etc. In this situation, I want to know how I can integrate Kedr — how will it interface with my existing code, can I write and debug it with my tools, and so on.

As mentioned above, it would be helpful to have a more thorough description of the intended use-case of Kedr. On a higher level, what distinguishes it from other languages that a reader is likely to be considering, and how does it slot in among these other languages?

Personally, I’ve been looking at Zig, C3, V, Odin, D, Beef, Nim, Crystal, Daslang, and others. These would be the languages (in addition to the big ones like C and C++) that I would evaluate Kedr against.

Having a bespoke IDE for Kedr, I think, makes more sense if the intention is to make it into more than a code editor (like Tomorrow Corporation’s quite impressive IDE). Otherwise, I would prefer using vscode or similar, since it would allow me to edit my Kedr, C, yaml, docs etc. all in the same editor.

2 Likes

Interaction with C was one of the key priorities for Kedr. It is described in documentation, and here you can see the Vulkan bindings as an example. I will not be making integrations for other editors however, as I am not using them.

I think games absolutely require a language with automatic memory management and no garbage collector. From your list only Nim matches, which I decided against because it doesn’t have a custom IDE.

1 Like

What are you referring to by non-GC automatic memory management? Do you mean things like different types of allocators, like arena/region and object pools, reference counting for individual objects like C++'s shared_ptr, or something different?

If I understand you correctly, these things would be built in to the language so that e.g. you don’t have write std::shared_ptr<my_type> or manually call library functions for setting up an allocator for a task, section or what have you?

Could be worthwhile to consider the argument for tabs.

I am talking about reference counting. Programmer would only have to add the @weak attribute to prevent strong cycles.

1 Like

Lua is a good choice for bigger games, as well as smaller ones.

Static typing is in a language to give the compiler information it needs. It is not a code assurance tool (‘hey my code compiles so it must be fine!’ doh).

Scripting is ideal for fast prototyping a game, the code might be a mess and who cares you have a working idea. To develop it further, first pay the technical-debt, and refactor.

The Defold code editor has lots of helpful functionality for writing code, including nailing down function parameters (Writing code).

Lua is good for writing clean,safe scale-able code. It has comprehensive error handling (pcall, xpcall, assert, debug etc). Modules can be compiled with Luac, local unit tests can be added to modules, for compile time testing. Variable scoping can be constrained maximally. Tables can be made read-only. Closures are first class with lexical scoping, up value access, full tail calls, non-global functions. Environments can be made non-global.
The two rules of optimisation are “don’t do it” and “don’t do it yet”, C extensions are easy to implement if really required. Garbage collect can be controlled if really needed, which it probably will not be.

Static typing has the side effect of being a handy little (very limited) test, however for absolute proper full on code assurance, Test Driven Development (TDD) is the answer.
This is independent of programming language used.