|
226 | 226 |
|
227 | 227 | Assignments have the syntax `TYPE : identifier = expression` on first use, where TYPE is `INT`, `FLT`, `STR`, `TNS`, or `FUNC`. Spaces around the colon and equals sign are optional. Subsequent assignments to an existing identifier may omit the type but must preserve the original type. Variables are deallocated only when `DEL(identifier)` is executed. |
228 | 228 |
|
| 229 | +Inline assignment operator: the built-in `ASSIGN` provides an expression form of assignment, similar to a walrus operator. The general form is `ASSIGN(target, expression)` and it evaluates `expression`, assigns it to `target`, and returns the assigned value. The `target` may be a plain identifier (e.g. `ASSIGN(x, 1)`) or an indexed assignment target (e.g. `ASSIGN(tensor[1], 0)` or `ASSIGN(map<"k">, 1)`). If the identifier has not yet been declared, the typed form is required: `ASSIGN(TYPE: name, expression)` declares the identifier's type and performs the assignment in one step. The typed form is only valid for plain identifiers; indexed targets must already exist and follow the same indexed-assignment rules as statement assignments. |
| 230 | +
|
229 | 231 | Tensor elements can be reassigned with the indexed form `identifier[i1,...,iN] = expression`. The base must be a previously-declared `TNS` binding. The indices must match the tensor's dimensionality, follow the same one-based/negative-index rules as ordinary indexing, and must reference anexisting position. The element's original type cannot change: attempting to store a different type at that position is a runtime error. Indexed assignment mutates the `TNS`. |
230 | 232 |
|
231 | 233 | The language provides `IF`, `ELSEIF`, and `ELSE` constructs for conditional execution. An `IF` statement has the general form `IF(condition){ block }`. Optional chained branches may follow: one or more `ELSEIF(condition){ block }` clauses and an optional terminal `ELSE{ block }` clause. An `ELSEIF` or `ELSE` must immediately follow an `IF` or another `ELSEIF`; otherwise it is a syntax error. At most one `ELSE` may appear in a given chain. Evaluation proceeds by first evaluating the condition of the initial `IF`. If it is non-zero, the associated block executes and the rest of the chain is skipped. Otherwise, the conditions of subsequent `ELSEIF` clauses are evaluated in order until one is non-zero; its block then executes and the chain terminates. If no `IF` or `ELSEIF` condition is satisfied and an `ELSE` is present, the `ELSE` block executes; if there is no `ELSE`, no block in the chain executes. |
|
520 | 522 |
|
521 | 523 | - `DEL(SYMBOL: x)` ; delete variable `x` from environment |
522 | 524 |
|
| 525 | +- `ASSIGN(SYMBOL: target, ANY: value):ANY` — Evaluate `value`, assign it to `target`, and return the assigned value. `target` may be a plain identifier or an indexed target (`tensor[...]` or `map<...>`). If the identifier has not been declared, use the typed form `ASSIGN(TYPE: name, value)` to declare and assign in one step. The typed form is only valid for plain identifiers; indexed targets must already exist. |
| 526 | +
|
523 | 527 | - `EXIT()` or `EXIT(INT:code)` — Requests immediate termination of the interpreter. If an integer `code` is supplied, it is used as the interpreter's process exit code; otherwise `0` is used. Execution stops immediately when `EXIT` is executed (no further statements run), and an entry is recorded in the state log to make deterministic replay possible. Using `EXIT` inside a function terminates the entire program (not just the function). |
524 | 528 |
|
525 | 529 | - `INT(STR: x):INT` ; `STR` -> `INT` using empty/01/other rules; `INT` passthrough |
|
560 | 564 |
|
561 | 565 | ### 12.2 Arithmetic (`INT` or `FLT`, no mixing) |
562 | 566 |
|
563 | | -- `ADD(INT|FLT: a, INT|FLT: b):INT|FLT` ; a + b |
| 567 | +- `ADD(INT|FLT: a, INT|FLT: b):INT|FLT` ; `a` + `b` |
564 | 568 |
|
565 | | -- `SUB(INT|FLT: a, INT|FLT: b):INT|FLT` ; a - b |
| 569 | +- `SUB(INT|FLT: a, INT|FLT: b):INT|FLT` ; `a` - `b` |
566 | 570 |
|
567 | | -- `MUL(INT|FLT: a, INT|FLT: b):INT|FLT` ; a * b |
| 571 | +- `MUL(INT|FLT: a, INT|FLT: b):INT|FLT` ; `a` * `b` |
568 | 572 |
|
569 | | -- `DIV(INT|FLT: a, INT|FLT: b):INT|FLT` ; floor(a / b) |
| 573 | +- `DIV(INT|FLT: a, INT|FLT: b):INT|FLT` ; floor(`a` / `b`) |
570 | 574 |
|
571 | | -- `CDIV(INT|FLT: a, INT|FLT: b):INT|FLT` ; ceil(a / b) |
| 575 | +- `CDIV(INT|FLT: a, INT|FLT: b):INT|FLT` ; ceil(`a` / `b`) |
572 | 576 |
|
573 | | -- `POW(INT|FLT: a, INT|FLT: b):INT|FLT` ; a ^ b |
| 577 | +- `POW(INT|FLT: a, INT|FLT: b):INT|FLT` ; `a` ^ `b` |
| 578 | +- `ROOT(INT|FLT: x, INT|FLT: n):INT|FLT` ; `n`th root of `x`. No mixing of `INT` and `FLT` is allowed. For `INT` arguments `n` must be non-zero; positive `n` returns the integer nth root (largest integer r with r^n <= x for x >= 0); negative `n` yields an integer result only for `x` equal to `1` or `-1` (reciprocal is integer), and `x < 0` requires odd `n`. For `FLT` arguments the result is `x^(1/n)` (negative `n` allowed); negative `x` is allowed only when `n` is an odd integer. Division by zero is an error. |
574 | 579 |
|
575 | | -- `ROOT(INT|FLT: x, INT|FLT: n):INT|FLT` ; nth root of `x`. No mixing of `INT` and `FLT` is allowed. For `INT` arguments `n` must be non-zero; positive `n` returns the integer nth root (largest integer r with r^n <= x for x >= 0); negative `n` yields an integer result only for `x` equal to `1` or `-1` (reciprocal is integer), and `x < 0` requires odd `n`. For `FLT` arguments the result is `x^(1/n)` (negative `n` allowed); negative `x` is allowed only when `n` is an odd integer. Division by zero is an error. |
| 580 | +- `MOD(INT|FLT: a, INT|FLT: b):INT|FLT` ; remainder of `a` / `b` |
576 | 581 |
|
577 | | -- `MOD(INT|FLT: a, INT|FLT: b):INT|FLT` ; remainder of a / b |
| 582 | +- `NEG(INT|FLT: a):INT|FLT` ; -`a` (additive inverse) |
578 | 583 |
|
579 | | -- `NEG(INT|FLT: a):INT|FLT` ; -a (additive inverse) |
| 584 | +- `ABS(INT|FLT: a):INT|FLT` ; absolute value of `a` |
580 | 585 |
|
581 | | -- `ABS(INT|FLT: a):INT|FLT` ; absolute value of a |
| 586 | +- `GCD(INT|FLT: a, INT|FLT: b):INT|FLT` ; greatest common divisor of `a` and `b` |
582 | 587 |
|
583 | | -- `GCD(INT|FLT: a, INT|FLT: b):INT|FLT` ; greatest common divisor of a and b |
584 | | -
|
585 | | -- `LCM(INT|FLT: a, INT|FLT: b):INT|FLT` ; least common multiple of a and b |
| 588 | +- `LCM(INT|FLT: a, INT|FLT: b):INT|FLT` ; least common multiple of `a` and `b` |
586 | 589 |
|
587 | 590 | ### 12.3 Bitwise / Boolean |
588 | 591 |
|
|
612 | 615 |
|
613 | 616 | ### 12.4 Comparisons |
614 | 617 |
|
615 | | -- `EQ(ANY: a, ANY: b):INT` ; 1 if a == b else 0 |
| 618 | +- `EQ(ANY: a, ANY: b):INT` ; 1 if `a` == `b` else 0 |
| 619 | + |
| 620 | +- `GT(INT|FLT: a, INT|FLT: b):INT` ; 1 if `a` > `b` else 0 (no mixing `INT`/`FLT`) |
616 | 621 |
|
617 | | -- `GT(INT|FLT: a, INT|FLT: b):INT` ; 1 if a > b else 0 (no mixing `INT`/`FLT`) |
| 622 | +- `LT(INT|FLT: a, INT|FLT: b):INT` ; 1 if `a` < `b` else 0 (no mixing `INT`/`FLT`) |
618 | 623 |
|
619 | | -- `LT(INT|FLT: a, INT|FLT: b):INT` ; 1 if a < b else 0 (no mixing `INT`/`FLT`) |
| 624 | +- `GTE(INT|FLT: a, INT|FLT: b):INT` ; 1 if `a` >= `b` else 0 (no mixing `INT`/`FLT`) |
620 | 625 |
|
621 | | -- `GTE(INT|FLT: a, INT|FLT: b):INT` ; 1 if a >= b else 0 (no mixing `INT`/`FLT`) |
622 | | -- `LTE(INT|FLT: a, INT|FLT: b):INT` ; 1 if a <= b else 0 (no mixing `INT`/`FLT`) |
| 626 | +- `LTE(INT|FLT: a, INT|FLT: b):INT` ; 1 if `a` <= `b` else 0 (no mixing `INT`/`FLT`) |
623 | 627 |
|
624 | 628 | ### 12.5 Aggregates / Utilities |
625 | 629 |
|
|
0 commit comments