Mark Tyrkba (rakivo)

Email: marktyrkba456@gmail.com

GitHub: github.com/rakivo

Codeberg: https://codeberg.org/rakivo


About Me

I'm a self-taught 17-year-old systems programmer and compiler enthusiast building low-level, high-performance software.

My work includes compilers, virtual machines, custom SSA-based IRs, bytecode formats, version control systems, fastest greps in the world and other performance-critical applications — but really, if you think about it, what program's performance isn't critical?

In a world of people never diving deep and performance being treated as an optional feature, I will always try my absolute best to make my programs as fast as I can — with the defaults being as intuitive as possible while keeping the program easy to download and/or compile from scratch. Of course, I'm nowhere near as skilled as people like Jonathan Blow, Casey Muratori, Shawn Barrett, Alan Webster, Vjekoslav Krajačić and other absolutely legendary engineers but I do and I will continue doing everything I can to one day be as knowledgeable and experienced as them.

The poor state of software today is what drives this work. Every day I use modern software I encounter more and more bugs — it's devastating how far quality standards have fallen in this industry. Thousands of people AI-generating their programs just to pollute the internet with even more buggy and unstable software. But I hope that in contrast, genuinely high quality software will become more and more noticeable. A good example of that is File Pilot — people were shocked that it's a single 2MB executable, and how fast and snappy it feels.

Make software great again!


Highlight Projects

1. The rok language Compiler planned public release in H1 2026.

A compiler written in Rust from completely scratch, featuring custom SSA IR, bytecode, type inference, polymorph solver, register machine, and an extremely flexible pipeline for insane meta-programming.

Every single piece of user code can execute at compile time and communicate with the compiler with NO exceptions.

Show / Hide ValuePool — Generic Memory Pool

A generic memory pool for storing lists of any type T. Uses a handle-based API for indirection, power-of-two capacity rounding, and interprets raw memory slots as u32 length headers.


INVALID_HANDLE : u32 : 0xFFFFFFFF;

// A lightweight handle into a ValuePool — just a u32 index.
// Parameterized on T for type safety at compile time.
EntityList :: struct (T: Type) {
    handle: u32;
}

// A memory pool for storing lists of T.
// Layout per allocation: [length_as_T, elem0, elem1, ..., padding to next power of 2]
ValuePool :: struct (T: Type) {
    data: [..] T;
}

// Allocate a new list inside the pool, returns a typed handle.
alloc_list :: (pool: *ValuePool($T), elements: [] T) -> EntityList(T) {
    #if size_of(T) < size_of(u32) {
        #run panic("size_of(T) in ValuePool(T) must be >= 4 bytes!");
    }

    count    := elements.len as u32;
    needed   := 1 + count;
    capacity := next_power_of_two(needed);

    // The handle points just past the length slot
    element_start := (pool.data.len + 1) as u32;

    array_ensure_capacity(*pool.data, pool.data.len + capacity as _);

    // Write the element count by reinterpreting the next T slot as *u32
    length_ptr := *pool.data[pool.data.len] as *u32;
    length_ptr.* = count;
    pool.data.len += 1;

    for elements  array_add(*pool.data, it);

    // Pad to power-of-two boundary
    zero: T;
    for 0..capacity - needed  array_add(*pool.data, zero);

    list: EntityList(T);
    list.handle = element_start;
    return list;
}

// Retrieve a slice view into the pool — zero-copy, no allocation.
get_list :: (pool: *ValuePool($T), list: EntityList(T)) -> [] T {
    if list.handle == INVALID_HANDLE {
        result: [] T;
        return result;
    }

    length_ptr := *pool.data[list.handle - 1] as *u32;

    result: [] T;
    result.data = *pool.data[list.handle] as *T;
    result.len  = length_ptr.* as _;
    return result;
}

main :: () {
    pool: ValuePool(u32);
    defer free_pool(*pool);

    list := alloc_list(*pool, u32.[10, 20, 30, 40, 50]);

    values := get_list(*pool, list);
    for values  print("  %\n", it);
}

#import "std.rok";
    
Show / Hide Asteroids — Raylib Demo

A full Asteroids game written in rok using Raylib — entities, particles, collisions, audio, and a game loop, all in rok's syntax. Below are the most interesting excerpts.

Structs & constants — typed, zero-init, enum tiers:


Asteroid_Tier :: enum {
    LARGE :: 0;
    MED   :: 1;
    SMALL :: 2;
}

Player :: struct {
    pos := #run vec2(SCREEN_W / 2.0, SCREEN_H / 2.0);
    vel: Vector2;
    angle := 0.0;
    alive := true;
}

Asteroid :: struct {
    pos:    Vector2;
    vel:    Vector2;
    radius: f32;
    tier:   Asteroid_Tier;
    seed:   u64;
}

ExplosionParticle :: struct {
    pos:      Vector2;
    vel:      Vector2;
    life:     f32;
    max_life: f32;
    size:     f32;
}

COLOR_BG       :: Color.{ r = 12,  g = 12,  b = 22  };
COLOR_PLAYER   :: Color.{ r = 220, g = 230, b = 255 };
COLOR_THRUST   :: Color.{ r = 255, g = 180, b = 60  };
COLOR_GAMEOVER :: Color.{ r = 255, g = 80,  b = 80  };
    

Explosion emitter — per-tier particle burst with randomized speed, life, and size:


emit_explosion :: (particles: *[..] ExplosionParticle, pos: Vector2, tier: Asteroid_Tier, rng: *u64) {
    count: i32;
    life:  f32;
    speed: f32;

    if      tier == .LARGE { count = 45; life = 1.1;  speed = 280.0; }
    else if tier == .MED   { count = 28; life = 0.85; speed = 200.0; }
    else                   { count = 16; life = 0.6;  speed = 140.0; }

    for i: 0..count {
        angle  := rand_range(rng, 0.0, PI * 2.0);
        spd    := rand_range(rng, speed * 0.25, speed);
        life_j := rand_range(rng, life * 0.6, life);
        size   := rand_range(rng, 2.5, 6.5);

        array_add(particles, .{
            pos      = pos,
            vel      = vec2(cosf(angle) * spd, sinf(angle) * spd),
            life     = life_j,
            max_life = life_j,
            size     = size
        });
    }
}
    

Explosion draw — fire-to-white color animation driven by life / max_life:


draw_explosion_particles :: (particles: *[..] ExplosionParticle) {
    for * particles {
        frac  := it.life / it.max_life;
        alpha := (frac * 255.0) as u8;

        r: u8 = 255;
        g: u8 = 0;
        b: u8 = 0;

        if frac > 0.7 {
            t := (frac - 0.7) / 0.3;
            g = (255.0 * t) as u8;
            b = (240.0 * t) as u8;
        } else if frac > 0.4 {
            t := (frac - 0.4) / 0.3;
            g = (220.0 * t + 80.0 * (1.0 - t)) as u8;
        } else {
            t := frac / 0.4;
            g = (80.0 * t) as u8;
        }

        color := Color.{ r = r, g = g, b = b, a = alpha };
        DrawCircleV(it.pos, it.size * frac, color);

        if frac > 0.5 {
            glow_alpha := ((frac - 0.5) * 2.0 * 100.0) as u8;
            glow_color := .{ r = 255, g = 200, b = 80, a = glow_alpha };
            DrawCircleV(it.pos, it.size * frac * 2.2, glow_color);
        }
    }
}
    

Main loop — defer EndDrawing(), smooth thrust audio fade, and twinkling stars:


while !WindowShouldClose() {
    dt   := GetFrameTime();
    time := GetTime() as f32;

    // Smooth thrust audio volume interpolation
    speed := THRUST_FADE_OUT;
    if thrusting_and_alive  speed = THRUST_FADE_IN;
    thrust_volume += (thrust_target_vol - thrust_volume) * speed * dt;
    SetSoundVolume(thrust_sound, thrust_volume);

    if thrust_volume < 0.01 && IsSoundPlaying(thrust_sound) {
        StopSound(thrust_sound);
    }

    update_player(*player, dt);
    update_bullets(*bullets, dt);
    update_asteroids(*asteroids, dt);
    update_thrust_particles(*thrust_particles, dt);
    update_explosion_particles(*explosions, dt);
    update_stars(*stars, dt);

    points := check_bullet_asteroid(*bullets, *asteroids, *explosions, *state.rng_state);
    if points > 0  state.score += points;

    BeginDrawing();
    defer EndDrawing();

    ClearBackground(COLOR_BG);
    draw_stars(*stars, time);          // twinkle via sinf(time + phase)
    draw_asteroid_trails(*asteroid_trails);
    draw_explosion_particles(*explosions);
    draw_thrust_particles(*thrust_particles);
    draw_asteroids(*asteroids);
    draw_bullets(*bullets);
    draw_player(*player);
    draw_hud(*state);
}

#import "std.rok";
#import "math.rok";
#import "raylib.rok";
#import "dynamic_array.rok";
    
Show / Hide Dynamic Arrays & String Builder Demo

Demonstrates Dynamic arrays with automatic growth, insertion, and removal operations. String builders with type-aware formatting and printf-style syntax. All powered by compile-time generics that specialize for each type.


  // Compile-time polymorphic functions work on any type T
  array_add :: (arr: *[..] $T, value: T) {
      new_len := arr.len + 1;
      array_ensure_capacity(arr, new_len);

      ptr: *T = arr.data + (arr.len * size_of(T));
      ptr.* = value;
      arr.len = new_len;
  }

  // Safe removal returns both value and success status
  array_remove :: (arr: *[..] $T, index: u64) -> T, bool {
      ret : T;
      if index >= arr.len return ret, false;

      size :: size_of(T);
      ptr : *T = arr.data + (index * size);
      ret = ptr.*;

      count := arr.len - index - 1;
      if count > 0 memmove(ptr, ptr + size, count * size);

      arr.len -= 1;
      return ret, true;
  }

  String_Builder :: struct {
      inner: [..] u8;
  }

  sb_append :: (sb: *String_Builder, n: i32)    { sb_append_integer(sb, n); }
  sb_append :: (sb: *String_Builder, n: f64)    { sb_append_float(sb, n); }
  sb_append :: (sb: *String_Builder, s: string) { sb_append_string(sb, s); }

  // Printf-style formatting with variadic Any
  sb_print :: (sb: *String_Builder, fmt: string, args: ..Any) {
      i := 0;
      arg_index := 0;
      while i < fmt.len {
          if fmt[i] == '%' && i + 1 < fmt.len && fmt[i + 1] != '%' {
              if arg_index < args.len {
                  sb_append_any(sb, args[arg_index]);
                  arg_index += 1;
              }
              i += 1;
          } else {
              sb_append_byte(sb, fmt[i]);
              i += 1;
          }
      }
  }

  main :: () {
      sb: String_Builder;
      defer sb_free(*sb);

      sb_append(*sb, "Temperature: ");
      sb_append(*sb, 98.6);
      sb_print(*sb, "User % scored % points\n", "Alice", 1337);

      print("%", sb_to_string(*sb));
  }

  #import "std.rok";
    
Show / Hide Build meta-programming demo

A meta-program that runs at compile-time, registers and manages build options to compile the raylib demo from above.


#run {
    opts : Build_Options;

    opts.do_output = false;
    array_add(*opts.build_files, "examples/triangle.rok");
    array_add(*opts.link_libs, "raylib");
    array_add(*opts.link_libs, "m");

    ok := set_build_options(*opts);

    if !ok panic("couldn't set build options!! exiting..\n");
};

#import "std.rok";
    

Currently in a private repository; planned public release in H1 2026.

Demo video/GIF will go here soon

2. rawgrep — The Fastest Grep in the World

A Rust tool that searches text by reading filesystems directly from raw block devices, completely bypassing the kernel's VFS layer, page cache, and filesystem overhead. Uses aggressive work-stealing parallelism that automatically load-balances across all CPU cores, making it faster than ripgrep on real workloads. Requires only CAP_DAC_READ_SEARCH — no full root access. Currently supports ext4 on Linux.

Show / Hide Demo

Basic usage:


# Search current directory
rawgrep "error"

# Regex patterns
rawgrep "error|warning|critical" .

# Filtering levels:
# Default: respects .gitignore, skips binaries and large files (> 5 MB)
rawgrep "pattern"
rawgrep "pattern" -u     # ignore .gitignore
rawgrep "pattern" -uu    # also search binary files
rawgrep "pattern" -uuu   # search everything, including large files

# Specify device manually (auto-detected by default)
rawgrep "pattern" /home --device=/dev/sda1

# Print match statistics
rawgrep "pattern" . --stats
    

Tap on the video to fullscreen

3. brik-asm — RISC-V Assembler & brik — Object file building library

A Rust library providing a Cranelift-like SSABuilder API for building RISC-V object files, including custom sections, instructions, relocations, and more. Emphasizes performance: cache-friendly memory layout and parsing accelerated via SSE2, AVX2, AVX512BW on x86-64 and Neon on AArch64. Runs in QEMU emulator.

Show / Hide Code Examples & Demos

.include "std"

.text
.extern printf
.global main

main:
    prologue

    ; t0 = 69
    li      t0, 69
    printf1 fmt1, t0      ; prints: "t0 = 69"

    ; t1 = -t0
    li      t0, 69
    neg     t1, t0
    printf1 fmt2, t1      ; prints: "neg(t0) = -69"

    ; t2 = ~t0
    li      t0, 69
    not     t2, t0
    printf1 fmt3, t2      ; prints: "not(t0) = -70"

    j done

skip:
    printf1 fmt_skip, t0
    epilogue
    reti 0

done:
    epilogue
    reti 0

.rodata
fmt1:
    .stringz "t0      = %ld\n"

fmt2:
    .stringz "neg(t0) = %ld\n"

fmt3:
    .stringz "not(t0) = %ld\n"

fmt_skip:
    .stringz "this should not print, t0=%ld\n"
    

Quick example of using `brik` to build a factorial-computing program


fn produce_factorial_obj<'a>() -> Object<'a> {
    let mut asm = Assembler::new(
        BinaryFormat::Elf,
        Arch::Riscv64,
        Endianness::Little,
        "rv64gc"
    );

    asm.set_object_flags(FileFlags::Elf {
        os_abi: 0,
        abi_version: 0,
        e_flags: 0x4,
    });

    // .rodata section for format strings
    let _rodata = asm.add_rodata_section_at_end();

    let  input_fmt_sym = asm.define_data(b"input_fmt",  b"enter a number: \0");
    let  scanf_fmt_sym = asm.define_data(b"scanf_fmt",  b"%ld\0");
    let result_fmt_sym = asm.define_data(b"result_fmt", b"factorial: %ld\n\0");

    // =================
    // external symbols
    // =================

    let printf_sym = asm.add_symbol_extern(
        b"printf",
        SymbolKind::Text,
        SymbolScope::Dynamic
    );

    let scanf_sym = asm.add_symbol_extern(
        b"scanf",
        SymbolKind::Text,
        SymbolScope::Dynamic
    );

    let text_section = asm.add_text_section_at_end();

    asm.emit_function_prologue();

    // allocate space on stack for input number (8 bytes)
    asm.emit_addi(SP, SP, -8);

    // print input prompt
    asm.emit_pcrel_load_addr(A0, input_fmt_sym, 0);
    asm.emit_call_plt(printf_sym);

    // read input number
    asm.emit_pcrel_load_addr(A0, scanf_fmt_sym, 0);
    asm.emit_addi(A1, SP, 0);
    asm.emit_call_plt(scanf_sym);

    // load input number into s1
    asm.emit_ld(S1, SP, 0);

    // init factorial result in s2 (result = 1)
    asm.emit_addi(S2, ZERO, 1);

    // init counter in s3 (i = 1)
    asm.emit_addi(S3, ZERO, 1);

    let loop_lbl = asm.add_label_here(
        b".fact_loop",
        SymbolKind::Text,
        SymbolScope::Compilation
    );

    let done_lbl = asm.declare_label(
        b".fact_done",
        SymbolKind::Text,
        SymbolScope::Compilation
    );

    // loop condition: if i > n, exit
    asm.emit_branch_to(
        done_lbl,
        // if s1 < s3 (n < i)
        BLT { s1: S1, s2: S3, im: 0 },
    );

    // result *= i
    asm.emit_bytes(MUL { d: S2, s1: S2, s2: S3 });

    // i++
    asm.emit_addi(S3, S3, 1);

    // jump back to loop
    asm.emit_branch_to(
        loop_lbl,
        JAL { d: ZERO, im: 0 },
    );

    ...

    asm.add_symbol(
        b"main",
        0,
        asm.section_size(text_section),
        SymbolKind::Text,
        SymbolScope::Dynamic,
        false,
        SymbolFlags::None
    );

    asm.finish().unwrap()
}

fn main() -> Result<(), Box> {
    let args = env::args().collect::>();

    let Some(output_path) = args.get(1) else {
        println!{
            "usage: {prog} ",
            prog = args[0]
        };
        return Ok(())
    };

    let obj = produce_factorial_obj();

    let file = fs::File::create(output_path)?;
    obj.write_stream(&file)?;

    println!("[wrote object file to {output_path}]");

    Ok(())
}
    

Demo video/GIF will go here soon

4. Stalkr — language-agnostic TODO Tracker

A language-agnostic Rust tool for scanning your project for TODOs and either reporting, purging, or listing them. Heavily inspired by tsoding/snitch , rewritten in Rust for high performance with worker-parallelized execution. Fully modular and host-agnostic (works with GitHub or other platforms via a pluggable API layer).

Show / Hide Demo

Brief example of a tagged (reported) TODO in real code


// ...

TK::CQuote => {
    self.lexer.eat_next_token()?; // c"

    let (loc, span) = self.parse_string_literal()?;
    let src_str = span.s(&self.mo);

    let mut nul_terminated = String::with_capacity(src_str.len() + 1);
    util::unescape_string(src_str, &mut nul_terminated);

    if nul_terminated.bytes().last().is_some_and(|b| b != b'\0') {
        nul_terminated.push('\0');
    } else {
        // TODO(#252): Emit a warning if a C string literal already ends with `\0`
    }

    let str_lit_id = self.pc.new_str_lit(nul_terminated);

    Expr {
        loc,
        span,
        kind: EK::ConstStr(str_lit_id),
        ...
    }
}
  

Run Stalkr on this codebase you'll see this:


[reporting mode]

[detected project]: https://github.com/rakivo/rok

[todoʼs from]: rok_frontend/src/parser.rs

1. [line 1662]: Warn if a c string literal already ends with \0

selection (e.g. 1,2; 'a' all; 's' skip file; 'h' help; '^C' quit):
    

Just press `1` and return (enter), and the TODO is going to get reported:


[reporting mode]

[detected project]: https://github.com/rakivo/rok

[todoʼs from]: rok_frontend/src/parser.rs

1. [line 1662]: Warn if a c string literal already ends with \0

selection (e.g. 1,2; 'a' all; 's' skip file; 'h' help; '^C' quit): 1
[master 24dce81] Add TODO(#341): Warn if a c string literal already ends with \0
 1 file changed, 1 insertion(+), 1 deletion(-)
[1/1] todoʼs reported
    

A video of me using Stalkr to report TODO's while I was programming brik

Tap on the video to fullscreen

The bug with `0 insertions` is already fixed btw .. :D

5. Rush — Rust-based build system inspired by Ninja

A Rust-based build system inspired by Ninja. Rush executes build scripts efficiently, sometimes matching or exceeding Ninja's speed on typical workloads. It demonstrates parallelism, minimal overhead, and custom build pipeline design.

Show / Hide Build Script Example

cflags = -std=gnu99 -Wall -Wextra -O3
builddir = build

phony all
build all: $builddir/main run

rule cc
  depfile = $out.d
  command = gcc -MD -MF $out.d $cflags -o $out -c $in

rule link
  command = cc $cflags -o $out $in

build $builddir/foo.o: cc foo.c
build $builddir/bar.o: cc bar.c
build $builddir/main.o: cc main.c

build $builddir/main: link $builddir/foo.o $
                           $builddir/bar.o $
                           $builddir/main.o
  cflags = -std=gnu99 -O2

phony run
build run:
  command = ./$builddir/main

phony clean
build clean:
  command = rm -f $builddir/*
  

Me showcasing Rush building Ninja and Lua

Tap on the video to fullscreen

Other projects

I've worked on many other projects not shown here - feel free to explore them on my GitHub page.

Skills


Other Achievements


Contact

Demo / Media

This section will soon showcase demo videos, screenshots, GIFs, and other project media.

But for now, enjoy "Handmade Hero - Announcement Trailer", an insanely inspiring video by legendary Casey Muratori.