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

1.4 Statements

Variable Declarations

Variables must be declared with let or const, require a type annotation, and require an initializer:

let x:int = 42
const BUFFER_SIZE:int = 1024
let data:array<int> = __alloca__(BUFFER_SIZE)

let declares a mutable binding. const declares an immutable binding and cannot be assigned after its initializer.

At local scope, the initializer must be a normal expression. extern initializers are not allowed inside function bodies.

Ignored Type Declarations

Anywhere a statement or top-level declaration may appear, udewy accepts type declarations of the form <IDENT>:type = <EXPR>, let <IDENT>:type = <EXPR>, or const <IDENT>:type = <EXPR>, e.g.

Point:type = [x:int y:int]
let Point:type = [x:int y:int]
const Line:type = [start:Point end:Point]

Semantics:

  • The type annotation must exactly be the literal type
  • The declaration is parsed and ignored.
  • The right-hand side is not evaluated.
  • The declared name may still appear inside type annotations or other ignored type declarations.
  • The declared name may not be used as a runtime value; doing so is a compile-time error.

Assignment

Simple assignment:

x = 42

The assignment target must be a let binding. Assigning to a const is a compile-time error.

Compound assignment operators combine a binary operation with assignment:

OperatorEquivalent
x += yx = x + y
x -= yx = x - y
x *= yx = x * y
x //= yx = x // y
x %= yx = x % y
x <<= yx = x << y
x >>= yx = x >> y
x and= yx = x and y
x or= yx = x or y
x xor= yx = x xor y

If / Else

if condition {
    # then branch
} else if other_condition {
    # else-if branch
} else {
    # else branch
}

Braces are always required. Conditions check if any bit is set (non-zero = true, zero = false).

Well-formedness note: Full Dewy requires conditions to be strictly bool typed. Using a non-bool value as a condition (e.g., if some_int { ... }) will fail Dewy type-checking even though it compiles in udewy.

Loop

udewy has a single loop construct that loops while a condition is true:

let i:int = 0
loop i <? 10 {
    # body
    i = i + 1
}

The condition is evaluated before each iteration. Braces are required.

Break and Continue

Within a loop:

  • break exits the innermost loop immediately
  • continue jumps to the next iteration (re-evaluates condition)
loop true {
    if done {
        break
    }
    if skip_this {
        continue
    }
    # ...
}

Return

All functions must explicitly return using return:

return value     # return a value
return void      # return from a void function

The return expression is mandatory. Use return void for functions that don't return a meaningful value.

Prelude Directives

Prelude directives are preprocessing-only forms recognized before tokenization. They may appear only in the leading prelude at the top of a file or inside active preprocessor target blocks in that prelude. They are removed before the normal udewy parser sees the source.

Include Bytes

$include_bytes(p"tables/gcb.bin") as gcb_table

$include_bytes(p"path") as name embeds a file's contents as read-only static data and binds name (a module-level int64) to its address — exactly as let name:int64 = 0x"…" of the same bytes would. It is a prelude directive: it may appear only in the leading prelude alongside import and $supported_targets, the argument must be a single path literal (nothing else is accepted), and a relative path is resolved against the directory of the file containing the directive. The file is read by the preprocessor, so its bytes never appear in the program text; a missing file is a compile-time error. Generated programs use it for large tables (the Dewy compiler's Unicode data).

Import Directives

Import directives bring definitions from other udewy files into scope:

import p"utils.udewy"
import p"lib/helpers.udewy"
import p"../third_party/libfoo.a"

Semantics:

  • Paths are relative to the importing file's directory
  • Imports are recognized only in the leading prelude at the top of a file
  • Imports ending in .udewy are treated as udewy source and processed recursively
  • Imported paths with any other suffix are treated as direct external link artifacts, not source
  • Native artifacts are expected to be fully prepared for the final backend link step; native targets hand them directly to the system linker
  • Each imported source file or artifact path is only included once
  • Imported udewy source is prepended to the source being compiled
  • After preprocessing, import directives are removed from the source before tokenization and parsing
  • import remains a reserved word; if it reaches tokenization, the tokenizer reports an error

The import preprocessor records the resolved paths of imported udewy source files as generic provenance. It does not interpret those paths beyond source loading and duplicate suppression; concrete backends may use that provenance to recognize their own library modules.

Target Support Metadata

Any source file may declare the targets it supports:

$supported_targets = ["c" "wasm32" "x86_64"]

If the selected compile target is not present, preprocessing stops with a diagnostic for that file. Target names are the same names accepted by the compiler's --target flag.

Target-Conditional Prelude Blocks

Target-conditional blocks choose which prelude directives are active:

if $target =? "wasm32" {
    import p"./backend_wasm.udewy"
}

if $target not=? "c" {
    import p"./native_only.udewy"
}

Only the exact $target =? "..." and $target not=? "..." conditions are supported. The block body may contain only prelude directives. Inactive blocks are skipped without resolving their imports or emitting their diagnostics.

Diagnostic Directives

Source files may emit preprocessor diagnostics:

$warning("wasm32 has limited support")
$error("this target needs a custom backend module")

Both forms accept exactly one string literal. $warning prints a source-context warning and continues. $error stops preprocessing with the provided message.