Skip to content

Commit bc6bef8

Browse files
Add PARFOR (parallel for), vectorized image ops, and performance improvements
Language/API: introduce PARFOR in SPECIFICATION, lexer, and parser; add ParForStatement AST node and REPL block detection. Interpreter: implement _execute_parfor with threaded iteration execution, iteration-local counter semantics, merge/backpressure on shared bindings, proper BREAK/CONTINUE behavior; restore FOR counter scoping; add fast-path/robust merging and error propagation. Performance & safety: convert many hot dataclasses to slots=True; inline environment lookup/set/delete hot-paths; optimize hook emission and step-rule short-circuits. ext/image.py: replace per-pixel Python loops with NumPy-vectorized routines and optional threading; add helpers (_tensor_to_int_image, _value_tensor_from_ints, _resize_image_int) and ThreadPoolExecutor usage for blit/scale/resize/grayscale/blur/invert/edge/replace_color/thresh implementations. Libraries: update several lib/*.asmln modules (stats, waveforms, csprng, etc.) to use PARFOR for parallel reductions and faster data movement; adjust tensor/key/nonce representations and related routines.
1 parent df66a06 commit bc6bef8

File tree

10 files changed

+593
-473
lines changed

10 files changed

+593
-473
lines changed

SPECIFICATION.html

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,20 @@
149149
150150
Conditions accept `INT`, `STR`, or `TNS`. `STR` conditions are first converted to `INT` using the `INT` built-in rules (empty -> 0; binary string -> that integer; other non-empty -> 1) before truthiness is checked. A `TNS` condition is true if any of its elements is true by the `INT`/`STR` truthiness rules.
151151
152-
Loops are provided via `WHILE` and `FOR`. A `WHILE` loop has the form `WHILE(condition){ block }`. On each iteration, the condition is evaluated; if it is non-zero, the block executes and control returns to the start of the loop to evaluate the condition again. If the condition evaluates to zero, the loop terminates and execution continues with the next statement.
152+
Loops are provided via `WHILE`, `FOR`, and `PARFOR`. A `WHILE` loop has the form `WHILE(condition){ block }`. On each iteration, the condition is evaluated; if it is non-zero, the block executes and control returns to the start of the loop to evaluate the condition again. If the condition evaluates to zero, the loop terminates and execution continues with the next statement.
153153
154154
The `FOR` construct has the form `FOR(counter, target){ block }`, where `counter` is an identifier and `target` is an expression. At loop entry, `target` is evaluated once to a value `T` (must be `INT`), and `counter` is initialized to the `INT` value `0`, creating it as an `INT` if necessary. The loop then repeats: if the current value of `counter` is greater than or equal to `T`, the loop exits; otherwise, the block executes and `counter` is incremented by `1` before the next iteration.
155155
156+
Note on scoping: the loop `counter` is loop-local and does not persist in the enclosing environment after the `FOR` completes (any prior binding with the same name is restored). Any other identifiers that are declared (first assigned with a `TYPE:` declaration) inside the `FOR` body are bound in the enclosing environment (that is, they persist after the loop finishes).
157+
158+
The `PARFOR` construct has the form `PARFOR(counter, target){ block }`. Semantically, the interpreter evaluates `target` once at loop entry (must be `INT`) yielding `T`, then concurrently executes `T` independent iterations indexed from `1` to `T` (inclusive). Each iteration runs the loop `block` with the loop `counter` bound to its iteration index. The interpreter waits for all iterations to complete before proceeding to the statement following the `PARFOR` block. Iteration bodies execute in parallel and may run on different threads; therefore, writes to shared mutable identifiers are subject to race conditions. To avoid unintended races, iteration-local state should be stored in identifiers that are created inside the iteration body or otherwise synchronized by user code. Runtime errors raised inside an iteration are reported and will cause the `PARFOR` to fail after all iterations have joined; the first such error is re-raised to the caller.
159+
160+
Note on scoping: as with `FOR`, the loop `counter` is iteration-local and does not persist in the enclosing environment after the `PARFOR` completes. Identifiers (other than the counter) that are declared inside iteration bodies are nevertheless bound in the enclosing environment; when iterations finish, the interpreter merges those bindings back into the enclosing scope. Because iterations execute concurrently, concurrent writes to the same identifier are subject to race conditions and the final value is implementation-defined (the reference implementation uses a last-writer-wins merge strategy).
161+
162+
Loop-control semantics inside `PARFOR` differ from sequential loops in the following ways:
163+
- `CONTINUE()` ends the current iteration only; it does not affect other concurrently running iterations.
164+
- `BREAK(n)` terminates the entire `PARFOR`. When a `BREAK` is executed in any iteration, the interpreter signals termination of the `PARFOR`, stops starting any further iterations, waits for currently-running iterations to complete, and then behaves as if `BREAK(n)` had executed at the `PARFOR` site (that is, a `BreakSignal` is propagated to outer loop handlers). Note that because iterations execute concurrently on threads, iterations already executing when the `BREAK` occurred will run to completion unless they themselves check user-level synchronization; `BREAK` prevents additional iterations from starting and ensures the `PARFOR` as a whole terminates as soon as the in-flight iterations finish.
165+
156166
BREAK statement: The language provides a statement form `BREAK(n)` that terminates enclosing loops. When executed inside a loop body (either a `WHILE` or `FOR` loop), `BREAK(n)` breaks out of the innermost `n` loops and resumes execution at the statement following those loops. The argument `n` is evaluated as an integer at runtime and must be strictly positive. If `n 0` the interpreter raises a runtime error. If `n` is greater than the number of currently-enclosing loops (that is, the statement would escape all surrounding loops), the interpreter raises a runtime error rather than silently terminating the program. Using `BREAK` outside of any loop context similarly results in an error. The exact error type and reporting information are implementation-defined but should be recorded in the state log to make replay and debugging deterministic.
157167
158168
CONTINUE statement: The language provides a statement form `CONTINUE()` that, when executed inside a loop body (either a `WHILE` or `FOR` loop), immediately proceeds to the next iteration of the innermost enclosing loop, skipping any remaining statements in the current iteration. If the current iteration is the final one (that is, no further iterations would occur), `CONTINUE()` has the same effect as executing `BREAK(1)` and thus exits the innermost loop. Using `CONTINUE()` outside of any loop context is a runtime error. Implementations should record the use of `CONTINUE` in the state log so that replay and tracebacks remain deterministic.
@@ -440,10 +450,7 @@
440450
- `ISFLT(SYMBOL: name):INT` — 1 if `name` is bound and has type `FLT`, otherwise 0.
441451
442452
### Rounding
443-
- `ROUND(FLT: float, STR: mode="floor", INT: ndigits=0):FLT` — Round `float` to `ndigits` places right of the radix point (binary places; `ndigits` may be negative). Modes are:
444-
445453
- `ROUND(FLT: float, STR: mode="floor", INT: ndigits=0):FLT` — Round `float` to `ndigits` places right of the radix point (binary places; `ndigits` may be negative). When exactly two arguments are supplied and the second is an `INT`, it is treated as `ndigits` with the mode defaulting to `"floor"`. Modes are:
446-
447454
- `"floor"` — round toward $-\infty$
448455
- `"ceiling"` or `"ceil"` — round toward $+\infty$
449456
- `"zero"` — round toward zero
@@ -499,7 +506,8 @@
499506
- `IF(condition){ block }` (optional `ELSEIF(condition){ block }` ... `ELSE{ block }`)
500507
- `WHILE(condition){ block }`
501508
- `FOR(counter, INT: target){ block }` ; `counter` initialized to 0, loop until counter >= target
502-
`FUNC name(T1:arg1, T2:arg2, ..., TN:argN):R{ block }` ; typed function definition with return type R (`INT`, `STR`, or `TNS`); optional defaults use `Tk:arg=expr` and must appear only after all positional parameters. Functions with return type `TNS` must explicitly execute `RETURN(value)`; there is no implicit default tensor value.
509+
- `PARFOR(counter, INT: target){ block }` ; concurrently execute `target` iterations with `counter` bound to `1..T`. Iteration bodies run in parallel (threaded) and may race on shared mutable identifiers. `CONTINUE()` ends the current iteration only; `BREAK(n)` terminates the entire `PARFOR` (prevents starting further iterations, waits for in-flight iterations to finish, then propagates the `BreakSignal`). Runtime errors raised inside iterations are collected and the first such error is re-raised after all iterations join.
510+
- `FUNC name(T1:arg1, T2:arg2, ..., TN:argN):R{ block }` ; typed function definition with return type R (`INT`, `STR`, or `TNS`); optional defaults use `Tk:arg=expr` and must appear only after all positional parameters. Functions with return type `TNS` must explicitly execute `RETURN(value)`; there is no implicit default tensor value.
503511
- `RETURN(ANY: a)` ; return from function with value `a`
504512
- `POP(SYMBOL: x)` — Convenience statement combining `RETURN` and `DEL`: when executed inside a function body it retrieves the current value of the identifier `x`, deletes the binding `x` from the environment (so subsequent references are an error), and returns the retrieved value to the caller. Using `POP` outside of a function is a runtime error.
505513
- `BREAK(INT: n)` ; break out of the innermost `n` enclosing loops; raises a runtime error if `n` ≤ 0 or if `n` is greater than the current loop nesting depth

asm-lang.exe

5.33 KB
Binary file not shown.

asm-lang.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def _output_sink(text: str) -> None:
123123
is_block_start = False
124124
if not buffer:
125125
uc = stripped.upper()
126-
if uc.startswith("FUNC") or uc.startswith("IF") or uc.startswith("WHILE") or uc.startswith("FOR"):
126+
if uc.startswith("FUNC") or uc.startswith("IF") or uc.startswith("WHILE") or uc.startswith("FOR") or uc.startswith("PARFOR"):
127127
is_block_start = True
128128
if stripped.endswith("{"):
129129
is_block_start = True

0 commit comments

Comments
 (0)