Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction to AzLang

AzLang is a minimal, blazingly fast, and readable systems programming language engineered for direct bare-metal execution, sub-kilobyte binary output, and zero-runtime overhead.

AzLang blends Python-like visual clarity, Rust-like memory control, and TypeScript-like type safety, stripping away heavy runtime abstractions and external runtime daemons.


Key Characteristics

  • Zero-VM Execution: No virtual machines, dynamic garbage collectors, or heavy runtime initialization routines (crt1.o). Execution lowers directly to native machine code.
  • Microsecond Compilations: A lean frontend passes verified AST directly to fasm assembly and native machine instructions in a single pass.
  • Lean Binary Footprint: Produces standalone, self-contained ELF executables — a hello world program measures 180 bytes, and a comprehensive multi-module program stays around 2 KB.
  • Absence of Moving Parts: Eliminates runtime state machines, dynamic heap leaks, and unwinding tables by design.
  • Direct ABI & Syscall Interop: High-performance systems interfaces via native @link directives and direct kernel syscall invocation (x86_64 register calling conventions).

Architectural Snapshot

┌───────────────────────────────────────────────────────────────────────────────────┐
│ AZLANG ARCHITECTURE                                                               │
│                                                                                   │
│  [Source Code (.az)]                                                              │
│          │                                                                        │
│          ▼                                                                        │
│  [Tokenizer & Indent Engine]                                                      │
│          │                                                                        │
│          ▼                                                                        │
│  [AST Construction & Validation]                                                  │
│          │                                                                        │
│          ▼                                                                        │
│  [Transpiler → fasm Assembly (.asm)] ──► @link syscall stubs included inline      │
│          │                                                                        │
│          ▼                                                                        │
│  [fasm: single-pass assembler & linker]                                           │
│          │                                                                        │
│          ▼                                                                        │
│                                                  [~180 Byte Bare-Metal ELF]       │
└───────────────────────────────────────────────────────────────────────────────────┘

Real Syntax At a Glance

Here is an authentic snippet from the AzLang SDK illustrating low-level declarations, enumerations, ABI linking, and entry invocations:

enum FD
    Stdin
    Stdout
    Stderr

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

@link("./sdk/src/exit.s")
op exit(const int val): void

write(Stdout, "Hello, Bare Metal AzLang!\n", 26)
exit(0)

The Minimalist Doctrine

In classical aerospace and mechanical engineering, the highest reliability is achieved not by complicating safety redundancies, but by engineering unnecessary valves and moving parts out of the machine entirely.

AzLang brings this functional minimalist mindset to software engineering:

┌───────────────────────────────────────────────────────────────────────────────────┐
│ AZLANG FIELD DOCTRINE                                                             │
│                                                                                   │
│  [Source Code] ──► [fasm Assembly Emission] ──► [180-Byte Bare-Metal Binary]      │
│                                                                                   │
│  • Self-contained toolchain with zero runtime dependencies.                       │
│  • Executes anywhere, compiles in microseconds, leaves zero operational footprint.│
└───────────────────────────────────────────────────────────────────────────────────┘

1. Field Reliability vs. Heavy Infrastructure

Traditional compiler architectures often assume an infinite logistical tail:

  • Background daemons continuously running in memory.
  • Gigabytes of backend frameworks (like giant LLVM installation footprints).
  • Multi-megabyte runtime libraries and dynamic linker dependencies.

AzLang rejects this assumption.

AzLang is designed as a self-contained, field-deployable compiler:

  • No background daemons: Compiles directly in one shot.
  • Direct AST Lowering: AST nodes lower straight into readable fasm assembly without requiring gigabytes of compiler caches.
  • Microsecond compilation: The compiler executable can be dropped onto an environment, parse code, validate semantics, emit assembly, and link a binary in milliseconds.

2. Kinetic Thrust: Direct Execution Paths

Rather than performing multi-pass combinatorial saturations that bloat compile times, AzLang focuses on kinetic thrust:

  • Short, deterministic execution paths.
  • Lean native assembly generated directly for target architectures.
  • High thrust-to-weight ratio in generated code: no dead code bloat, no virtual dispatch tables unless explicitly constructed.
MetricAzLang Engineering ModelHeavy Industrial Toolchains
Compilation LatencyMicroseconds to millisecondsSeconds to minutes
Output Binary SizeHello world: 180 bytes; ~2 KB for multi-module programs5 MB – 50 MB
Runtime DependenciesNone (Direct Kernel Syscalls)libc, libm, libpthread, dynamic runtimes
Hardware TargetsBare metal, microcontrollers, embedded, microservicesCloud servers, heavy multi-core desktops

3. Developer Ergonomics: The Helmet Sight

Soviet fighter aircraft pioneered Helmet-Mounted Cueing Systems (such as the Shchel-3UM) paired with clean, uncluttered analog cockpits. The pilot simply looks at a target and engages; the instruments stay out of the way.

AzLang adopts this philosophy for Developer Experience (DX):

  • Readable indentation-based syntax akin to Python.
  • Clear explicit boundary typing: Types are inferred automatically where obvious, and explicitly declared at structural boundaries (enum, object, parameter signatures).
  • The language frontend stays clear and readable while the backend quietly outputs a lethal, high-speed native binary.

Zero-VM & Absence of Moving Parts

The most resilient system is one without excess complexity. Many modern programming runtimes inject heavy layers between application code and silicon:

  1. Virtual Machines (VM) with dynamic bytecode interpreters.
  2. Stop-the-world Garbage Collectors (GC) managing heap pages in the background.
  3. Complex C-runtime Initialization (crt0.o, crt1.o, libc) running pre-main hooks.
  4. Exception Unwinding Tables (.eh_frame) introducing hidden branches and stack unwinding machinery.

How AzLang Achieves Safety Through Absence

AzLang eliminates every single one of these layers:

1. Direct Bare-Metal Entry (_start)

AzLang executables do not need main() wrapped in standard C-runtime setup. They target _start directly. The operating system kernel spawns the process, pushes initial stack frames (arguments, environment pointers), and transfers instruction control directly to AzLang code.

2. Zero Heap Leaks by Design

With direct register allocation and stack management, AzLang does not rely on opaque runtime memory arenas. When a program exits, it issues a direct kernel exit syscall (sys_exit, 60 on Linux x86_64).

3. Predictable State Invariants

Because there are no background scheduler threads, garbage collector pauses, or hidden asynchronous thread pools, program execution is:

  • 100% Deterministic: Timing jitter is near zero.
  • Traceable: Assembly instructions correspond directly to written operations.
  • Inspectable: Debugging with tools like gdb, objdump, or strace reveals pure syscalls and predictable stack frames.
[AzLang Application]
        │
        ▼ (direct syscall: rax=1 for write, rax=60 for exit)
[Linux Kernel Ring 0]

Installation

AzLang ships as a single compiler binary. There is no runtime to install, no VM, and no LLVM-sized toolchain — the only external tool the compiler invokes is fasm.


Building from Source

cargo build --release

This generates the azcli binary executable.


Installing fasm

AzLang emits one .asm file per build and hands it to fasm, which assembles and links it into a standalone ELF executable in a single pass.

# Arch Linux
sudo pacman -S fasm

# Debian / Ubuntu
sudo apt install fasm

For other platforms, download fasm from https://flatassembler.net/ and put it on your PATH.


Next Steps

Continue to the Hello World Walkthrough to compile your first native binary.

Hello World Walkthrough

Here is a step-by-step walkthrough of writing and compiling your first native AzLang program using the real SDK syntax.


1. Writing main.az

Create a file named main.az:

enum FD
    Stdin
    Stdout
    Stderr

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

@link("./sdk/src/exit.s")
op exit(const int val): void

write(Stdout, "Hello World from AzLang!\n", 25)
exit(0)

Deconstructing the Code:

  1. enum FD: Defines standard file descriptors (Stdin=0, Stdout=1, Stderr=2). Enum variants are inlined as immediates — no lookup table exists at runtime.
  2. @link(...): Points at a fasm assembly source containing a syscall stub that performs a direct Linux syscall instruction. The source is included straight into the generated assembly — there is nothing to pre-compile.
  3. op write(...): Declares a callable operation function signature and parameter types.
  4. write(...) & exit(...): Calls the operations natively without libc overhead. The string length 25 accounts for the \n escape, which is resolved to a single newline byte at emission time.

2. Compiling with AzCLI

Compile main.az using azcli:

azcli build main.az

The AzLang pipeline will:

  1. Parse main.az into an AST.
  2. Validate symbols and types.
  3. Emit a single assembly file (main.asm) containing the program code, its string data, and include directives for write.s and exit.s.
  4. Invoke fasm, which assembles and links that file directly into the standalone binary main in one pass.

The only external tool required is fasm. There is no qbe, no as, no ld and no object files.

Run the resulting executable:

./main
# Output:
# Hello World from AzLang!

Check the binary size:

ls -l main
# 180 bytes

A complete, functional ELF executable in 180 bytes!

Variables & Mutability

AzLang enforces explicit distinction between immutable constants and mutable variables.


1. Constants (const)

By default, data should remain immutable. Use the const keyword to declare constants:

const int max_retries = 5
const str host = "127.0.0.1"
const float pi = 3.14159

Once defined, attempting to reassign a const identifier will produce a compile-time semantic error during the validation phase.


2. Mutable Variables (var)

When state needs to change over time, declare the variable using var:

var int counter = 0
counter = counter + 1

var str status = "pending"
status = "ready"

3. Type Inference & Annotations

AzLang supports type inference for basic expressions, while allowing explicit type annotations for maximum clarity:

// Explicit type annotation
const int port = 8080

// Mutable variable with type
var int connections = 0
connections = 1

For custom structures, enums, and module interfaces, explicit types are required at structural boundaries.

Data Types

AzLang provides a focused set of primitive and composite types that map directly to hardware registers and low-level data layouts.


1. Numeric Types

TypeDescriptionMachine Mapping
intStandard signed integer32-bit / 64-bit machine word
naturalUnsigned non-negative integerUnsigned machine word
bigintLarge 64-bit integer64-bit register
tinyintSmall 8-bit / 16-bit integerByte / Half-word
floatFloating-point numberSingle / Double IEEE-754

Example:

const int count = 42
const bigint big_offset = 1000000000
const float ratio = 0.75

2. Textual & Character Types

  • char: A single character literal ('a').
  • str: String representation. Depending on declaration, string literals are handled either as static immutable string slices (stored in data sections) or dynamic strings:
const str greeting = "Hello, world!"
const char initial = 'A'

AzLang also supports template strings (string interpolation) with backticks:

const str name = "AzLang"
const str msg = `Welcome to ${name}`

3. Boolean & Unit Types

  • bool: Represents true or false.
  • void: Represents an empty or absent return value from an operation.
  • any: Universal type placeholder for dynamic dispatch or heterogeneous buffers.

4. Compound Types

  • list<T>: Linear collection of elements of type T.
const list<int> numbers = [1, 2, 3, 4]
  • User-defined types (enum, object, type).

Enums

Enums in AzLang provide a zero-cost, type-safe abstraction for representing discrete states, flags, and system descriptors (such as Linux file descriptors, open flags, or socket options).


1. Syntax

Enums are declared using the enum keyword followed by the enum type name and an indented list of variants:

enum FD
    Stdin
    Stdout
    Stderr

enum FLAG
    ReadOnly
    Write

enum FMODE
    NoCreate
    Create

2. Zero-Cost Compile-Time Inlining & Memory Representation

In AzLang, enums do not produce runtime allocation overhead or stack indirection tables.

Byte-Level Direct Inlining (Zero Footprint)

During the semantic validation stage, enum variants are registered directly as sequential numeric constants starting from 0:

  • Stdin -> 0
  • Stdout -> 1
  • Stderr -> 2

During code generation, any reference to an enum variant is directly inlined at compile-time as an immediate byte / literal value directly into the instruction stream or call site:

; Emitted assembly
; Notice that no load from memory or lookup table is generated.
; The variant is inlined directly as an immediate argument:
    mov rax, 1
    push rax
    lea rax, [main_str0]
    push rax
    mov rax, 27
    push rax
    pop rdx
    pop rsi
    pop rdi
    call write

Key Architectural Benefits:

  1. Zero Stack Allocation: No temporary register operations needed at runtime.
  2. Byte-Level Memory Density: Directly fits the exact ABI byte/word requirement of native syscalls with zero runtime indirection.
  3. Optimized Instruction Stream: Machine code directly emits immediate constants, minimizing executable binary size and instruction cache misses.

3. Usage with Operations & Native Syscalls

Enums are first-class types during semantic validation. They enforce strict compile-time type safety while passing as zero-cost inlined numbers to ABI operations:

enum FD
    Stdin
    Stdout
    Stderr

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

@link("./sdk/src/exit.s")
op exit(const int val): void

# Stdout is validated as FD type at compile-time,
# and directly inlined as literal 1 in the emitted binary
write(Stdout, "Writing to standard output...\n", 30)
exit(0)

Operations & Expressions

AzLang supports standard binary and unary operations with strict type checks enforced during compiler validation.


1. Arithmetic Operators

AzLang supports the standard arithmetic operations:

OperatorMeaningExample
+Additiona + b
-Subtractiona - b
*Multiplicationa * b
/Divisiona / b
%Moduloa % b

Example:

const int a = 10
const int b = 3
const int sum = a + b
const int rem = a % b

2. Comparison Operators

Comparisons evaluate to a bool (true or false):

OperatorDescription
==Equal
!=Not equal
>Greater than
>=Greater than or equal
<Less than
<=Less than or equal

Example:

const bool is_equal = (a == b)
const bool is_positive = (a > 0)

3. Logical Operators

AzLang provides natural keywords as well as standard symbol alternatives:

  • and / && : Logical AND
  • or / \|\| : Logical OR
  • ! : Logical NOT
if a > 0 and b > 0
    // block

Control Flow

AzLang utilizes significant whitespace and indentation (4 spaces per level) to organize execution blocks cleanly, avoiding noisy curly braces or verbose block delimiters.


1. Conditional Branching (if, elif, else)

Conditional statements evaluate boolean expressions to branch execution paths:

const int value = 42

if value == 0
    write(Stdout, "Value is zero\n", 14)
elif value > 0
    write(Stdout, "Value is positive\n", 18)
else
    write(Stdout, "Value is negative\n", 18)

2. While Loops (while)

The while loop continuously executes an indented statement block as long as the condition remains true:

var int i = 0

while i < 10
    i = i + 1

3. Infinite Loops (loop)

For continuous polling, kernel event pumps, or server request loops, use the bare loop construct:

loop
    // execution body
    if should_stop
        break

4. Iteration (for .. in)

AzLang supports iterating through lists and collections:

const list<int> items = [10, 20, 30]

for items in item
    // use item

5. Loop Control Statements

  • break: Terminate the loop immediately.
  • continue: Skip the rest of the current iteration and proceed to the next cycle.

Operations & Functions (op)

In AzLang’s real SDK syntax, callable procedures and functions are declared using the op keyword. This aligns with AzLang’s low-level systems nature: procedures are atomic machine operations.


1. Declaring Internal Operations

An operation defines parameters, parameter types, a return type, and an indented block:

op add(const int a, const int b): int
    return a + b

op multiply(var int x, const int factor): int
    return x * factor

Mutability in Parameters

  • const <Type> <name>: Value parameter passed immutably.
  • var <Type> <name>: Parameter treated as a mutable pointer reference.

2. Returning Void

When an operation does not yield a value (e.g. system exit or logging), its return type is specified as void:

op log_message(const str msg, const int len): void
    write(Stdout, msg, len)

To declare an interface to an external assembly source, place the @link directive above the op signature:

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

@link("./sdk/src/exit.s")
op exit(const int val): void

@link("./sdk/src/fopen.s")
op fopen(const str val, FLAG flag, FMODE mode): File

When AzLang compiles this file, it registers the external function signature in its symbol table and, for every operation that is actually called, emits an include directive pulling the assembly source into the generated .asm — fasm then resolves the symbol statically in the same pass.

Modules & Imports

AzLang organizes codebases into self-contained modules imported using the import statement.


1. Importing Modules

To import definitions from another .az file:

import lib

write(Stdout, "Hello from imported module\n", 27)

In the AzLang SDK, sample.az imports lib.az:

// sample.az
import lib

write(Stdout, "Hello World", 11)

Where lib.az contains common type definitions, enums (FD, FLAG, FMODE), and external system call links:

// lib.az
enum FD
    Stdin
    Stdout
    Stderr

@link("./sdk/src/exit.s")
op exit(const int val): void

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

2. Compilation Model for Modules

When an import directive is encountered:

  1. The parser resolves the target file in the module search path.
  2. The imported module AST is parsed and analyzed.
  3. Symbol tables are merged or qualified, ensuring every @link source needed by the combined program is included exactly once in the emitted assembly.

Direct ABI Linking (@link)

One of AzLang’s most powerful capabilities is seamless, zero-overhead interoperability with native assembly code — no C runtime, no FFI wrappers, no dynamic loading.


To call native code, point @link at a fasm assembly source and declare the operation’s signature:

@link("<path-to-fasm-source>")
op <function_name>(<parameters>): <return_type>

Example:

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

@link("./sdk/src/exit.s")
op exit(const int val): void

2. Compiler Pipeline Integration

When the AzLang compiler encounters an @link directive:

  1. Parser: The AST node Statement::ExternalFunctionDef records:
    • name: Target symbol name (e.g. write).
    • library: Path to the assembly source (e.g. ./sdk/src/write.s).
    • params & return_typ: Checked against call sites.
  2. Validator: Registers write as a valid function and adds ("write", "./sdk/src/write.s") to the compilation’s link_files registry.
  3. Transpiler: When write is actually called, the compiler canonicalizes the path and emits it into the generated assembly:
include "/abs/path/to/sdk/src/write.s"

Sources of operations that are never invoked are skipped, and duplicate paths are included only once — unused stubs never reach the binary. 4. fasm: The included source and the generated code live in the same translation unit, so call write resolves statically at assembly time.

No dynamic library lookups at runtime, no dlopen overhead: the code is assembled directly into the binary image in a single fasm main.asm main pass.

Kernel Syscalls & Bare-Metal Stubs

In the AzLang architecture, standard I/O does not rely on the heavy GNU C Library (glibc or musl). Instead, core operations are mapped directly to Linux kernel system calls using lean assembly stubs.


1. System Call Assembly Implementations

The AzLang SDK provides plain fasm assembly sources for Linux x86_64 (fasm defaults to Intel syntax). These files are pulled in by @link via include — they are never assembled on their own.

write.s — Direct sys_write (Syscall 1)

write:
    mov rax, 1      ; sys_write
    syscall
    ret

On x86_64 Linux ABI:

  • rdi: File descriptor (FD fd)
  • rsi: Buffer pointer (const str val)
  • rdx: Buffer byte count (const int size)
  • rax: Syscall number (1 for sys_write)

exit.s — Direct sys_exit (Syscall 60)

exit:
    mov rax, 60     ; sys_exit
    syscall

fopen.s — Direct sys_open (Syscall 2)

fopen:
    mov rax, 2      ; sys_open
    syscall
    ret

2. Advantages of Direct Syscalls

  • Zero Startup Penalty: No dynamic symbol relocations or runtime linker (ld-linux.so) overhead.
  • Microscopic Footprint: Omits megabytes of standard library code that standard C programs pull in.
  • Security & Attack Surface Reduction: Eliminates vulnerabilities inside complex libc string/format-string/locale handlers.

Standard SDK Library

The official AzLang SDK resides in the sdk/ directory (tracked as a git submodule). It acts as the reference standard library implementation demonstrating how systems programming is conducted in pure AzLang.


1. Structure of sdk/

sdk/
├── src/
│   ├── lib.az        # Common types, enums, and @link declarations
│   ├── write.s       # Linux sys_write assembly stub (fasm syntax)
│   ├── exit.s        # Linux sys_exit assembly stub (fasm syntax)
│   └── fopen.s       # Linux sys_open assembly stub (fasm syntax)
└── README.md

There is no build step: the .s files are fasm assembly sources referenced by @link and included directly into the compiler’s generated assembly.


2. Standard Types in lib.az

enum FD
    Stdin
    Stdout
    Stderr

enum FLAG
    ReadOnly
    Write

enum FMODE
    NoCreate
    Create

@link("./sdk/src/exit.s")
op exit(const int val): void

@link("./sdk/src/write.s")
op write(FD fd, const str val, const int size): void

@link("./sdk/src/fopen.s")
op fopen(const str val, FLAG flag, FMODE mode): File

3. Sample Application

// hello_world.az
import lib

write(Stdout, "Hello World\n", 12)

Build it with a single command:

azcli build hello_world.az
./hello_world

Pipeline: Tokenizer to AST

AzLang’s compiler frontend transforms raw human-readable source code into a strongly-typed Abstract Syntax Tree (AST).


1. Tokenizer

The tokenizer transforms raw source text into a stream of spanned tokens:

  • Indentation Tracking: Maintains an indentation stack to generate synthetic indent and dedent blocks (based on 4 spaces), giving AzLang its clean, readable syntax.
  • String Templates: Handles template interpolation (`text ${val}`) cleanly without dynamic runtime parsing.
  • Accurate Diagnostics: Tracks line and character offsets for precise compile-time error reporting.

2. Parser

The parser consumes tokens and builds a strongly-typed Abstract Syntax Tree (AST):

  • Statements:
    • Variable declarations (const / var)
    • Operations and procedures (op)
    • External system bindings (@link)
    • Enumerations (enum)
    • Conditional branching blocks (if, elif, else)
    • Loops (while, for, loop)
  • Expressions:
    • Binary operations (+, -, *, /), comparisons, identifiers, literals, function calls, and template expressions.

Semantic Validation & Symbol Resolution

Before any code generation takes place, AzLang programs pass through semantic validation.


1. Type and Symbol Verification

During semantic validation, the compiler analyzes program declarations to verify:

  • Type Safety: Variable assignments, arithmetic expressions, and function arguments match expected types.
  • Scope Management: Variables, constants, and functions are validated within their lexical scopes.
  • Link Registry: External function declarations (@link) are recorded as (operation, source path) pairs and prepared for assembly emission.
  • Unused & Mutation Tracking: Identifies immutable violations and unused bindings at compile-time.

2. Compile-Time Constant & Enum Resolution

AzLang resolves static constants and enumerations during validation:

  • Enum Inlining: Enum variants are assigned zero-based sequential numbers and stored directly in the compiler’s constant table.
  • Zero Runtime Memory: Any reference to an enum variant is converted directly into an immediate value before code generation. No lookup tables, dynamic allocations, or wrapper structures exist at runtime.

fasm Assembly Emission

AzLang compiles code by emitting a single, human-readable fasm (flat assembler) assembly file, which fasm turns directly into a native ELF executable in one pass.


1. Why fasm?

fasm was chosen because it aligns with AzLang’s minimalist engineering doctrine:

  • One Pass, One Binary: fasm assembles and links in a single step — there is no separate as, no ld, no object files.
  • Small Footprint: the entire fasm distribution is a single binary of well under 1 MB.
  • Readable Output: the emitted .asm is clean, commented-friendly x86_64 assembly you can inspect directly.

2. Sample Assembly Emission

Here is the exact assembly generated for the Hello World program (paths abbreviated; the compiler canonicalizes them to absolute paths):

format ELF64 executable
entry _start

segment readable executable

include "./sdk/src/write.s"
include "./sdk/src/exit.s"

_start:
    push rbp
    mov rbp, rsp
    sub rsp, 8
    mov rax, 1
    push rax
    lea rax, [main_str0]
    push rax
    mov rax, 25
    push rax
    pop rdx
    pop rsi
    pop rdi
    call write
    mov rax, 0
    push rax
    pop rdi
    call exit
    xor edi, edi
    mov eax, 60
    syscall

main_str0 db "Hello World from AzLang!",10,0

AzLang generates this directly from the validated AST:

  • Function calls lower to ordinary call <symbol> instructions following the System V AMD64 ABI (register arguments, 16-byte stack alignment).
  • String literals become db data directives (escape sequences such as \n are resolved to bytes at emission time).
  • @link(...) sources that are actually invoked are pulled in with include, so unused SDK stubs never reach the binary.
  • Programs end with a direct sys_exit (rax = 60) — no C runtime, no ret to nowhere.

Single-Pass Assembly & Binary Layout

The final stage of the AzLang compiler pipeline turns the emitted assembly into a finished, standalone bare-metal executable — in one invocation, with no linker.


1. Pipeline Execution Flow

AzLang produces machine code through a deterministic two-step lowering pipeline:

  1. Assembly Emission: the validated AST is lowered into one .asm file — header, include directives for every invoked @link source, the program’s code, and its string data.
  2. Single-Pass Assembly: fasm assembles that file directly into the final ELF executable. Assembly and linking happen in the same pass, so no intermediate object files ever exist.
fasm main.asm main

Because @link targets are fasm assembly sources (not pre-built .o files), there is nothing to pre-compile: the symbols write, exit, etc. are defined in the same translation unit and resolved statically at assembly time.


2. Resulting Binary

AzLang emits format ELF64 executable with entry _start and a single readable executable segment (a 120-byte program header). Because the program targets the system entry point _start and inlines its syscall stubs, no C runtime or dynamic linker is involved:

  • No dynamic interpreter (/lib64/ld-linux-x86-64.so.2 is not required)
  • No section headers, no relocations — a minimal static image
  • Tiny footprint: the Hello World program measures 180 bytes; a comprehensive 60-line multi-module program stays around 2 KB
  • Instantaneous startup: execution begins at _start with direct syscalls
$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header
$ ./main
Hello World from AzLang!