# 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 ``` 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(a: int, b: Foo, c: Bar): int { } [c_export("renamed_foo2")] pub fn foo2(a: int, b: Foo, c: Bar): int, int { } ``` Functions can be overloaded on parameter and return types ``` fn a(): s32 { return -1; } fn a(): u32 { return 1; } fn a(x: i32, y: i32): (i32, i32) { return y, x; } fn a(x: u32): 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 x) where Foo T1 T2 { T2 y = some_other_func(x); some_func(x, y); } fn bar(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; } ``` ### 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}; let f = d[1:3]; // f has type [s32] (slice) now type Arr = [u8]; let g = Arr[]{1,2,3}; ``` ##### struct ###### declaration ``` struct Point { x: s32; y: s32; z: s32; } type Point = struct { x: s32; y: s32; z: s32; } type Options = struct { api: struct { int foo; }; } ``` ##### 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} ``` ## operator precedence ``` . (struct member access), [] array subscripting unaries: + - ! ~, pointer dereference *, pointer reference &, binary operators: * / % + - << >> > >= < <= == != & ^ | && ^^ || lowest precedence, assignment: = += -= /= *= %= &= |= ^= <<= >>= ```