DOCUMENTATION

Functions & Fibers

DOCUMENTATION

XCX 4.4.1 Functions and Fibers

IMPORTANT:

Global Scope Rule: Functions and fibers must be declared at the top level of a file. They cannot be nested inside if/while/for blocks or other functions/fibers in a way that affects scoping - all function and fiber names are registered globally during compilation.

Functions

Definition Styles

Parameters follow the type: name pattern (e.g., i: count).

NOTE:

Semicolons after blocks are optional (recommended style: without). The

; after a function's or fiber's closing } may be omitted and is

removed in XCX 5.0a. Statement semicolons inside the body stay required.

$ xcx
_ ⛶ ×
1--- No parameters, no return value
2func hello() {
3 >! "Hello!";
4};
5
6--- No parameters, with return value
7func get_pi(-> f) {
8 return 3.14159;
9};
10
11--- With parameters, no return value
12func greet(s: who) {
13 >! "Hello, " + who + "!";
14};
15
16--- With parameters and return value
17func add(i: x, i: y -> i) {
18 return x + y;
19};

Calling Functions

$ xcx
_ ⛶ ×
1hello();
2f: pi = get_pi();
3greet("Alice");
4i: result = add(3, 4);

Recursion

Max depth: 800 frames. Exceeding this triggers halt.error.

$ xcx
_ ⛶ ×
1func factorial(i: n -> i) {
2 if (n <= 1) then;
3 return 1;
4 else;
5 return n * factorial(n - 1);
6 end;
7};
8>! factorial(5); --- 120

Fibers (Coroutines)

Fibers can suspend execution with yield and be resumed. There are two variants: typed (yield returns a value) and void (yield without a value).

Definition

$ xcx
_ ⛶ ×
1--- Typed Fiber: each yield returns a value of type T
2fiber generator(i: max -> i) {
3 for i in 1 to max do;
4 yield i;
5 end;
6 return 0;
7};
8
9--- Void Fiber: yield without a value
10fiber logger(s: msg) {
11 if (msg == "") then; return; end;
12 >! msg;
13 yield;
14};

Instantiation

$ xcx
_ ⛶ ×
1fiber:i: gen = generator(10); --- typed
2fiber: log = logger("init"); --- void

Fiber Methods

MethodWorks onReturnsDescription
.next()fiber:TTResumes; returns next yielded value
.run()fiber:bResumes void fiber one step
.isDone()bothbtrue when fiber has finished
.close()bothbForcefully terminates the fiber

Calling .next() when isDone() == true triggers halt.alert (R306).

yield

$ xcx
_ ⛶ ×
1--- In a typed fiber
2yield true;
3yield score + 10;
4
5--- In a void fiber
6yield;

return in Fibers

1. Typed fiber (fiber ... -> T): Typed fiber requires return expr; not plain return;. Returning without a value throws a compile error (S210).

2. Void fiber: Uses return; to exit early.

$ xcx
_ ⛶ ×
1fiber:i: gen(i: max -> i) {
2 for i in 1 to max do;
3 if (i == 3) then;
4 return 99; --- Valid: terminates and returns 99
5 end;
6 yield i;
7 end;
8 return 0; --- Required at end of typed fiber
9};
10
11fiber logger(s: msg) {
12 if (msg == "") then;
13 return; --- Valid for void fiber
14 end;
15 >! msg;
16};

for Loop over a Fiber

$ xcx
_ ⛶ ×
1fiber:i: f = generator(5);
2for val in f do;
3 >! val;
4end;

Equivalent to while (!f.isDone()) { val = f.next(); ... }. break inside the loop automatically calls .close().

NOTE:

The fiber's return value is the last iteration item. Once the yields

are exhausted, the final next() executes the fiber's return and the

loop delivers that value as the last element (a fiber ending with

return 99 emits 99 last). This follows directly from the

while (!isDone()) { next() } equivalence above and is intentional. It

does not apply through yield from - see Delegation below.

Fiber as Function Parameter

$ xcx
_ ⛶ ×
1func run_checks(fiber:b: f) {
2 while (f.isDone() == false) do;
3 b: result = f.next();
4 if (result == false) then;
5 halt.alert >! "Step failed";
6 return;
7 end;
8 end;
9};
10
11fiber:b: checks = login_pipeline(user, pass);
12run_checks(checks);

yield from (Delegation)

Delegates execution to a sub-fiber. The compiler desugars this into a loop that yields every value from the sub-fiber.

NOTE:

The sub-fiber's return value is not re-yielded. Delegation runs the

sub-fiber to completion and yields only its yielded values (in the example

below, count's return 0 never surfaces). This is intentional and

differs from a direct for over the same fiber, whose last iteration item

is the return value - see the note in the previous section.

$ xcx
_ ⛶ ×
1fiber count(i: n -> i) {
2 i: x = 0;
3 while (x < n) do;
4 yield x;
5 x = x + 1;
6 end;
7 return 0;
8};
9
10fiber delegator(-> i) {
11 fiber:i: sub = count(3);
12 yield from sub; --- yields: 0, 1, 2
13 yield 100; --- then yields: 100
14 return 0;
15};

Manual Delegation

$ xcx
_ ⛶ ×
1fiber pipeline(s: user, s: pass -> b) {
2 fiber:b: step1 = check_user(user);
3 yield step1.next();
4
5 fiber:b: step2 = check_pass(user, pass);
6 yield step2.next();
7
8 return false;
9};