317 lines
5.5 KiB
Markdown
317 lines
5.5 KiB
Markdown
# meow
|
|
|
|
most awesome language, mainly because it's not object-oriented and it's called meow.
|
|
|
|
Multiple dispatch!
|
|
|
|
Weird syntax!
|
|
|
|
Implicit interfaces, except we call them constraints! whyyyy did I do this?
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
<imports>
|
|
|
|
<declarations>
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### imports
|
|
|
|
```
|
|
import "std:strings" as str // standard library
|
|
import "std:strings/ext" as strext // nested
|
|
import "foo:bar" as fb // file bar from project foo
|
|
import ":foo/bar" // relative to project root
|
|
import "foo" // relative to current file
|
|
import "./foo" as whatever // relative to current file
|
|
import "../foobar" // relative to current file
|
|
```
|
|
|
|
access public thingies from imports with `:`
|
|
|
|
```
|
|
import foo;
|
|
|
|
foo:somefunction();
|
|
foo:SomeType
|
|
foo:SomeConstraint
|
|
```
|
|
|
|
|
|
### functions
|
|
Functions are by default private to the current file, functions with `pub` are accessible from other files/projects.
|
|
```
|
|
fn x() {}
|
|
pub fn y() {}
|
|
```
|
|
|
|
Functions can take the `[c_export]` attribute to make them callable when compiled as a static library, and to generate C headers for them.
|
|
```
|
|
[c_export] pub fn foo(int a, Foo b, Bar c) -> int {
|
|
|
|
}
|
|
|
|
[c_export("renamed_foo2")] pub fn foo2(int a, Foo b, Bar c) -> int, int {
|
|
|
|
}
|
|
```
|
|
|
|
Functions can be overloaded on parameter and return types
|
|
```
|
|
fn a() -> s32 {
|
|
return -1;
|
|
}
|
|
fn a() -> u32 {
|
|
return 1;
|
|
}
|
|
|
|
fn a(i32 x, i32 y) -> (i32, i32) {
|
|
return y, x;
|
|
}
|
|
|
|
fn a(u32 x) -> u32 {
|
|
return x + 1;
|
|
}
|
|
```
|
|
|
|
### constraints
|
|
constraints are kind of weird because they
|
|
- can have multiple types, like, a constraint can constrain multiple types together
|
|
- can be used both as a constraint on generic types and as a type themselves
|
|
- but only can be used as a type when they constrain only one type, and then they're kinda like an interface?
|
|
- fuck this is weird
|
|
|
|
```
|
|
// this one can be used only as a constraint for generic type parameters
|
|
constraint Foo on A B {
|
|
some_func(A, B);
|
|
some_other_func(A) -> B;
|
|
}
|
|
|
|
// this one can be used both as a constraint for generic type parameters or as an interface type
|
|
constraint Bar on A {
|
|
f1(A) -> A;
|
|
f2(A) -> i32;
|
|
}
|
|
```
|
|
|
|
```
|
|
// usage as type parameter constraints
|
|
fn foo<T1, T2>(T1 x)
|
|
where Foo T1 T2
|
|
{
|
|
T2 y = some_other_func(x);
|
|
some_func(x, y);
|
|
}
|
|
|
|
fn bar<T>(T a) -> i32
|
|
where Bar T
|
|
{
|
|
T b = f1(a);
|
|
return f2(b);
|
|
}
|
|
|
|
// usage as interface types
|
|
|
|
Bar x = getSomeTypeThatIsBar();
|
|
Bar y = f1(x);
|
|
```
|
|
|
|
constraints can be embedded in other constraints like this:
|
|
```
|
|
constraint Arithmetic on A {
|
|
operator+ (A, A) -> A;
|
|
operator- (A, A) -> A;
|
|
operator* (A, A) -> A;
|
|
operator/ (A, A) -> A;
|
|
}
|
|
|
|
constraint Foo on A {
|
|
Arithmetic A;
|
|
some_func(A) -> A;
|
|
}
|
|
|
|
```
|
|
|
|
|
|
```
|
|
int a = 1;
|
|
mut int b = 2;
|
|
|
|
let a = 1;
|
|
mut let b = 2;
|
|
|
|
```
|
|
|
|
### literals
|
|
#### numeric
|
|
Numeric literals are untyped but literals with a decimal point can not be used as integers.
|
|
They can contain underscores between digits which are ignored, e.g. `1_000` or `1_0_0_0`.
|
|
Unprefixed numeric literals are decimal, prefixes exist for hexadecimal (`0x`), octal (`0o`) and binary (`0b`).
|
|
|
|
#### character
|
|
The character literal is a single unicode character enclosed in single quotes, its value is the character's unicode code point.
|
|
|
|
#### bool
|
|
`true` and `false`
|
|
|
|
#### string
|
|
String literals are enclosed in double quotes (e.g. `"hello world"`).
|
|
Their type is an `u8` array with length of the string in bytes.
|
|
|
|
|
|
### types
|
|
#### basic types
|
|
- bool: `bool`
|
|
- signed integer types: `s8`, `s16`, `s32`, `s64`, `s128`
|
|
- unsigned integer types: `u8`, `u16`, `u32`, `u64`, `u128`
|
|
- floating point types: `f32`, `f64` (possibly more?)
|
|
- decimal type? `decimal`
|
|
- complex types? `c64`, `c128` (does this refer to the total size or the size of each component?)
|
|
|
|
|
|
#### compound types
|
|
##### array & slice
|
|
###### declaration
|
|
```
|
|
// array
|
|
[u8; 10]
|
|
// slice
|
|
[u8]
|
|
```
|
|
###### use
|
|
```
|
|
let a: [u8] = "foo";
|
|
let b: u8 = a[1];
|
|
let d: [s32; 4] = {1,2,3,4};
|
|
let e = [u8]{1,2,3,4};
|
|
```
|
|
##### struct
|
|
###### declaration
|
|
```
|
|
struct Point {
|
|
s32 x;
|
|
s32 y;
|
|
s32 z;
|
|
}
|
|
type Point = struct {
|
|
s32 x;
|
|
s32 y;
|
|
s32 z;
|
|
}
|
|
|
|
type Options = struct {
|
|
struct {
|
|
int foo;
|
|
} api;
|
|
}
|
|
```
|
|
##### use
|
|
```
|
|
let p1 = Point{
|
|
x: 1,
|
|
y: 2,
|
|
z: 3,
|
|
};
|
|
let p2: Point = {
|
|
x: 2,
|
|
y: 3,
|
|
z: 4,
|
|
};
|
|
|
|
let x = p1.x;
|
|
|
|
p1.x = 2;
|
|
|
|
let opt = Options{
|
|
api: {
|
|
foo: 1
|
|
}
|
|
};
|
|
|
|
let a: Options@api = opt.api; // yeah this is weird, try to avoid it
|
|
|
|
```
|
|
|
|
##### enum
|
|
###### declaration
|
|
```
|
|
enum A {
|
|
Foo,
|
|
Bar(u8)
|
|
}
|
|
|
|
type A = enum {
|
|
Foo,
|
|
Bar(u8)
|
|
}
|
|
|
|
type B = enum {
|
|
X,
|
|
Y(enum { // this is terrible but you can do it if you want for consistency reasons
|
|
A,
|
|
B
|
|
})
|
|
}
|
|
|
|
```
|
|
###### use
|
|
```
|
|
let x = A'Foo;
|
|
let y = A'Bar(10);
|
|
let z = B'Y(B@Y'A); // don't do this why would you do this
|
|
```
|
|
|
|
##### tuple
|
|
###### declaration
|
|
```
|
|
type X = (s8, s8);
|
|
tuple X(s8, s8);
|
|
type Y = (struct {int a; int b}, enum {A, B}); // why would you do this aaaaa
|
|
```
|
|
###### use
|
|
```
|
|
let a: X = (1,2);
|
|
let b = a.0;
|
|
let c = a.1;
|
|
let d = Y({a: 1, b: 2}, Y@1'A); // oh no
|
|
let e: Y@1 = d.1;
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### pointers
|
|
Pointers are taken with the `&` operator and dereferenced with the `*` operator. They are mostly similar to C I think.
|
|
Pointer types have a `*` appended to the type they point to.
|
|
|
|
```
|
|
let a: int = 1;
|
|
let b: int* = &a;
|
|
let c = *b;
|
|
```
|
|
|
|
A special `void*` type exists???? does it really? maybe? kinda yes? aaaaaaa
|
|
|
|
|
|
Pointer arithmetic works the same as in C, except that arithmetic on void pointers is allowed?
|
|
|
|
```
|
|
let a: [u8; 2] = {0,1};
|
|
let b: u8* = &a[0];
|
|
let c: u8* = b + 1;
|
|
let d: u8 = *b; // 0
|
|
let e: u8 = *c; // 1
|
|
*(&a[0]+1) = 2; // a is now {0,2}
|
|
```
|
|
|