aboutsummaryrefslogtreecommitdiff
path: root/AGENTS
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-18 08:07:50 +0000
committer_ov4 <ov4@ov4.org>2026-10-18 08:07:50 +0000
commit345e3d419eafb0e234aecb4a33f37efe2afbbf53 (patch)
tree9330322103f26f15c6df91cbbd62bf5a1f6e72da /AGENTS
parent927e3fc0384c941f9ad313a28768660c3cdb1777 (diff)
feat(classes): add copy constructors and statement-scoped temporaries
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'AGENTS')
-rw-r--r--AGENTS/CONVENTIONS.md2
-rw-r--r--AGENTS/PITFALLS.md4
-rw-r--r--AGENTS/SUBSYSTEMS.md5
3 files changed, 7 insertions, 4 deletions
diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md
index fa9f12a..b8ca3e9 100644
--- a/AGENTS/CONVENTIONS.md
+++ b/AGENTS/CONVENTIONS.md
@@ -162,7 +162,7 @@ builtin result types. Returns may be any supported function result, including
non-BOOLEAN comparisons/logic. emitCoercedExpr rejects implicit STRING to BOOLEAN;
CASE separately requires BOOLEAN comparisons. Operators use shared argument
marshalling and exception-aware calls. Member lvalues keep their original address;
-rvalues are materialized and registered for the existing function-scoped cleanup.
+rvalues are materialized with Alive tracking and destroyed at statement end.
**Parameter modes are sticky and BYREF is procedure-only (guide ยง8.3).** In
`(BYREF a : T, b : T)` the `b` is BYREF too; unannotated parameters default to
diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md
index 820fa55..4c72a4f 100644
--- a/AGENTS/PITFALLS.md
+++ b/AGENTS/PITFALLS.md
@@ -124,7 +124,7 @@ test programs.
Explicit calls do not recurse into fields or affect Alive tracking. Keyword DELETE
validates an active allocation start before destroying the object and its fields,
then frees memory and leaves aliases dangling; FREE skips all destruction.
- DECLARE storage and shallow BYVAL copies are destroyed in reverse declaration order
+ DECLARE storage and BYVAL copies are destroyed in reverse declaration order
at normal function exit or when unwinding leaves the frame. Arrays reverse their
flat element order. Repeated DECLARE destroys its previous incarnation first.
Lifetimes are function-scoped, even for declarations inside blocks. NEW rebinding
@@ -178,3 +178,5 @@ Linux.
WHILE accepts both the standard header without DO and the older WHILE DO form.
- **Literal escapes.** C++17 escapes are decoded by the lexer. Unicode escapes encode UTF-8 in strings; CHAR Unicode escapes must be ASCII. Built-in STRING remains NUL-terminated: `"a\0b"` is observed as `"a"`.
+
+- **Copy limits.** Classes may define a same-class BYREF copy constructor. Classes without one, whole TYPE records containing class fields, and BYVAL arrays still copy bits; owning handles inside these aggregate copies need explicit care. Class rvalues transfer ownership when consumed; discarded results and temporary receivers are destroyed at statement end.
diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md
index be20bc3..427fc45 100644
--- a/AGENTS/SUBSYSTEMS.md
+++ b/AGENTS/SUBSYSTEMS.md
@@ -134,8 +134,7 @@ DELETE method calls remain ordinary calls without field recursion. Keyword DELET
resolves a class lvalue, validates its allocation start through MemoryHandler before
any destruction, destroys it, then releases it through FREE; aliases remain dangling.
Stack lifetimes use a per-function `StackObjects` list saved/restored around function
-emission. DECLARE and shallow BYVAL copies share registration (the copy point is
-marked), including arrays and records with class fields. Each record retains the
+emission. DECLARE and BYVAL copies share ownership registration, including arrays and records with class fields. Each record retains the
original address, an entry-initialized Alive flag and, for arrays, a runtime element
count in an entry slot. Array buffer addresses also live in entry slots so deferred
cleanup never references branch-local bound SSA values. Repeated DECLARE destroys
@@ -195,3 +194,5 @@ nothing is declared or emitted eagerly. Helper bodies are built with the *shared
Builder (RuntimeCheck emits through the same one), saving/restoring the insert block.
**Explicit memory** (`MemoryHandler`): lazily emits internal allocation/find/release/resize helpers and a linked list of live allocation start addresses. Explicit MALLOC/REALLOC and keyword NEW allocations enter the list; STRING/ARRAY internals retain their existing ownership. `emitValidate` always calls the find helper, including for null, so keyword DELETE validates before running destructors. FREE validates non-null addresses, unlinks and frees the tracking node, releases the block and returns the original address. Zero-byte allocation returns null. REALLOC validates non-null addresses before its zero-size release path; null behaves as MALLOC. Positive-size resizing updates the node only after success, leaving the old block and record intact on failure. Node allocation precedes the user allocation; if the latter fails, its node is freed before the diagnostic and anonymous throw. Helpers use RuntimeCheck and ExceptionHandler, including source-line arguments and per-function unwind preparation. Sizes accept INTEGER and C integers and convert to native size_t. Address reuse can make stale aliases indistinguishable from current allocations; dereferences are not checked against this list.
+
+**Class copies and temporaries.** Callers construct BYVAL class arguments with a same-class BYREF OVERLOAD NEW; the callee's RegisterCopy hook takes ownership. emitOwnedValue constructs lvalue copies and keeps pending arguments Alive until marshalling succeeds. RETURN copies lvalues and transfers rvalues. StackObject::Temporary uses statement cleanup and deferred temporary-only cleanup before local handlers, while ordinary objects remain function-scoped. Function-result method receivers are materialized by the same path as operator receivers.