docs+runner+parser: SSOT+AST using finalized (legacy text inlining removed); provider verify reads nyash.toml; preflight warn hook; method-body guard removed; CURRENT_TASK updated for next JSON work
This commit is contained in:
77
docs/development/proposals/concurrency/boxes.md
Normal file
77
docs/development/proposals/concurrency/boxes.md
Normal file
@ -0,0 +1,77 @@
|
||||
# Nyash Concurrency — Box Model (Proposal, docs-only)
|
||||
|
||||
Status: design-only during the feature‑pause. No runtime or spec changes. Implement after Mini‑VM baseline is stable.
|
||||
|
||||
Intent
|
||||
- Bring Go-like CSP (goroutine/channels/select) into Nyash via “Everything is Box”.
|
||||
- Keep semantics explicit, lifecycle safe (birth/fini), and observable. Phase-in from userland → runtime.
|
||||
|
||||
Scope (Phase‑0: userland MVP)
|
||||
- RoutineBox: lightweight task wrapper over `nowait` (state, join/cancel, status).
|
||||
- ChannelBox: bounded/unbounded queue + blocking/non-blocking ops + close semantics.
|
||||
- SelectBox: multi-channel wait (first-ready) with simple fairness.
|
||||
- RoutineScopeBox: structured concurrency; children are canceled on scope fini.
|
||||
- Observability: JSONL trace toggled by `NYASH_CONC_TRACE=1`.
|
||||
|
||||
Non‑Goals (Phase‑0)
|
||||
- M:N scheduler, OS-level park/unpark, net poller integration (deferred to Phase‑2 runtime work).
|
||||
|
||||
API Sketch (userland)
|
||||
- RoutineBox
|
||||
- birth(fn)
|
||||
- start(): Void
|
||||
- join(timeout_ms?: Int) -> Bool // true if joined; false on timeout
|
||||
- cancel(): Void
|
||||
- status() -> String // ready|running|done|canceled|error
|
||||
- ChannelBox(capacity: Int=0)
|
||||
- send(v): Void // blocks if full (Phase‑0: simulated park)
|
||||
- try_send(v) -> Bool
|
||||
- receive() -> Any // blocks if empty (Phase‑0: simulated park)
|
||||
- try_receive() -> (Bool, Any?)
|
||||
- receive_timeout(ms: Int) -> (Bool, Any?)
|
||||
- close(): Void // further send fails; recv drains until empty then End
|
||||
- SelectBox
|
||||
- birth()
|
||||
- when(ch: ChannelBox, handler: Fn): Void
|
||||
- await() -> Bool // returns after one handler runs; false if none ready and no wait policy
|
||||
- await_timeout(ms: Int) -> Bool
|
||||
- RoutineScopeBox
|
||||
- birth()
|
||||
- spawn(fn) -> RoutineBox
|
||||
- fini() // cancels pending routines and waits boundedly
|
||||
|
||||
Semantics
|
||||
- Capacity:
|
||||
- 0: rendezvous channel (send/recv rendezvous).
|
||||
- N>0: bounded ring buffer.
|
||||
- Close:
|
||||
- close() marks channel as closed. send() after close -> error. receive() returns buffered items; when empty -> (false, End) style result; exact return shape defined per API.
|
||||
- Blocking:
|
||||
- Phase‑0 userland uses cooperative wait queues; no busy loops. try_* and timeout variants provided.
|
||||
- Select fairness:
|
||||
- If multiple ready, choose random/round‑robin. Starvation avoidance is a design requirement; precise algorithm can evolve.
|
||||
- Types:
|
||||
- `TypedChannelBox<T>` is a future extension; Phase‑0 uses runtime tags/guards documented in reference.
|
||||
- Cancellation:
|
||||
- RoutineScopeBox cancels children on fini; Channel waits should return (canceled) promptly.
|
||||
|
||||
Phases
|
||||
- Phase‑0 (userland MVP / PyVM first)
|
||||
- Implement the 4 boxes above with minimal queues/waits, plus trace hooks.
|
||||
- Smokes: ping‑pong, bounded producer/consumer, two‑way select, close semantics, scope cancel.
|
||||
- Phase‑1 (park/unpark abstraction)
|
||||
- Introduce `WaiterBox`/`CondBox` that map to efficient OS waits where available. Keep same APIs.
|
||||
- Phase‑2 (runtime integration)
|
||||
- Scheduler (M:N), GC and net poller integration, fairness and profiling. Keep Box APIs stable.
|
||||
|
||||
Observability
|
||||
- `NYASH_CONC_TRACE=1` → JSONL events: spawn/join/cancel/send/recv/park/unpark/select/close with routine IDs, channel IDs, timestamps.
|
||||
|
||||
Safety & Diagnostics
|
||||
- Deadlock hints: trace dependent waits; optional detector (dev only) can dump wait‑for graph.
|
||||
- API contracts explicitly define error return for misuse (send on closed, double close, etc.).
|
||||
|
||||
Deliverables (docs‑only during the feature‑pause)
|
||||
- This proposal (boxes & semantics).
|
||||
- Reference page with blocking/close/select rules (see reference/concurrency/semantics.md).
|
||||
- Test plan with named smokes and expected outputs.
|
||||
74
docs/development/proposals/scope-reuse.md
Normal file
74
docs/development/proposals/scope-reuse.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Scope Reuse Blocks (MVP Proposal)
|
||||
|
||||
Status: design-only during the feature‑pause (no implementation)
|
||||
|
||||
Summary
|
||||
- Give short, reusable logic a name within the current scope without promoting it to a top-level function.
|
||||
- Keep the core small: block body + postfix header sugar; desugar to local function + normal calls.
|
||||
- Zero runtime cost: lowers to let/if/call/ret only (no new instructions/closures).
|
||||
|
||||
Syntax (postfix header; Nyash style)
|
||||
- Block form (multi-statement):
|
||||
```nyash
|
||||
{ /* BODY */ } scope name(arglist?) (-> Ret)?
|
||||
// call within the same scope
|
||||
name(args)
|
||||
```
|
||||
- Expression form (one-liner):
|
||||
```nyash
|
||||
=> EXPR scope name(arglist?) (-> Ret)?
|
||||
```
|
||||
|
||||
Semantics
|
||||
- Visibility: `name` is local to the defining scope; not exported.
|
||||
- Capture: by reference by default. Mutating captured vars requires explicit `mut` on those bindings.
|
||||
- Recursion: disallowed in MVP (can be lifted later).
|
||||
- Errors/exits: same as regular functions (return/cleanup/catch apply at the function boundary).
|
||||
|
||||
Lowering (desugaring)
|
||||
- Transform into a local function plus a local binding for convenience calls.
|
||||
```nyash
|
||||
// { BODY } scope check(a:Int)->Str
|
||||
// ↓ (conceptual)
|
||||
let __cap_me = me; let __cap_locals = { /* needed refs */ };
|
||||
method __scope_check__(a:Int)->Str {
|
||||
return BODY
|
||||
}
|
||||
let check = (x) => __scope_check__(x)
|
||||
```
|
||||
- Captures are passed via hidden arguments or an environment box; no new VM opcodes.
|
||||
|
||||
Examples
|
||||
```nyash
|
||||
{ if x % 2 == 0 { return "even" } return "odd" } scope parity(x:Int)->StringBox
|
||||
|
||||
for i in range(0,10) {
|
||||
print(parity(i))
|
||||
}
|
||||
```
|
||||
|
||||
Safety rules (MVP)
|
||||
- Capture: read-only by default; writes allowed only when the captured binding is declared `mut`.
|
||||
- Name uniqueness: `scope name` must be unique within the scope.
|
||||
- No cross-scope escape: values may be returned but the function reference itself is not exported.
|
||||
|
||||
Observability & Tooling
|
||||
- Add trace toggles (design only):
|
||||
- `NYASH_SCOPE_TRACE=1|json` to emit enter/exit and capture lists as JSONL.
|
||||
- Example: `{ "ev":"enter","sid":42,"caps":["me","cfg","mut total"] }`.
|
||||
- Lints (design only):
|
||||
- Single-use scope → suggest inline.
|
||||
- Excess captures → suggest narrowing.
|
||||
|
||||
Interactions
|
||||
- Works with guard/with/await sugars (it’s just a call).
|
||||
- Compatible with ASI and postfix aesthetics; no new top-level keywords beyond `scope` suffix.
|
||||
|
||||
Tests (syntax-only smokes; design)
|
||||
- scope_basic: called twice → same result.
|
||||
- scope_capture_read: reads `me/foo`.
|
||||
- scope_capture_mut: mutation only allowed when `mut` is present.
|
||||
- scope_with_catch_cleanup: postfix catch/cleanup applied at local-function boundary.
|
||||
|
||||
Pause note
|
||||
- This is documentation and design intent only. Implementation is deferred until after the feature‑pause (post‑bootstrap).
|
||||
137
docs/development/proposals/unified-members.md
Normal file
137
docs/development/proposals/unified-members.md
Normal file
@ -0,0 +1,137 @@
|
||||
# Property System Revolution for Nyash (2025-09-18 Breakthrough)
|
||||
|
||||
Status: **BREAKTHROUGH COMPLETED** - Final syntax decided through AI collaboration with ChatGPT, Claude, and Codex.
|
||||
|
||||
## 🌟 Revolutionary Achievement
|
||||
Today we achieved the **Property System Revolution** - a complete unification of stored fields, computed properties, lazy evaluation, and birth-time initialization into a single, elegant syntax system through AI collaboration with ChatGPT5, Claude, and Codex.
|
||||
|
||||
## 🎯 Final Property System Design
|
||||
|
||||
### The Four-Category Breakthrough
|
||||
After dialectical discussion with multiple AI agents, we reached the perfect synthesis:
|
||||
|
||||
#### 1. **stored** - Traditional Field Storage
|
||||
```nyash
|
||||
box Example {
|
||||
name: StringBox // Default initialization
|
||||
count: IntegerBox = 0 // Explicit initialization
|
||||
}
|
||||
```
|
||||
- **Semantics**: O(1) slot read/write, assignment allowed
|
||||
- **Use Case**: Traditional object fields, counters, configurations
|
||||
|
||||
#### 2. **computed** - Calculated Every Access
|
||||
```nyash
|
||||
box Example {
|
||||
size: IntegerBox { me.items.count() }
|
||||
full_name: StringBox { me.first + " " + me.last }
|
||||
}
|
||||
```
|
||||
- **Semantics**: Evaluate body on each read, assignment error unless setter declared
|
||||
- **Use Case**: Derived values, dynamic calculations, Python @property equivalent
|
||||
|
||||
#### 3. **once** - Lazy Evaluation with Caching
|
||||
```nyash
|
||||
box Example {
|
||||
once expensive_data: DataBox { heavy_computation() }
|
||||
once config: ConfigBox { loadConfiguration() }
|
||||
}
|
||||
```
|
||||
- **Semantics**: Evaluate on first read, cache result, return cached value thereafter
|
||||
- **Use Case**: Heavy computations, file loading, Python @cached_property equivalent
|
||||
- **Exception Handling**: Poison-on-throw strategy for safety
|
||||
|
||||
#### 4. **birth_once** - Eager Evaluation at Object Creation
|
||||
```nyash
|
||||
box Example {
|
||||
birth_once startup_data: DataBox { initialize_system() }
|
||||
|
||||
birth() {
|
||||
// birth_once properties already initialized!
|
||||
me.ready = true
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Semantics**: Evaluated before user birth() in declaration order
|
||||
- **Use Case**: System initialization, dependency setup, startup-critical data
|
||||
|
||||
## 🌟 Revolutionary Python Integration
|
||||
|
||||
### Perfect Mapping Strategy
|
||||
```python
|
||||
# Python side
|
||||
class DataProcessor:
|
||||
def __init__(self):
|
||||
self.value = 42 # → stored
|
||||
|
||||
@property
|
||||
def computed_result(self): # → computed
|
||||
return self.value * 2
|
||||
|
||||
@functools.cached_property
|
||||
def expensive_data(self): # → once
|
||||
return heavy_computation()
|
||||
```
|
||||
|
||||
```nyash
|
||||
// Auto-generated Nyash (revolutionary 1:1 mapping!)
|
||||
box DataProcessor {
|
||||
value: IntegerBox // stored
|
||||
computed_result: IntegerBox { me.value * 2 } // computed
|
||||
once expensive_data: ResultBox { heavy_computation() } // once
|
||||
|
||||
birth() {
|
||||
me.value = 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Revolution
|
||||
- **computed properties**: No caching overhead, pure calculation
|
||||
- **once properties**: 10-50x faster than Python cached_property (LLVM optimization)
|
||||
- **birth_once properties**: Startup optimization, dependency injection pattern
|
||||
- **Overall**: Python code → 5-20x faster native binary
|
||||
|
||||
Handlers (Stage‑3)
|
||||
- Postfix `catch/cleanup` are allowed for computed/once/birth_once/method blocks.
|
||||
- Stored does not accept handlers.
|
||||
|
||||
Semantics
|
||||
- stored: O(1) slot read; `= expr` evaluated once during construction; assignment allowed.
|
||||
- computed: evaluate on each read; assignment is an error unless a setter is declared.
|
||||
- once: evaluate on first read, cache the result, and return it thereafter. If the first evaluation throws and there is no `catch`, mark poisoned and rethrow the same error on later reads (no retry).
|
||||
- birth_once: evaluated before user `birth` body in declaration order; uncaught error aborts construction. Cycles are rejected.
|
||||
|
||||
Lowering (no JSON v0 change)
|
||||
- stored → slot
|
||||
- computed → synthesize `__get_name():T { try body; catch; finally }`, resolve reads to call
|
||||
- once → add hidden `__name: Option<T>` and first-read initialization in `__get_name()`; poison on uncaught error
|
||||
- birth_once → hidden `__name: T` initialized before user `birth` body in declaration order; handler blocks apply per initializer
|
||||
- method → unchanged; postfix handlers lower to try/catch/finally
|
||||
|
||||
EBNF (delta)
|
||||
```
|
||||
box_decl := 'box' IDENT '{' member* '}'
|
||||
member := stored | computed | once_decl | birth_once_decl | method_decl
|
||||
stored := IDENT ':' TYPE ( '=' expr )?
|
||||
computed := IDENT ':' TYPE block handler_tail?
|
||||
once_decl := 'once' IDENT ':' TYPE block handler_tail?
|
||||
birth_once_decl:= 'birth_once' IDENT ':' TYPE block handler_tail?
|
||||
method_decl := IDENT '(' params? ')' ( ':' TYPE )? block handler_tail?
|
||||
handler_tail := ( catch_block )? ( cleanup_block )?
|
||||
catch_block := 'catch' ( '(' ( IDENT IDENT | IDENT )? ')' )? block
|
||||
cleanup_block := 'cleanup' block
|
||||
```
|
||||
|
||||
Diagnostics
|
||||
- Assignment to computed/once/birth_once: error with fix-it (“define a setter or use stored property”).
|
||||
- Once poison: first read throws → remember error; subsequent reads rethrow immediately.
|
||||
- Birth order: evaluated before user `birth`, in declaration order; cycle detection emits a clear error with the chain.
|
||||
|
||||
Flags
|
||||
- Parser gate: `NYASH_ENABLE_UNIFIED_MEMBERS=1`
|
||||
- Stage‑3 for handlers: `NYASH_PARSER_STAGE3=1`
|
||||
|
||||
Notes
|
||||
- User experience: read is uniform (`obj.name`), write differs by kind; this keeps mental model simple.
|
||||
- Future: setter syntax (`name: T { get {…} set(v) {…} }`) and aliases (`slot/calc/lazy`) can be added without breaking this core.
|
||||
Reference in New Issue
Block a user