Skip to content
Xen / docs

Search documentation

English · v0.1.0-demo.3

Type to search the documentation.

    한국어
    Xen / learn v0.1.0-demo.3

    Scope modes

    This chapter starts the advanced path. You have built a program using default behavior and the standard library. Now choose features for individual functions or blocks to control changes to original values and the extent of optimization. The next chapter, copies, moves, and references, develops the borrowing rules.

    Scope modes enable features in a particular function or block. explc and opt serve different purposes.

    AnnotationLocationPurpose
    #![explc]Immediately before a functionUse explicit references in that function.
    #scope[explc] { ... }A block inside a functionUse explicit references within that block.
    #scope[opt] { ... }A block inside a functionMark code for the selected optimization option.

    let mut allows a variable to change. explc allows explicit references. Neither replaces the other.

    Save this as scope_modes.xen. append_shared declares a reference parameter, so it has #![explc]. In main, only the part that creates and passes the reference is enclosed in #scope[explc].

    scope_modes.xen
    #![explc]
    fn append_shared(values: &mut Vec<Int>) {
    values.push(3);
    }
    fn main() {
    let mut values = [1, 2];
    #scope[explc] {
    append_shared(&mut values);
    }
    println(values);
    let mut total = 0;
    #scope[opt] {
    for value in 1..5 {
    total = total + value;
    }
    }
    println(total);
    }
    Terminal window
    xen check scope_modes.xen
    xen run scope_modes.xen
    scope_modes.stdout
    [1, 2, 3]
    10

    The caller’s vector now contains 3. Unlike passing a value and changing an independent copy, &mut values refers to the caller’s original. The sum calculation is marked separately with opt.

    When explicit references are used throughout a function, you can also put #![explc] immediately before main. Choose the function or block boundary to match where references are needed.

    A callee’s annotation does not annotate its caller

    Section titled “A callee’s annotation does not annotate its caller”

    This program deliberately fails. Run xen check scope_error.xen:

    scope_error.xen
    #![explc]
    fn append_shared(values: &mut Vec<Int>) { values.push(3); }
    fn main() {
    let mut values = [1, 2];
    append_shared(&mut values);
    }
    scope_error.stderr
    passing references requires #![explc]

    Annotating append_shared does not enable &mut values inside main. Enclose the call in #scope[explc], as in the working program, or annotate main with #![explc]. Check both the function declaring reference parameters and the caller creating references.

    explc preserves borrowing restrictions. You cannot change or move an original while shared references remain in use, or access it through another path while a mutable reference remains in use. Borrowing a temporary directly, returning references, and storing references in struct fields are unavailable.

    Run the same program with optimization disabled and enabled:

    Terminal window
    xen run scope_modes.xen --opt=off
    xen run scope_modes.xen --opt=basic
    xen run scope_modes.xen --opt=basic --opt-report
    xen build scope_modes.xen --opt=basic --opt-cache=.xen-opt-cache -o scope-modes

    The first two commands produce the standard output shown above. --opt-report writes application information separately to stderr. Do not use report line counts or internal identifiers as part of your program’s output contract.

    build, run, and test default to --opt=basic. Optimization applies to code marked with #scope[opt]; unmarked code is unaffected. --opt-report and --opt-cache require basic and are unavailable for check. Checking does not execute the program or measure performance.

    This small example teaches annotation placement and the execution workflow. Marking a block does not by itself establish a speed improvement.

    bb enables raw memory, volatile and atomic operations, syscalls, external C calls, and inline assembly. The low-level reference documents its APIs, target support, and caller responsibilities. Use the standard library for ordinary files, I/O, and paths.

    Look up rules in the scope modes reference and options in the CLI reference.