Sam Abbott-Kennedy's Avatar

Sam Abbott-Kennedy

@samothyk

[onlookers booing]

74
Followers
242
Following
48
Posts
28.09.2023
Joined
Posts Following

Latest posts by Sam Abbott-Kennedy @samothyk

Sounds like a game mechanic waiting to happen ๐Ÿ˜œ

12.03.2026 12:01 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
A snippet of my programming language showing optionals and early returns on optionals:
```
fn maybe(b: bool): ?u32 {
    if (b) return 10
    return none
}

fn opt_return(b: bool): ?u32 {
    let x = maybe(b)
    println(x?) //if x is none, return here, else print the value of x (10)
    println("x was some!")
    return x
}

fn main(): u32 {
    let x = opt_return(true)

    if (x) |value| {
        println(value + 10)
    } else println("x was none")

    let y = opt_return(false)
    if (y) |value| {
        println(value + 10)
    } else println("y was none")

    return 0
}
```

A snippet of my programming language showing optionals and early returns on optionals: ``` fn maybe(b: bool): ?u32 { if (b) return 10 return none } fn opt_return(b: bool): ?u32 { let x = maybe(b) println(x?) //if x is none, return here, else print the value of x (10) println("x was some!") return x } fn main(): u32 { let x = opt_return(true) if (x) |value| { println(value + 10) } else println("x was none") let y = opt_return(false) if (y) |value| { println(value + 10) } else println("y was none") return 0 } ```

The output of the program:
```
10
x was some!
20
y was none
```

The output of the program: ``` 10 x was some! 20 y was none ```

It's all coming together. Now I have unions I can implement the optional type ?T which is just a tagged union. In addition I could implement rust style try-unwrap of optionals basically for free with all the parts I have!
Here opt_return only prints x if it's some, else it returns early!
#compiler

12.03.2026 07:17 ๐Ÿ‘ 3 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Post image

Now with the fancy struct syntax, implementing tagged unions was relatively easy. Also got rid of all those pesky semicolons messing up the place
#compiler

11.03.2026 14:44 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Post image Post image

Blew apart my struct and function parsing to allow default values and named arguments. Pretty swanky imo
#compiler

10.03.2026 10:46 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Video thumbnail

Output of the program:

09.03.2026 12:12 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Post image

Not sure it's the greatest use of it but the new `with` statement works nicely with raylib ๐Ÿ˜…
#raylib #compiler

09.03.2026 12:12 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
A snippet of my programming language showing the defer statement:
```
fn main() {
    let f = os::open_file("test.txt");
    defer os::close(f);
    
    for _ in 0..15 {
        os::write(f, "Hello once again from osmium!\n");
    }
}
```

A snippet of my programming language showing the defer statement: ``` fn main() { let f = os::open_file("test.txt"); defer os::close(f); for _ in 0..15 { os::write(f, "Hello once again from osmium!\n"); } } ```

A snippet from my programming language showing the same code but using a `with` statement:
```
fn main() {
    with let f = os::open_file("test.txt"); { println("closing file!"); os::close(f); } {
        for _ in 0..15 {
            os::write(f, "Hello once again from osmium!\n");
        }
        println("done writing!");
    }
    println("end of main!");
}
```

A snippet from my programming language showing the same code but using a `with` statement: ``` fn main() { with let f = os::open_file("test.txt"); { println("closing file!"); os::close(f); } { for _ in 0..15 { os::write(f, "Hello once again from osmium!\n"); } println("done writing!"); } println("end of main!"); } ```

The output of the with statement variant showing the order in which things are run:
```
done writing!
closing file!
end of main!
```

The output of the with statement variant showing the order in which things are run: ``` done writing! closing file! end of main! ```

Added a defer statement to my language, but I didn't like how the resource acquisition and disposal had to be separated. So I added a with statement that just desugars to defer, and I kinda like it!
#compiler

09.03.2026 08:44 ๐Ÿ‘ 3 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
A program in my programming language showing pointer allocation and illegal freeing:
```
fn bad(ptr: &u32) {
    free ptr;
}

fn main() {
    let x = new u32;
    free x;

    let i = 10;
    let p = &i;
    free p;
}
```

A program in my programming language showing pointer allocation and illegal freeing: ``` fn bad(ptr: &u32) { free ptr; } fn main() { let x = new u32; free x; let i = 10; let p = &i; free p; } ```

The error messages from compiling the program:
```
Error: Cannot free a pointer with lifetime `Param` at src\main\resources\examples\memory.os:2:5
2 |     free ptr;
  |     ^^^^^^^^^
Error: Cannot free a pointer with lifetime `Stack` at src\main\resources\examples\memory.os:11:5
11 |     free p;
   |     ^^^^^^^
```

The error messages from compiling the program: ``` Error: Cannot free a pointer with lifetime `Param` at src\main\resources\examples\memory.os:2:5 2 | free ptr; | ^^^^^^^^^ Error: Cannot free a pointer with lifetime `Stack` at src\main\resources\examples\memory.os:11:5 11 | free p; | ^^^^^^^ ```

Starting on the memory management for my language. Nothing fancy but just a few more guard rails than C. Every pointer has an "origin": Stack, Param, Heap, or Global. Only Heap can be freed, and Stack can't be returned from functions.
Maybe this will cause problems but we'll see!
#compiler #llvm

08.03.2026 14:40 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
Video thumbnail

Osmium Raylib ffi speedrun

#compiler #llvm #raylib

04.03.2026 14:17 ๐Ÿ‘ 2 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Using FFI and modules to make an os.os file that's imported to write to a file:
`os.os`:
```
extern fn exit(status: u32);
extern struct FILE();

extern fn fopen(filename: &const char, mode: &const char): &FILE;
extern fn fputs(s: &const char, file: &FILE): u32;
extern fn fclose(file: &FILE);

struct File(handle: &FILE) {
    fn write(self: File, s: string): u32 {
        return fputs(s.data, self.handle);
    }

    fn close(self: File) {
        fclose(self.handle);
    }
}

fn open_file(filename: string): File {
    return File(fopen(filename.data, "w".data));
}
```
files.os:
```
import "core/os.os";

fn main() {
    let f = os::open_file("test.txt");
    for _ in 0..10 {
        os::write(f, "Hello again from osmium!\n");
    }
    os::close(f);
}
```
test.txt:
```
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
Hello again from osmium!
```

Using FFI and modules to make an os.os file that's imported to write to a file: `os.os`: ``` extern fn exit(status: u32); extern struct FILE(); extern fn fopen(filename: &const char, mode: &const char): &FILE; extern fn fputs(s: &const char, file: &FILE): u32; extern fn fclose(file: &FILE); struct File(handle: &FILE) { fn write(self: File, s: string): u32 { return fputs(s.data, self.handle); } fn close(self: File) { fclose(self.handle); } } fn open_file(filename: string): File { return File(fopen(filename.data, "w".data)); } ``` files.os: ``` import "core/os.os"; fn main() { let f = os::open_file("test.txt"); for _ in 0..10 { os::write(f, "Hello again from osmium!\n"); } os::close(f); } ``` test.txt: ``` Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! Hello again from osmium! ```

Yeah like that

04.03.2026 11:08 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
A program in my programming language showing FFI:
```
extern fn exit(status: u32);
extern struct FILE();

extern fn fopen(filename: &const char, mode: &const char): &FILE;
extern fn fputs(s: &const char, file: &FILE): u32;
extern fn fclose(file: &FILE);

fn main() {
    let file = fopen("test.txt".data, "w".data);
    if file == null {
        println("Could not open file!");
        exit(1);
    }

    for _ in 0..10 {
        fputs("Hello from osmium!\n".data, file);
    }
    fclose(file);
}
```

A program in my programming language showing FFI: ``` extern fn exit(status: u32); extern struct FILE(); extern fn fopen(filename: &const char, mode: &const char): &FILE; extern fn fputs(s: &const char, file: &FILE): u32; extern fn fclose(file: &FILE); fn main() { let file = fopen("test.txt".data, "w".data); if file == null { println("Could not open file!"); exit(1); } for _ in 0..10 { fputs("Hello from osmium!\n".data, file); } fclose(file); } ```

The output in a new file `test.txt`
```
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
Hello from osmium!
```

The output in a new file `test.txt` ``` Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! Hello from osmium! ```

Decided the next logical step from modules was ffi, surprisingly straightforward to implement! Now I can tuck all that nasty ffi code in a libc.os or something
#compiler

04.03.2026 10:54 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0

The way it works is horribly inefficient, it takes the main file and parses it and gathers every type and function declared. Then it takes every import statement, finds the file it points to and then repeats the process recursively to build a graph. Then the graph is DFS'd to emit one llvm file!

04.03.2026 07:53 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
A picture of 3 separate files in my programming language that form a dependency chain. main.os imports io.os and math.os, math.os imports io.os.
main.os:
```
import "math.os";
import "io.os";

fn main() {
    io::print_msg("Hello from main.os!");
    var v = math::Vec(1.0, 2.0);
    println(math::dot(v, v));
    var x = math::pow(2.0, 3);

    println(x);

    math::greet();
}
```
math.os:
```
import "io.os";

struct Vec(x: f32, y: f32) {
    fn dot(v1: Vec, v2: Vec): f32 {
        return v1.x * v2.x + v1.y * v2.y;
    }
}

fn pow(x: f32, p: u32): f32 {
    for _ in 1..p x = x * x;
    return x;
}

fn greet() {
    io::print_msg("Hello from math.os!");
}
```
io.os:
```
fn print_msg(msg: string) {
    println(msg);
}
```

A picture of 3 separate files in my programming language that form a dependency chain. main.os imports io.os and math.os, math.os imports io.os. main.os: ``` import "math.os"; import "io.os"; fn main() { io::print_msg("Hello from main.os!"); var v = math::Vec(1.0, 2.0); println(math::dot(v, v)); var x = math::pow(2.0, 3); println(x); math::greet(); } ``` math.os: ``` import "io.os"; struct Vec(x: f32, y: f32) { fn dot(v1: Vec, v2: Vec): f32 { return v1.x * v2.x + v1.y * v2.y; } } fn pow(x: f32, p: u32): f32 { for _ in 1..p x = x * x; return x; } fn greet() { io::print_msg("Hello from math.os!"); } ``` io.os: ``` fn print_msg(msg: string) { println(msg); } ```

The output of the program:
```
Hello from main.os!
5.000000
16.000000
Hello from math.os!
```

The output of the program: ``` Hello from main.os! 5.000000 16.000000 Hello from math.os! ```

I managed to implement a somewhat halfway decent module system. I'm not thrilled that the import needs the relative path but it'll do for now. Plus it handles the same file being imported multiple times across the compilation graph ๐Ÿ˜Œ

#compiler #llvm

04.03.2026 07:49 ๐Ÿ‘ 2 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
A program in my programming language showing string slicing:
```
fn main() {
    var s: string = "Hello from osmium!";
    println(s);
    println(s[6..=10]);

    var sl = s[8..17];
    println(sl);

    for c in s[0..5] {
        print(c);
        print(' ');
    }
}
```

A program in my programming language showing string slicing: ``` fn main() { var s: string = "Hello from osmium!"; println(s); println(s[6..=10]); var sl = s[8..17]; println(sl); for c in s[0..5] { print(c); print(' '); } } ```

The output of the program:
```
Hello from osmium!
from 
om osmium
H e l l o 
```

The output of the program: ``` Hello from osmium! from om osmium H e l l o ```

Added strings to my language, since they're just backed by a slice of u8's all the regular slice operations just worked out of the box

Again nothing real languages don't do but it's so satisfying seeing it work!
#compiler #llvm

01.03.2026 10:51 ๐Ÿ‘ 4 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0

Something about the automatic printing of structs is very pleasing to me. It's incredibly simple and the print function is just one enormous hack at the moment but for debugging the compiler it's so good

28.02.2026 09:50 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
A program in my programming language showing array slicing:
```
fn print_slice(sl: []u32) {
    for i in sl print(i);
}

fn main() {
    var a = [*]u32 { 4, 5, 6, 7 };
    print_slice(&a);

    var sl: []u32 = a[2..=3];
    print_slice(sl);
    print(sl); //prints the raw underlying struct { ptr, len }

    sl[0] = 1; //mutate the original array through the slice, makes sense since []T == &[N]T
    for x in a print(x);
}
```

A program in my programming language showing array slicing: ``` fn print_slice(sl: []u32) { for i in sl print(i); } fn main() { var a = [*]u32 { 4, 5, 6, 7 }; print_slice(&a); var sl: []u32 = a[2..=3]; print_slice(sl); print(sl); //prints the raw underlying struct { ptr, len } sl[0] = 1; //mutate the original array through the slice, makes sense since []T == &[N]T for x in a print(x); } ```

The output of running the program:
```
4
5
6
7
6
7
{ &[0x61dff2e8], 2 }
4
5
1
7
```

The output of running the program: ``` 4 5 6 7 6 7 { &[0x61dff2e8], 2 } 4 5 1 7 ```

One huge rewrite later and a brand new backend (LLVM) and I'm extremely happy with my programming language's slices. Nothing fancy that any other real language doesn't do but it's fun seeing my scrappy little compiler go.
#compiler

28.02.2026 08:05 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
Post image

Taking structs to weird new places (java records) #compiler #development

11.02.2026 13:29 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0

I had it pointed out to me that fn means function declarations are easier to grep, and thus having a keyword like var or let does the same for variables. So I think we stick with the trendy syntax for now

10.02.2026 14:36 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
A snippet of my programming language of a recursive descent parser with rust style syntax.

A snippet of my programming language of a recursive descent parser with rust style syntax.

A snippet of my programming language of a recursive descent parser with C style syntax.

A snippet of my programming language of a recursive descent parser with C style syntax.

Trying to decide if I want the easier to parse, trendy variable: Type syntax, or the (imo) nicer but harder to parse Type variable syntax. Mainly I'm just trying to bikeshed so I don't have to think about implementing a module system ๐Ÿ˜” #compiler

10.02.2026 08:14 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
A screenshot of code in my language showing a recursive descent parser

A screenshot of code in my language showing a recursive descent parser

Writing a compiler, so far the language looks pretty cozy but every new feature I add pulls it closer to either zig or rust ๐Ÿ˜ฉ

06.02.2026 13:05 ๐Ÿ‘ 2 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0

I love how Wizwag looks, I'm looking forward to getting to play it!

26.01.2026 13:44 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
Post image Post image Post image

Brewing again, this time a sort of west coast IPA to use up some Pacific Sunrise hops I got for cheap. A bit lower OG than I wanted but still a respectable 1.054. The Kveik has already munched that down to 1.020 so today is dry hop day apparently ๐Ÿป

03.08.2025 07:55 ๐Ÿ‘ 2 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0

Now I have the urge to make a ship like that in starfield so I can walk around in it ๐Ÿ˜ฉ

13.07.2025 08:24 ๐Ÿ‘ 5 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
Post image

2kg of mixed berries added, the beer is now a nice dry 1.006 and tastes like summer. I'm hoping it clears a bit more but with all that wheat and pectin I'm doubtful ๐Ÿป
#homebrewing

01.05.2025 13:09 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Post image

And here it is. It's spicy and bitter but also slightly sweet and thick. Tastes very much like strawberry but thankfully solidly a saison rather than a wine

Definitely going to sink this whole batch ๐Ÿป

29.04.2025 16:54 ๐Ÿ‘ 0 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Post image Post image Post image

Berry sour is underway, 62/30/8 pils/wheat/oats. About 8 IBU of saaz with a late addition of mosaic and some frozen blackberries I had in my freezer

OG was bang on target at 1.042, and pitched 1pk Philly Sour at 23C

Once it slows down I'll be adding more frozen berries ๐Ÿป
#homebrewing #beer

25.04.2025 07:08 ๐Ÿ‘ 4 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0
Post image Post image Post image

The sun finally came out after days of rain so I had to take some screenshots of my new oblivion remastered character

23.04.2025 10:00 ๐Ÿ‘ 4 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0

Just in time for the end of the long weekend ๐Ÿป

21.04.2025 15:40 ๐Ÿ‘ 5 ๐Ÿ” 0 ๐Ÿ’ฌ 0 ๐Ÿ“Œ 0
Post image Post image

Strawberry wheat saison bottled, I think I overdid it slightly with the puree. It tastes a bit wine-y but has some beer bitterness. Cold crashing didn't help much with the clarity but I don't think it ever would have. Let's see what it's like carbed and conditioned ๐Ÿป

20.04.2025 09:51 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0

Well now you can, Mr Ur

17.04.2025 09:55 ๐Ÿ‘ 1 ๐Ÿ” 0 ๐Ÿ’ฌ 1 ๐Ÿ“Œ 0