Skip to content

Instantly share code, notes, and snippets.

View alogic0's full-sized avatar

Oleg Tsybulskyi alogic0

  • Germantown, Tennessee, USA
View GitHub Profile
@alogic0
alogic0 / zig-0.16-through-cl365-lead-enrichment.md
Created August 1, 2026 10:32
Zig 0.16 tutorial, project based

Learning Zig 0.16 Through cl365-lead-enrichment

This is a project-based Zig guide. It explains the language and standard-library features used by cl365-lead-enrichment, a command-line data pipeline that:

  1. downloads CSV files from Google Drive;
  2. normalizes US phone numbers;
  3. deduplicates those numbers with a disk-backed bitmap;
@alogic0
alogic0 / zig_ru_2.md
Created July 22, 2026 22:27
Zig и цепочка инерфейсов

Это ощущение возникает не из‑за «бесконечной матрёшки» и уж точно не из‑за бага. В Zig это почти всегда композиция одинаковых по смыслу, но разных по реализации интерфейсов — и это намеренный, очень практичный приём.

Что именно ты видишь

Типичный паттерн, который считывается как «вызвал интерфейс → внутри ещё интерфейс → снова тот же интерфейс»:

try stdout.writer().writeAll("Hello\n");
@alogic0
alogic0 / zig_ru_1.md
Created July 22, 2026 22:09
Zig и вложенность

В Zig 0.16 нет какой‑то специальной «самовложенности» или рекурсивности как фичи языка — то, что выглядит как вложенность или рекурсия в библиотечных функциях, обычно объясняется тремя вещами:

  • Явной передачей зависимостей (DI).
  • Композицией интерфейсов (особенно I/O и аллокаторов).
  • Природой системных абстракций (например, обёртки над ОС, которые сами используют другие абстракции).

Что изменилось в Zig 0.16 и почему это влияет на вид API

Ключевые изменения в 0.16, которые сильнее всего меняют стиль стандартной библиотеки:

@alogic0
alogic0 / zig_writer_tutorial.md
Created July 13, 2026 16:31
std.Io.Writer explanation

The "Writergate" overhaul in Zig 0.15/0.16 completely re-architected how the standard library handles I/O. In Zig 0.16, the old std.io.Writer (which relied heavily on duck-typing with anytype) has been removed and replaced by the strict, explicit interface type under std.Io.Writer.

This change mirrors Zig's Allocator model. To perform any I/O, you now pass an explicit io: std.Io context down through your functions.


1. Core Architecture: What Is It?

Instead of using duck-typing (anytype), std.Io.Writer is a concrete type that acts as an interface using a Virtual Method Table (vtable).

@alogic0
alogic0 / zig_vtables.md
Last active May 19, 2026 03:57
Zig vtables

In Zig, vtables (virtual tables) are a manual pattern used to implement dynamic dispatch, allowing different types to be used through a single, shared interface. [^1][^2][^3][^4][^5] Unlike languages like C++ or Java, Zig does not have "classes" or "interfaces" as built-in keywords. Instead, you construct vtables yourself by creating a struct of function pointers. [^6][^7][^8][^9][^10]

How Zig vtables Work

A typical Zig interface is a "fat pointer" consisting of two main parts: [^3][^11]

  1. A Context Pointer (ptr): A pointer to the specific implementation's data, usually typed as *anyopaque.
  2. A VTable Pointer (vtable): A pointer to a constant struct containing function pointers that define the interface's behavior. [^3][^12][^13]

Example: std.mem.Allocator

The most prominent use of this pattern in the Zig Standard Library is the Allocator. It allows functions to accept any allocator (like ArenaAllocator or GeneralPurposeAllocator) without knowing exactly which one is being used at co

@alogic0
alogic0 / lexer_4.md
Created April 26, 2026 07:58
Phase 4: Incrementalism and the "Dirty" Range

Phase 4: Incrementalism and the "Dirty" Range

Now we reach the defining feature of Tree-sitter: Incremental Parsing. In a traditional parser, if a user has a 10,000-line file and types a single }, you re-parse the whole file. In Tree-sitter, you only re-parse what changed.

To do this in Zig, we need to introduce Edit Mapping and Node Reuse.


1. The Edit Structure

When a user types, we receive an "edit" event. This isn't just the new string; it's the range of bytes that were replaced.

@alogic0
alogic0 / lexer_3.md
Created April 26, 2026 07:49
Phase 3: The Stack and the State Machine

Phase 3: The Stack and the State Machine

To move from "manual reductions" to a real Tree-sitter-like algorithm, we have to introduce the LR Stack. In a bottom-up parser, the stack doesn't just hold nodes; it holds States.

In Zig, we can represent this by combining our NodeId with a StateId. This tells the parser: "I am currently in the middle of a function definition, and I just saw an identifier. What do I expect next?"


1. Defining the State

The "State" is an integer that refers to a row in a giant transition table (the Parse Table). In Tree-sitter, this table is generated from your grammar.js.

@alogic0
alogic0 / lexer_2_1.md
Created April 20, 2026 09:03
Lesson 2, extension about Zig memory management

Since you're architecting a high-performance parser for large-scale data (like your work with millions of records), Zig's approach to memory is your greatest ally. It avoids the "hidden" costs of garbage collection by making every allocation explicit.

In Zig, if a function needs memory, it must ask for an Allocator.

1. Manual Memory Management: The Allocator

Zig does not have a global heap. Instead, you pass an Allocator (an interface) to any structure—like your Parser—that needs to grow.

  • Explicit Control: You decide if memory lives on the stack, the heap, or a fixed-size buffer.
  • The defer Keyword: To prevent memory leaks, Zig uses defer to ensure memory is freed as soon as the scope closes.
  • Safety: Using the GeneralPurposeAllocator (GPA) during development will catch memory leaks and "double-frees" immediately.
@alogic0
alogic0 / lexer_2.md
Created April 20, 2026 08:46
Lesson 2 in Lexer Generator

To move from a flat stream of tokens to a Syntax Tree, we need to define how tokens relate to each other hierarchically.

In Tree-sitter, the goal is to create a Concrete Syntax Tree (CST). Unlike an Abstract Syntax Tree (AST), which throws away "useless" characters like parentheses or semicolons, a CST keeps everything so that the code can be reconstructed exactly as it was written.

1. The Node Structure

In Zig, we want this to be memory-efficient. Instead of using pointers for every child (which causes cache misses), we can use an index-based approach.

pub const NodeId = u32;
@alogic0
alogic0 / lexer_1.md
Created April 18, 2026 07:00
Lexer 1

To understand Tree-sitter using Zig, we start with the absolute atom of parsing: the Lexer.

In a traditional compiler, the Lexer (or Scanner) turns a string of characters into a stream of Tokens. In an incremental system like Tree-sitter, the lexer must be able to start at any byte offset, but for our first step, we will build a linear Lexer in Zig.


1. The Core Data Structures

First, we define what our "Tokens" look like. Using a Zig enum is perfect for this because we can use tagged unions later for more complex metadata.