mers rewrite is starting to be usable

This commit is contained in:
Mark
2023-08-14 17:17:08 +02:00
parent e549b1a5be
commit 2a7cb08596
50 changed files with 1411 additions and 407 deletions

View File

@@ -1,12 +1,9 @@
# mers
Mers is getting a rewrite!
Mers is a high-level programming language.
It is designed to be safe (it doesn't crash at runtime) and as simple as possible.
This means that this README isn't complete,
many things will change,
and the docs/ are for a completely different language.
## why mers?
## what makes it special
### Simplicity
@@ -15,18 +12,21 @@ But this means that many things you may be familiar with simply don't exist in m
because they aren't actually needed.
This includes:
**Exceptions**, because errors in mers are values just like any other.
**Exceptions**, because errors in mers are just values.
A function to read a UTF-8 text file from disk could have a return type like `String/IOError/UTF8DecodeError`,
which tells you exactly what errors can happen and also forces you to handle them (see later for mers' type-system).
**Loops**, because, as it turns out, a function which takes an iterable and a function can do this just fine.
**Loops**, because, as it turns out, a function which takes an iterable and a function can do this just fine:
```
my_list := (1, 2, 3, "four", "five", 6.5).as_list
(my_list, val -> val.println).for_each
```
Javascript has `forEach`, Rust `for_each`, C# `Each`, and Java has `forEach`.
At first, it seemed stupid to have a function that does the same thing a `for` or `foreach` loop can already do,
but if a function can do the job, why do we even need a special language construct to do this for us?
To keep it simple, mers doesn't have any loops except for `loop`.
`loop` simply repeats until the inner expression returns `(T)`, which causes loop to return `T`.
To keep it simple, mers doesn't have any loops - just functions you can use to loop.
**Breaks** aren't necessary, since this can be achieved using iterator magic or by returning `(T)` in a `loop`.
**Breaks** aren't necessary, since this can be achieved using iterators or by returning `(T)` in a `loop`.
It is also similar to `goto`, because it makes control flow less obvious, so it had to go.
The same control flow obfuscation issue exists for **returns**, so these also aren't a thing.
@@ -37,18 +37,41 @@ Why? Because we don't need anything else.
A function with no arguments now takes an empty tuple `()`,
a function with two arguments now takes a two-length tuple `(a, b)`,
a function with either zero, one, or three arguments now takes a `()/(a)/(a, b, c)`,
and a function with n args takes a list, or a list as part of a tuple, or an optional list via `()/<the list>`.
and a function with n arguments takes a list, or a list as part of a tuple, or an optional list via `()/<the list>`.
### Types
### Types and Safety
Mers is built around a type-system where a value could be one of multiple types.
This is basically what dynamic typing allows you to do:
x := if condition { 12 } else { "something went wrong" }
```
x := if condition { 12 } else { "something went wrong" }
```
This would be valid code.
However, in mers, the compiler still tracks all the types in your program,
and it will catch every possible crash before the program even runs:
If we tried to use `x` as an Int, the compiler would complain since it might be a string.
If we tried to use `x` as an int, the compiler would complain since it might be a string, so this does not compile:
```
list := (1, 2, if true 3 else "not an int")
list.sum.println
```
(note: type-checks aren't implemented since the rewrite is just barely functional, but they will be there and fully working soon)
Type-safety for functions is different from what you might expect.
You don't need to tell mers what type your function's argument has - you just use it however you want as if mers was a dynamically typed language:
```
sum_doubled := iter -> {
one := iter.sum
(one, one).sum
}
(1, 2, 3).sum_doubled.println
```
We could try to use the function improperly by passing a string instead of an int:
```
(1, 2, "3").sum_doubled.println
```
But mers will catch this and show an error, because the call to `sum` inside of `sum_doubled` would fail.
(note: type-checks aren't implemented for all functions yet, you may need to use `--check no` to get around this and deal with runtime panics for now)
## docs
docs will be available some time. for now, check mers_lib/src/program/configs/*