CHANGE LOG ============================================================================================= 1.3.0 ===== language changes ---------------- * Removed `uses` clause from try blocks. - Try blocks now execute in the parent variable scope transparently. - all reads and writes operate on the parent ident directly. This eliminates the copy-in/copy-out machinery and aligns try/catch scope behavior (catch already shared parent scope). - `capturedVars` field removed from `tryBlockInfo` - `MODE_TRY` added to call modes - `captured_vars` parameter in `Call()` retained for future closure use - `C_Uses` token type retained in lexer/constants for future closure syntax * Format specifiers in string interpolation (`{varname:format}` and `{=expr:format}`) - `{varname:fmt}` : format a variable: `{n:04d}`, `{cost:.2f}`, `{n:08x}` - `{=expr:fmt}` : format an expression result: `{=1+2:04d}`, `{=255:08x}` - Format specs are Go `fmt.Sprintf` verbs without the leading `%` - Ternary expressions work in `{=...}`; - test coverage: za_tests/test_interpolation.za (17 tests) * `sort()` key-extractor option: `sort(list, map(.key `#.field`, .reverse true))` - Pre-computes keys using `processConditionString()` + `ev()` with existing `#`/`#.field`/`$idx` substitution from `->`/`?>` operators - Returns list in original type; eliminates decorate/sort/undecorate patterns - Fixed unclosed paren in sort help text - test coverage: za_tests/test_sort_key.za (8 tests) * added support for 'else if ' and 'return if [,expr[,...]]' - test coverage: za_tests/test_return_if.za and za_tests/test_else_if.za * Added `global` keyword for persistent variable declarations. - Declares variables into the main function space (mident), so they survive module loading and can be written via @ from any scope. - Syntax mirrors `var`: `global name[, name...] [size] type [= expr]` - test coverage: za_tests/test_global.za * `yield` / `emit` statements for async tasks (cooperative suspension + streaming). - `yield` parks the task until resumed; `yield v` publishes v on the task stream, then parks. `emit [v]` publishes without parking (nil heartbeat when omitted). Unbuffered rendezvous throughout: undrained producers wedge by design (drain or don't stream); see `resume`/`drain`. - Only legal inside async tasks (clean error elsewhere, including from nested user calls, which resolve task state through ctx). - test coverage: za_tests/test_yield.za * `unset` of an undeclared name is a silent noop (was: index panic). - The pre-existing `declared` check is now bounds-guarded first; the WITH statement keeps its loud `Variable 'x' does not exist` error, now reached instead of panicking on the same shape. * Async calls from plain scripts (no namespace decl) resolve worker functions: empty runtime namespace normalizes to main::, matching how definitions register. Previously `invalid function '::name'`. * ternary precedence changed to be C-like: `?:` (prec 13) now binds looser than `&&`/`||`/comparisons - `a && b ? x : y` now parses as `(a && b) ? x : y` (was `a && (b ? x : y)`, and the false-lhs short-circuit form could hard-error) - applies to both the interpretive dparse() path and the bytecode compiler (both read default_prectable); a single change in main.go - test coverage: za_tests/test_vm.za section 20 (8 new asserts) * First-class narrow integer widths: `int8`, `int16`, `int32`, `uint8`, `uint16`, `uint32` (existing `int`/`int64`/`uint64`/`float32` untouched). - `var`/`global` declarations with these scalar types and their typed slices (`var x []int32`, `global g []uint16`, ...). - `foreach`/`for` over `[]int8/16/32/64`, `[]uint8/16/32/64` typed slices. - arithmetic (`+ - * /`), comparisons (`== != < > <= >=`), `len()`, `append()`, `type()`/`kind()`, `is_number` all handle the widths. - new list converters: `list_int8/16/32`, `list_uint8/16/32/64` - new scalar converters: `as_int8/16/32`, `as_uint8/16/32/64` - typed function params/returns accept these types (`def f(x:int16)`, `def g(a:[]int32) -> []uint64`, defaults incl.); exact-type matching, no silent coercion. NB: `uint64` values are never coerced to `int`/`int64`/`bigi`. tooling changes --------------- * Added `-PP` evented profiling output. - Writes ANSI-free Speedscope JSON to `za-profile.json` after execution. - Uses existing call-chain/function and FFI timing boundaries; normal execution and the existing `-P` summary remain unchanged. * Cleaned `-z` parse timing output. - `-z` now reports project source files only, omitting native module/library paths. - `-zz` retains the full diagnostic output and module reporting behavior. * TAP 13 test output (`--tap` flag) - `--tap` emits test results in TAP 13 format instead of colored text - `--tap` without `-o` writes to stderr; with `-o file` writes to file - `ok`/`not ok` per assertion with expression text in the description (`group/name : expr`) - `#` diagnostic comments include file path, line number, function name, and module - `#` comments for section headers; no `1..N` plan line (avoids buffering) - `Bail out!` emitted on `ASSERT FAIL` exits - DOC statements suppressed in TAP mode to avoid corrupting the stream - `appendToTestReportRaw()` helper for plain-text (no sparkle/ANSI) output * VS Code extension: client-side regex diagnostics for escape/backslash patterns (removed), exponent regex fix, keyword exclusion fix * Added `-xx` bundling of the native libffi runtime. - With `za -x -xx`, the platform-native libffi library is embedded in the bundle: Windows `libffi-8.dll` (from `shared/win/`), Linux/BSD the system `libffi.so.8` (fallbacks `.so.7`/`.so` via LD_LIBRARY_PATH, ldconfig and known paths). - On execution the library unpacks beside the extracted script; libffi is loaded from the script's directory before any system path. - A `-xx` bundle therefore runs with no system/wine libffi installed. - Missing native libffi at build time prints a warning and continues (bundle still builds); libffi is MIT-licensed (`shared/win/LICENSE`). - test coverage: `za_tests/ffi/win/run_bundle_tests.sh` (Windows via the Windows suite runner, Linux standalone), packaging bundle_ffi_win.za / bundle_ffi_linux.za. * Fixed bundle execution on Windows: the embedded `za` is now extracted as `za.exe` (Windows requires the extension for CreateProcess), so `-x` bundles actually run on Windows. * Unix libffi discovery now prefers the executed script's directory first (`