Flash tutorial · 11 / 12
11. Zig Interoperability
Flash is designed to compile side-by-side with Zig. It does not replace Zig entirely; instead, it coexists, allowing module-by-module porting of existing systems code.
1. The Coexistence Rule
Throughout the development of FlashOS, Flash and Zig files compile side-by-side:
- A Flash file lowers to a Zig file.
- This lowered Zig file can import existing hand-written Zig modules.
- Existing Zig files can import the lowered Flash module in turn, without knowing it was originally written in Flash.
2. Syntactic Lowering Comparison
To understand how the compiler lowers Flash code to Zig, examine the following side-by-side comparison.
Flash Input:
use flibc
const BUF_LEN usize = 512
fn drain(fd i32) {
var buf [BUF_LEN]u8 = undefined
while true {
n := flibc.sys.read(fd, &buf, buf.len)
if n <= 0 {
break
}
_ = flibc.sys.write_fd(1, &buf, #intCast(n))
}
}
Generated Zig Output:
const flibc = @import("flibc");
const BUF_LEN: usize = 512;
fn drain(fd: i32) void {
var buf: [BUF_LEN]u8 = undefined;
while (true) {
const n = flibc.sys.read(fd, &buf, buf.len);
if (n <= 0) {
break;
}
_ = flibc.sys.write_fd(1, &buf, @intCast(n));
}
}
3. Key Lowering Transformations
Notice the following changes made by the compiler during lowering:
- Type Suffixes: In Flash, variables are typed as
var name type = value. The compiler lowers this to Zig'svar name: type = value;. - Semicolons: Semicolons are automatically restored in the output Zig code.
- Implicit Void: Functions without a return type in Flash (like
fn drain) are explicitly lowered to returnvoidin Zig. - Braces on Loops: Loop conditions in Zig require parentheses (e.g.,
while (true)). The compiler inserts these automatically. - Short-hand
:=: The short-handname := exprlowers to constant declarationsconst name = expr;inside local scopes (always immutable). - Intrinsic Sigil: Flash spells compiler intrinsics with a
#sigil (#intCast). These lower to Zig's@-prefixed builtins (@intCast); the semantics are identical, only the sigil changes.
4. Integrating with build.zig
To compile a Flash file in a Zig project, you first transpile it using flashc as part of your build pipeline (often using a b.addRunArtifact step or custom build command in build.zig), and then compile the resulting Zig file as a module or executable. This keeps the integration clean and standard.