Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.stoffelmpc.com/llms.txt

Use this file to discover all available pages before exploring further.

Compilation

This page explains the StoffelLang compilation process, from source code to executable bytecode, including optimization techniques and debugging capabilities.

Overview

StoffelLang uses a multi-stage compilation pipeline that transforms human-readable source code into efficient bytecode for the StoffelVM. The compiler is designed to provide excellent error messages, strong type checking, and optimizations specific to MPC computations.

Compilation Pipeline

Stage 1: Lexical Analysis

The lexer tokenizes the source code, breaking it into meaningful tokens:
Source: let x: int64 = 42
Tokens: [LET, IDENTIFIER("x"), COLON, IDENTIFIER("int64"), ASSIGN, INT_LITERAL(42)]
Key Features:
  • Indentation-based: Uses 2-space indentation (tabs not allowed)
  • Unicode support: Full UTF-8 string and identifier support
  • Error recovery: Continues parsing after errors to find more issues

Stage 2: Parsing

The parser builds an Abstract Syntax Tree (AST) from the token stream:
AST Node: VariableDeclaration {
  name: "x",
  type_annotation: Some(Identifier("int64")),
  value: Some(Literal(Int(42))),
  is_mutable: false,
  is_secret: false,
  location: SourceLocation { line: 1, column: 1 }
}
Parser Features:
  • Recursive descent: Predictable parsing with clear error messages
  • Location tracking: Every AST node includes source location
  • Error recovery: Attempts to continue parsing after syntax errors

Stage 3: Semantic Analysis

The semantic analyzer performs type checking and builds the symbol table: Type Checking:
# This would produce a type error
let name: string = 42  # Error: Cannot assign int64 to string

# This works correctly
let age: int64 = 42    # OK: Types match
Symbol Resolution:
proc add(a: int64, b: int64): int64 =
  return a + b  # Resolves 'a' and 'b' to parameters

let result = add(10, 20)  # Resolves 'add' to function definition

Stage 4: Code Generation

Generates StoffelVM bytecode from the validated AST:
StoffelLang:           Bytecode:
let x: int64 = 42      LDI R0, 42
                      STORE x, R0

proc add(a, b):        FUNCTION add:
  return a + b           LOAD R0, a
                        LOAD R1, b
                        ADD R0, R0, R1
                        RET R0

Using the Compiler

Basic Compilation

# Compile a single file
stoffel compile src/main.stfl

# Compile to VM-compatible binary
stoffel compile src/main.stfl --binary --output program.stfbin

# Compile all files in src/
stoffel compile

Compilation Options

Optimization Levels

# No optimization (fastest compilation, good for debugging)
stoffel compile src/main.stfl -O0

# Basic optimizations (balanced)
stoffel compile src/main.stfl -O1

# Standard optimizations (recommended for production)
stoffel compile src/main.stfl -O2

# Maximum optimizations (slowest compilation, best performance)
stoffel compile src/main.stfl -O3

Output Formats

# Default bytecode format
stoffel compile src/main.stfl

# VM-compatible binary (for execution)
stoffel compile src/main.stfl --binary --output app.stfbin

# Specify custom output location
stoffel compile src/main.stfl --output custom/path/program.stfbin

Debug Information

# Include debug symbols
stoffel compile src/main.stfl --debug

# Print intermediate representations
stoffel compile src/main.stfl --print-ir

# Verbose compilation output
stoffel compile src/main.stfl --verbose

Optimization Techniques

Constant Folding

The compiler evaluates constant expressions at compile time:
# Source code
let result = 2 + 3 * 4

# Optimized to
let result = 14

Dead Code Elimination

Removes unreachable code:
# Source code
proc example(flag: bool) =
  if true:
    print("Always executed")
  else:
    print("Never executed")  # Removed by optimizer

# Optimized to
proc example(flag: bool) =
  print("Always executed")

Function Inlining

Small functions may be inlined at call sites:
# Source code
proc square(x: int64): int64 =
  return x * x

let result = square(5)

# May be optimized to
let result = 5 * 5

Secret Operation Optimization

Special optimizations for MPC operations:
# Source code
let a: secret int64 = 10
let b: secret int64 = 20
let sum = a + b
let product = a * b

# Compiler may batch secret operations for efficiency

Error Handling

Syntax Errors

Clear error messages with source locations:
Error: Unexpected token 'let'
  --> src/main.stfl:5:3
   |
 5 |   let x = 42
   |   ^^^ Expected expression, found 'let'
   |
Help: Variable declarations must be at the top level of a block

Type Errors

Detailed type mismatch information:
Error: Type mismatch in assignment
  --> src/main.stfl:8:12
   |
 8 | let name: string = 42
   |           ------   ^^ Expected 'string', found 'int64'
   |           |
   |           Variable declared as 'string' here
   |
Help: Convert the integer to string: "42" or $42

Semantic Errors

Context-aware error messages:
Error: Cannot find value 'undefined_var' in this scope
  --> src/main.stfl:12:15
   |
12 |   return undefined_var + 10
   |                ^^^^^^^^^^^^
   |
Help: Did you mean 'defined_var'? (defined at line 3)

Intermediate Representations

Viewing IR with —print-ir

stoffel compile src/main.stfl --print-ir
Output includes:
  1. Tokens: Lexical analysis output
  2. AST: Parsed syntax tree
  3. Type Information: Resolved types and symbols
  4. Bytecode: Generated VM instructions

Example IR Output

=== TOKENS ===
LET(1:1) IDENTIFIER("x", 1:5) COLON(1:6) IDENTIFIER("int64", 1:8) ASSIGN(1:14) INT_LITERAL(42, 1:16)

=== AST ===
VariableDeclaration {
  name: "x",
  type_annotation: Some(TypeRef("int64")),
  value: Some(IntLiteral(42)),
  is_mutable: false,
  location: SourceLocation(1:1)
}

=== BYTECODE ===
Constants:
  0: Int(42)

Instructions:
  0000: LDC R0, 0     ; Load constant 42
  0001: STORE x, R0   ; Store in variable x

Binary Format

File Structure

StoffelLang produces .stfbin files with the following structure:
┌─────────────────┐
│   Magic Number  │  4 bytes: "STFL"
├─────────────────┤
│   Version       │  4 bytes: Format version
├─────────────────┤
│   Metadata      │  Variable: Type information
├─────────────────┤
│   Constants     │  Variable: Constant pool
├─────────────────┤
│   Functions     │  Variable: Function definitions
├─────────────────┤
│   Instructions  │  Variable: Bytecode instructions
├─────────────────┤
│   Debug Info    │  Variable: Source locations
└─────────────────┘

Binary Inspection

# Disassemble a compiled binary
stoffel compile program.stfbin --disassemble

# Output shows human-readable bytecode
FUNCTION main:
  Constants: [Int(42), String("Hello")]
  Instructions:
    0000: LDC R0, 0      ; Load 42
    0001: LDC R1, 1      ; Load "Hello"
    0002: CALL print     ; Call print function
    0003: RET R0         ; Return

Compilation Workflow

Single File Compilation

# 1. Compile source to binary
stoffel compile src/main.stfl --binary --output app.stfbin

# 2. Run the compiled program
stoffel-run app.stfbin main

# 3. Debug if needed
stoffel-run app.stfbin main --trace-instr

Multi-File Projects

# 1. Compile all files
stoffel compile

# 2. The compiler automatically handles dependencies
# Files are compiled in dependency order

# 3. Single binary output contains all functions

Development Workflow

# 1. Write code
# edit src/main.stfl

# 2. Quick compile check
stoffel compile src/main.stfl

# 3. Full compile and test
stoffel compile src/main.stfl --binary --output test.stfbin
stoffel-run test.stfbin main

# 4. Debug compilation issues
stoffel compile src/main.stfl --print-ir

# 5. Production build
stoffel compile src/main.stfl --binary -O3 --output production.stfbin

Performance Considerations

Compilation Speed

Optimization LevelCompile TimeRuntime Performance
-O0FastestBasic
-O1FastGood
-O2MediumBetter
-O3SlowestBest

Memory Usage

  • Compiler memory: Scales with source code size and complexity
  • Binary size: Optimizations can reduce final binary size
  • Runtime memory: Efficient bytecode reduces VM memory usage

Secret Type Optimization

Special considerations for MPC operations:
# Expensive: Many individual secret operations
proc inefficient(a: secret int64, b: secret int64): secret int64 =
  let temp1 = a + 1
  let temp2 = b + 1
  let temp3 = temp1 + temp2
  return temp3 + 1

# Better: Batched operations where possible
proc efficient(a: secret int64, b: secret int64): secret int64 =
  return a + b + 2  # Compiler can optimize this

Troubleshooting

Common Compilation Errors

“Tabs are not allowed”
# Fix: Use 2 spaces instead of tabs
# Bad:
	let x = 42
# Good:
  let x = 42
“Indentation error”
# Fix: Consistent 2-space indentation
proc example() =
  if true:
    print("Correct indentation")
“Type mismatch”
# Fix: Ensure types match
let age: int64 = 25      # Correct
let name: string = "Bob" # Correct
# let wrong: string = 42  # Error

Debugging Tips

  1. Use —print-ir to see what the compiler generated
  2. Start with -O0 for debugging, optimize later
  3. Check types explicitly rather than relying on inference
  4. Use —verbose to see detailed compilation steps

Performance Issues

  1. Profile with —trace-instr during execution
  2. Try different optimization levels
  3. Review generated bytecode with —disassemble
  4. Minimize secret operations where possible

Integration with Development Tools

Editor Integration

# Generate compilation database for editors
stoffel compile --export-compile-commands

# This creates compile_commands.json for IDE integration

Build Systems

# Makefile integration
%.stfbin: %.stfl
	stoffel compile $< --binary --output $@

# Used as:
# make program.stfbin

Continuous Integration

#!/bin/bash
# CI script for StoffelLang projects

# Compile all files
stoffel compile

# Compile with different optimization levels
stoffel compile --binary -O0 --output debug.stfbin
stoffel compile --binary -O3 --output release.stfbin

# Run basic tests
stoffel-run debug.stfbin main

Advanced Topics

Cross-Compilation

Currently, StoffelLang generates platform-independent bytecode that runs on any StoffelVM instance.

Linking (Future)

Planned support for linking multiple compiled modules:
# Compile library
stoffel compile --lib src/math.stfl --output math.stflib

# Link with main program
stoffel compile src/main.stfl --link math.stflib --output app.stfbin

Plugin Architecture (Future)

Support for compiler plugins to extend functionality:
# Custom optimization passes
stoffel compile --plugin my_optimizer.so src/main.stfl

# Custom code generators
stoffel compile --target wasm --plugin wasm_gen.so src/main.stfl
This compilation guide provides comprehensive information about building StoffelLang programs and optimizing them for the StoffelVM runtime environment.