Add my-own-programming-language.md

This commit is contained in:
germax26 2024-08-09 00:29:26 +10:00
parent 74f1826eb0
commit 0d96f03d30
Signed by: germax26
SSH Key Fingerprint: SHA256:N3w+8798IMWBt7SYH8G1C0iJlIa2HIIcRCXwILT5FvM

View File

@ -0,0 +1,43 @@
---
title: "My Own Programming Language"
date: 2024-08-08T23:04:34+10:00
tags: [ 'dev', 'python++' ]
---
Since [starting to really use emacs](/learning-emacs/), I have been using it to explore my old projects, and one in particular for today's discussion, that being [python++](https://git.germax26.net/germax26/python-plus-plus). It is a language that I made back in March of this year, as a result of my growing frustrations with Python.
## Python
I would consider Python to be my main language, with the vast, *vast* majority of the programming that I have done being in Python. I would not say that I am an expert in Python, but if I were to compare it to learning natural languages, I would say that I am fluent, in between a [C1 and C2 level](https://www.coe.int/en/web/common-european-framework-reference-languages/level-descriptions), as I have used some of the more advanced features of Python, such as [Metaclasses](https://docs.python.org/3.11/reference/datamodel.html#metaclasses) and [stack inspection](https://docs.python.org/3/library/inspect.html), which I would say are not usually used.
## Mypy
While using Python, one thing that I have pretty much always done is use the type hints, once I first found out about them. They not only allowed me to have proper intellisense in my editor (VSCode until literally this week), and I could also use programs such as [Mypy](https://www.mypy-lang.org/) to verify the types throughout my program. I use mypy so much that I have have a shortcut `mypython3` that is bound to a bash function that first runs mypy on a python file before executing it. Running my python code with just `python3` _feels unsafe_ to me. I don't really like Python's dynamic-ness. Whenever I did use it, I also guarded myself with union type hints and `isinstance` checks whenever I could.
## Python++
This language is the result of my frustrations, mainly with the type system of Python, but with certain other things as well. I called it "python++" since it was meant to replace Python for me. I wanted it to be statically typed, but also at the same level of abstraction as python. I wanted there to just be `str`s and `int`s without having to worry about memory management, but I also wanted the Algebraic Data Types that I longed for from languages such as Rust and Haskell. Whenever I did something that needed such things in Python, I always used ABCs with subclasses for each variant, and it was a whole messy ordeal which I would rather move on from. As a result, I could never really do some of the more powerful things that Rust and Haskell make so easy.
## My first iteration
My first attempt at implementing this language was hit-and-miss. I used [Crafting Interpreters](https://craftinginterpreters.com/) as an inspiration for the lexing and parsing code. I wrote an interpreter and I even got to the point of rewriting the language in itself. In the end, before I stopped working on it to work on other things, it was able to parse its own source code, and interpret a subset of all the commands that the Python implementation could. Speaking of which, the Python implementation, was, ... certainly something. It seems that I made my language into a kind of scripting language, similar to Python, which at the time was probably something I was going for. All the type checks, however, were done at run time. Every time you ran a function, it would check afterwards if the returned value was of the correct type, EVERY TIME YOU CALLED A FUNCTION. But it was not all doom-and-gloom. I did, as I set out to do, implement ADTs in a very satisfactory (for now) manner. You could define an Enum type like in Rust, with different variants, each with their own associated data, and you could use a `match` block to pattern match on the variant, destructuring the associated values into variables that could be used. I also implemented structs (a replace for all the `dataclass`es I used in python), and they worked correctly, I think, but they would lead to some strange decisions.
## Do While
After some time, however, I stopped working on the project. For some reason, I didn't even push the code to a private Github repository or anything. I guess I planned on coming back and cleaning it up. Well, I did end up coming back to it, while exploring my old projects after I started using Emacs. I remembered this old language that I made, and I looked through it, and remembered a certain decision that I made, regarding how the blocks under `if`s and `while`/`for` loops where implemented, which caused me to have a random though about `do`-`while` blocks. I decided to write it down into a markdown file, but in the process I came to realise a lot of things about my project. I would recommend to check out [do-while.md](https://git.germax26.net/germax26/python-plus-plus/src/branch/main/do-while.md), which explains the actual details of the problem with `do`-`while`, and also some decisions I made regarding the future of the language. Writing do-while.md is what inspired me to actually share this language on this blog, and to actually think critically about what I want this langauge to do.
## Jai and being a better programmer
Between me stopping and coming back, I think there was a big change in my ideas of what made a good language. It was at this time that I watched all of [A Programming Language for Games](https://www.youtube.com/playlist?list=PLmV5I2fxaiCKfxMBrNsU1kgKJXD3PkyxO), which introduced me to a lot of new ideas, and also it made me want to do more low level programming. I've always been a beginner in terms of low level code, only having written a little bit of C and modifying some Rust projects, but I have never done any normal projects in any of these languages. I had also watched pretty much all of Tsoding's videos, and I had picked up low level concepts from them, but I had never done anything with any of them. I had only ever been advanced in Python, and you probably know Python, being such a high level language compared to what C and Rust are. Watching A Programming Language for Games and Tsoding's videos showed me how much more control a programming language could give the programmer, and as a result, I have been inspired to move my language more to the low level end, so that I can give myself this control and also to learn about these concepts, both as I would implement my language, but then also use my language. I don't think a programmer is a serious developer if they don't use languages like C and so on, I don't even think I'm a serious dev at all, only really an amatuer, but these languages and the things I could do with them call out to me, and it just seems like the right fit for me, and so I want to be able to use this language to explore these ideas. Seeing many of the features in Jai also inspired me to try to see what I could do with my language. Features such as meta-programming, compile-time-execution, and some others seemed very cool to me.
## Plans for the future
As of now, all of this low-level stuff is just thoughts in my head and I've done nothing to actually action it. I don't think that I will be able to for some time, due to more pressing life matters at the moment, that will take up most of my time until December. Starting December, I will have a lot more free time in which I can actually work on this, but just for now, I want to map out some changes that I want to make. These are in no way the only things I want to do, as the language is certainly going to be massively overhauled from its current state, but these are just the ones that my tired brain can remember at this point in time.
1. Returns as values:
Currently, `return` is implemented in a very weird way, where it is an expression that returns an object of type `Return<T>`, and the interpreter will return from a function if it encounters a line that is just an expression that evaluates to return, i.e. `return ...`. I think the reason I structured it this way was because I had come up with this idea where a function can _return a `Return<T>`_ in order to tell the function that called it to return something. Looking back, I don't really know of any use cases for this. Maybe there are some, maybe not, but I am planning on removing this and just making `return` a normal keyword that indicates a return statement. If in the future there is a use for this, then I might implement it, but to me it seems that this is too niche of a feature and would require people using the feature to make too many assumptions.
2. Updated Struct, Enum, and Array syntax:
As I discuss in do-while.md, I want to use a syntax like `MyStruct.{}` and `int.[]` for my structs and arrays. Checkout do-while.md for more of an explanation.
3. More low level control:
Stuff like distinct types for different sizes of ints, and pointers are things that I want to allow a programmer to use. Basically what C allows you to do. For my vision of the language as more C-like, these are not really negotiable. I also plan to add allow interop with C through FFI.
4. Compilation:
It is quite hard for interpreted languages to meet adequete performance targets, and so I would like to switch my language over to being compiled. Currently it is just interpreting, building upon the Python runtime.
## Conclusion
I don't know. This really was just a ramble about a programming language I made and forgot about, only to come back to and have some grand ideas for. Hopefully I actually implement these ideas and have a servicable programming language that can be used for systems programming. I'm also not really bothered to write anything else for this post, as I am tired. Maybe I'll update it later. Hopefully using this project I will be able to become a better low level programmer in the process.