From c5d1246cd8349fe27d683d9152383e645e845595 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 6 May 2023 22:54:33 +0300 Subject: Create README.mg --- README.md | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) (limited to 'README.md') diff --git a/README.md b/README.md index e69de29..d7064b0 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,193 @@ +# Ek + +Ek (oak in Swedish) is my toy programming language. +Currently far from a usable state, but I thought I might +still put it up on GitHub. Get them green squares, yo. + +# Building + ++ `make` + +Add `RELEASE=1` to enable optimizations. + +# Ek features and target use case + +Ek is inteded to be a simple language, similar to C with little to no runtime but with +some quality of life improvements, mainly stuff already seen in other languages. +Nothing particularly ground-breaking. + +# Tests + +Tests are currently broken, I'm going to have to come up with some half decent +testing framework. + +## Feature showcase + +In no particular order of importance or significance. +Check the tests for some more examples. + +### C++-style comments +``` +// inline comment +/* + multi line comment + */ +``` + +Additionally, comments are allowed in comments: +``` +/* comment 1 + /* comment2 */ +*/ +``` + +### Right to left type declarations +``` +// an array of eight pointers to u32 +a [8]'u32; +// a pointer to an array of eight u32 +b '[8]u32; +``` + +### Unified function declaration syntax +``` +// function definition +some_func(a u8, b u16 => i32){ + // function pointer to some_func + a_callback '(u8, u16 => i32) = some_func; +} +``` + +### More legible casts +``` +b f32; +a u32 = b as u32; +``` + +### Immutable by default +``` +// immutable i64 +a i64 = 32; +// mutable u32 +b mut u32 = 32; +``` + +### Type inference +``` +// immutable i64 (integer constants are by default the largest signed type) +a const = 32; +// mutable u32 +b mut = 32 as u32; +``` + +### Strong(er) type system +``` +// ERROR +a u32 = 20.0f; +// OK +a u32 = 20.0f as u32; +``` + +### Defer +``` +a const = alloc(16); +defer(dealloc(a)); +``` + +### Shadowing is disallowed +``` +a u32; +{ + // ERROR + a f32; +} +``` + +Possibly controversial, but I've only ever run into shadowing bugs, +haven't really found it to be a useful feature. + +### Function overloading +``` +some_func(u32, u64){} +some_func(u32, u32){} +``` + +### Interfaces +``` +// accepts any type, but you're not allowed to do anything with it +typedef any {} +// any type where there exists a function add_one(some_type => some_type) +// fullfills the interface +typedef addable { + add_one(addable => addable); +} +``` + +Interfaces are a bit more complex with peculiarities I'm still not entirely sure about, +TODO. For example, +``` +typedef some_type { + add(some_type, some_type => some_type) +} + +// does this fullfill some_type for u32 and u64? Or neither? +add(u32, u32 => u64){} +``` + +These could be fairly easily solved with some extra syntax, but I would really prefer +keeping function syntax in the top context without extra decorations. Maybe just me. +However, as long as I pick an interpretation and stick to it, should be fine. + +### Generics through interfaces +``` +struct some_struct (A some_interface, B some_other_interface) { + a T; + b B; +}; +``` + +Note that each type must implement some interface. Similarly, procedures +can take an interface as the type which makes it 'generic', but type parameters are not +supported: +``` +do_something(a some_interface){ +// you can only call functions and read members that the interface defines +} +``` + +This type of interfaces and overloading are tricky to support at the same time, but +I currently use a left-to-right actualization. That is, in each parameter 'index' +there can only be actual types (`u32`, `i64`, `some_struct`), or a fallback 'generic' +interface. Each parameter type is matched to the argument type, and if none of the actual types match, +the fallback is checked. If it also fails, no function implements the requested types. + +This is to avoid cases where two interfaces would both be implemented by a type, leading +to unambiguous function resolutions. This system is inherently less powerful than what +C++ for example has, but might be more flexible than Rust, for example. + +### Hidden by default +``` +// visible through import +pub some_func(){} +// not visible through import +some_other_func(){} +``` + +### Public imports +``` +// visible in this file and through import +pub import "some_file.ek"; +// only visible in this file +import "some_file.ek"; +``` + +# Architecture + +At the moment I'm aiming for transpiling Ek to C. I'm hoping that it will be possible +to add other transpilation targets, for example JavaScript. + +# Name + +Ek is the current name, mainly because I like oaks and didn't seem to step on anyone's toes. +I had a number of names I toyed around with before pushing to GitHub, any mentions of other +names should be disregarded and preferrably fixed. -- cgit v1.3