Quartz v5.25

Phase 8: Const Evaluation

Priority: 8 | Duration: ~5 hours (was: 3-4 weeks) | Risk: High

Compile-time computation enables powerful metaprogramming and eliminates runtime overhead. Status: NEARLY COMPLETE — Const declarations, static_assert, const evaluator (all ops), @cImport integration, const functions, const conditionals, and generic struct semantics (G2) all done. Only const generics (G3) and const-in-array-sizes remain.


Prelude: Standards

We accept only world-class solutions.

Const evaluation is a significant undertaking. The implementation must:

  1. Evaluate expressions at compile time
  2. Support arithmetic, logic, and function calls
  3. Provide clear errors for non-const operations

Before writing any code:

  1. Study Zig’s comptime extensively
  2. Define clear boundaries for what’s evaluable
  3. Write tests for each supported operation
  4. Run rake quartz:validate after changes

Rationale

The Problem

Currently, no compile-time computation exists:

# Can't do this
const BUFFER_SIZE = 1024 * 4
const PI = 3.14159265358979

# Can't do this
type Buffer = Array<U8, BUFFER_SIZE>

# Can't do this
const fn is_power_of_two(n: Int): Bool = (n & (n - 1)) == 0

The Benefit

const HEADER_SIZE = 20
const PAYLOAD_SIZE = 1480
const PACKET_SIZE = HEADER_SIZE + PAYLOAD_SIZE  # Evaluated at compile time

# Array with compile-time size
type Packet = Array<U8, PACKET_SIZE>

# Compile-time validation
static_assert(PACKET_SIZE <= 1500, "Packet too large for MTU")

Design

Const Declarations

const MAX_SIZE = 1024
const PI = 3.14159
const MESSAGE = "Hello"

Const Functions

const def square(n: Int): Int = n * n
const def is_even(n: Int): Bool = n % 2 == 0

Const Blocks

const {
  SIZE = calculate_size()
  OFFSET = SIZE + 4
}

Evaluation Rules

ExpressionConst-Evaluable
Integer literalsYes
Float literalsYes
String literalsYes
Arithmetic operationsYes
Comparison operationsYes
Logical operationsYes
Const function callsYes
Conditionals (if/match)Yes
LoopsYes (bounded)
Heap allocationNo
I/O operationsNo
Runtime-only intrinsicsNo

Tasks

8.1 Const Declarations

8.1.1 Parser Support

File: quartz-bootstrap/src/parser.c

const NAME = expression
  • Parse const keyword before binding
  • Store is_const flag in binding AST

8.1.2 Type System

  • Mark const bindings as compile-time
  • Const bindings cannot be reassigned (already const-by-default)
  • Const bindings must have const-evaluable initializers

8.2 Const Evaluator

8.2.1 Interpreter Implementation

File: quartz-bootstrap/src/const_eval.c (new file)

Create a compile-time expression evaluator:

typedef struct {
    enum { CONST_INT, CONST_FLOAT, CONST_STRING, CONST_BOOL } kind;
    union {
        int64_t int_val;
        double float_val;
        const char* string_val;
        bool bool_val;
    };
} ConstValue;

ConstValue const_eval(Expr* expr);
  • Evaluate integer literals
  • Evaluate float literals
  • Evaluate string literals
  • Evaluate boolean literals

8.2.2 Arithmetic Operations

case EXPR_ADD:
    ConstValue left = const_eval(expr->left);
    ConstValue right = const_eval(expr->right);
    return (ConstValue){ .kind = CONST_INT, .int_val = left.int_val + right.int_val };
  • Implement add, sub, mul, div, mod
  • Implement negation
  • Handle overflow (wrap like runtime)

8.2.3 Comparison Operations

  • Implement eq, ne, lt, le, gt, ge
  • Return CONST_BOOL

8.2.4 Logical Operations

  • Implement and, or, not
  • Short-circuit evaluation

8.2.5 Conditional Expressions (COMPLETE)

const X = if A > B then A else B
  • Evaluate condition at compile time
  • Evaluate selected branch only

8.3 Const Functions (COMPLETE)

8.3.1 Const Function Syntax

const def max(a: Int, b: Int): Int
  if a > b
    return a
  else
    return b
  end
end
  • Parse const def as const function
  • Store in function registry with const flag

8.3.2 Const Function Calls

  • Only const functions can be called at const time
  • All arguments must be const-evaluable
  • Result is folded into the caller

8.3.3 Const Function Body Evaluation

  • Execute function body in const evaluator
  • Handle return statements
  • Handle local variables (compile-time stack)

8.4 Loops in Const Context (COMPLETE)

8.4.1 Bounded Loops

const def factorial(n: Int): Int
  var result = 1
  for i in 1..n+1
    result = result * i
  end
  return result
end
  • Track iteration count (1M iteration limit for while, range-based for)
  • Error if exceeds limit
  • Prevent infinite loops

8.5 Static Assertions

8.5.1 static_assert Intrinsic

static_assert(SIZE <= 1024, "Size too large")
static_assert(is_power_of_two(BUFFER_SIZE), "Buffer size must be power of 2")
  • Evaluate condition at compile time
  • Error with message if condition is false

8.6 Const Generics (Future)

struct Array<T, const N: Int>
  data: Ptr<T>
  
  const def len(): Int = N
end

type Buffer = Array<U8, 1024>
  • Mark as future extension
  • Document design direction

8.7 Self-Hosted Implementation

  • Add const parser support
  • Implement const evaluator
  • Add const function support

8.8 Test Suite

8.8.1 Basic Const Evaluation

describe "const evaluation" do
  it "evaluates const arithmetic" do
    result = compile_and_run(<<~QZ)
      const X = 10 + 20
      def main(): Int = X
    QZ
    expect(result).to eq(30)
  end
  
  it "evaluates const expressions with parens" do
    result = compile_and_run(<<~QZ)
      const X = (3 + 4) * 2
      def main(): Int = X
    QZ
    expect(result).to eq(14)
  end
end

8.8.2 Const Functions

it "evaluates const function calls" do
  result = compile_and_run(<<~QZ)
    const def square(n: Int): Int = n * n
    const SIZE = square(8)
    def main(): Int = SIZE
  QZ
  expect(result).to eq(64)
end

8.8.3 Static Assertions

it "passes static assertions" do
  result = compile_and_run(<<~QZ)
    const SIZE = 100
    static_assert(SIZE < 1000, "too big")
    def main(): Int = 0
  QZ
  expect(result).to eq(0)
end

it "fails static assertions" do
  result = compile_only(<<~QZ)
    const SIZE = 2000
    static_assert(SIZE < 1000, "too big")
  QZ
  expect(result.stderr).to include("too big")
end
  • Test const arithmetic
  • Test const functions
  • Test const conditionals
  • Test static_assert pass/fail
  • Test error on non-const expression

8.9 Documentation

File: ref.md

### Const Evaluation

Compile-time constants:

```quartz
const SIZE = 1024
const PI = 3.14159
const NAME = "Quartz"

Const functions:

const def square(n: Int): Int = n * n
const AREA = square(10)  # 100, computed at compile time

Static assertions:

static_assert(SIZE <= 4096, "Buffer too large")

Const-evaluable expressions:

  • Literals
  • Arithmetic (+, -, *, /, %)
  • Comparisons (==, !=, <, <=, >, >=)
  • Logic (and, or, not)
  • Const function calls
  • Conditionals (if/match)
  • Bounded loops

- [x] Add const evaluation section
- [x] Document const functions
- [x] Document static_assert
- [x] Document limitations

---

## Verification

```bash
rake test
rake quartz:validate

Success Criteria

  • const declarations work
  • Const arithmetic evaluated at compile time
  • Const functions work
  • static_assert works
  • Clear errors for non-const operations
  • Tests pass
  • Fixpoint validates

Next Phase

After completing Phase 8, proceed to Phase 9: Inline Assembly Improvements.