aboutsummaryrefslogtreecommitdiff
path: root/AGENTS
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-27 13:30:54 +0000
committer_ov4 <ov4@ov4.org>2026-10-27 13:30:54 +0000
commit24f410430b33aaf1f288b83ea37e18fa959e9d3e (patch)
tree1f10b4ad2fae28a54064be270de70454343a4d64 /AGENTS
parent0dd0b0908300eee08a06ee51d9eb48b85fd97d74 (diff)
docs(memory): describe standard-library allocation and explicit imports
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'AGENTS')
-rw-r--r--AGENTS/ARCH/LAYOUT.md2
-rw-r--r--AGENTS/CONVENTIONS/CALLS.md16
-rw-r--r--AGENTS/CONVENTIONS/EXCEPTIONS_AND_UNITS.md6
-rw-r--r--AGENTS/CONVENTIONS/STRINGS.md2
-rw-r--r--AGENTS/EXTENDING.md4
-rw-r--r--AGENTS/PITFALLS/modules-and-stdlib.md8
-rw-r--r--AGENTS/SUBSYSTEMS.md4
-rw-r--r--AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md5
-rw-r--r--AGENTS/SUBSYSTEMS/MEMORY.md40
-rw-r--r--AGENTS/SUBSYSTEMS/STDLIB.md13
-rw-r--r--AGENTS/TESTING.md2
11 files changed, 65 insertions, 37 deletions
diff --git a/AGENTS/ARCH/LAYOUT.md b/AGENTS/ARCH/LAYOUT.md
index dc8696e..c2cfee2 100644
--- a/AGENTS/ARCH/LAYOUT.md
+++ b/AGENTS/ARCH/LAYOUT.md
@@ -23,7 +23,7 @@
| `lib/CodeGen/Designator.cc`, `TypeCheckGen.cc` | TYPE pre-pass, member lookup/calls and lvalue access; type admission and user-kind binary operators |
| `lib/CodeGen/CTypeGen.cc` | CodeGen methods for native C scalar conversions, casts, arithmetic and input/output |
| `lib/CodeGen/NativeTypeSystem.cc` | Builtin registration, native C type imports/aliases and scalar promotion |
-| `lib/CodeGen/MemoryHandler.cc` | Explicit raw memory allocation, resizing and release with a live-address tracking list |
+| `lib/CodeGen/MemoryGen.cc` | Keyword NEW/DELETE calls to visible EXTERN helpers in memory.cps; memory.cc owns allocation tracking |
| `lib/CodeGen/FileHandler.cc`, `FileRuntimeIO.cc` | File runtime setup/lookup/open and call entry points; read/write/close/EOF helper bodies |
| `lib/CodeGen/ArrayHandler.cc`, `ArrayParameters.cc`, `ArrayOutput.cc` | Array allocation/indexing, parameter binding/arguments and whole/subarray output |
| `include/cps/CABI.h`, `lib/CodeGen/CABI/ClangABI.cc`, `lib/CodeGen/CABI/Lowering.cc` | EXTERN C ABI: the ABI description, the only file that includes clang CodeGen headers, and the generic lowering of signatures, arguments and returns |
diff --git a/AGENTS/CONVENTIONS/CALLS.md b/AGENTS/CONVENTIONS/CALLS.md
index 3fc2daa..55b3647 100644
--- a/AGENTS/CONVENTIONS/CALLS.md
+++ b/AGENTS/CONVENTIONS/CALLS.md
@@ -32,9 +32,10 @@ bridge C void* and nominal pseudocode pointer types.
An expression's expected result type filters overloads when present. Overload sets,
visibility filtering and exact selection:
[SUBSYSTEMS/FUNCTIONS.md](../SUBSYSTEMS/FUNCTIONS.md#signatures-and-call-resolution).
-- In all cases, `emitPrototype` rejects names that collide with runtime/libc symbols
- (`isReservedRuntimeName`), builtins, or enum values. Signatures retain the first
- declaration spelling for LLVM lookup, independently of call-site casing.
+- `emitPrototype` rejects builtin and enum names. Ordinary non-EXTERN, non-OVERLOAD
+ definitions also reject runtime/libc names (`isReservedRuntimeName`); OVERLOAD
+ definitions have signature-mangled symbols and cannot replace libc symbols.
+ Signatures retain the first declaration spelling for LLVM lookup, independently of call-site casing.
- Methods use `Class.Method` names and a hidden leading receiver address; their
FuncSig parameters contain only explicit source parameters.
@@ -52,11 +53,12 @@ callback CodeGen injects into FunctionGen). BYVAL arrays copy their buffer at ca
entry and clone STRING-bearing elements; BYREF binds the caller's buffer.
**Builtins are plain identifiers backed by one table.** Builtins
-(EOF/MALLOC/FREE/REALLOC) parse as ordinary calls — no lexer/parser support, and the
+(EOF/INT) parse as ordinary calls — no lexer/parser support, and the
names are not reserved words. The inline constexpr `Builtins` table in the internal
`lib/CodeGen/Builtins.h` ({Name, Arity, ReturnTypeName}) is the single source of
truth: `emitCall` checks arity against it before dispatching to the per-builtin emit
branches (still an if-chain, ahead of the user-function fallback), and
-`getExprTypeInfo` reads return types from it. EOF and the memory builtins consume the
-call source line for runtime diagnostics; they touch mutable runtime state and can
-throw.
+`getExprTypeInfo` reads return types from it. EOF and INT consume the call source
+line for runtime diagnostics and can throw.
+MALLOC/REALLOC/FREE are ordinary OVERLOAD functions in memory.cps, with no builtin
+dispatch or type rules in the compiler.
diff --git a/AGENTS/CONVENTIONS/EXCEPTIONS_AND_UNITS.md b/AGENTS/CONVENTIONS/EXCEPTIONS_AND_UNITS.md
index deed7ec..8ee97ec 100644
--- a/AGENTS/CONVENTIONS/EXCEPTIONS_AND_UNITS.md
+++ b/AGENTS/CONVENTIONS/EXCEPTIONS_AND_UNITS.md
@@ -41,8 +41,10 @@ it only on non-library to library calls. Runtime helper line arguments use
RuntimeCheck::lineValue too. Compiler diagnostics retain the owning file location.
**Default standard library.** The driver extracts embedded std.cps, its imported units
-and matching objects to a temporary directory that survives linking/execution. User
+and matching objects to a content-keyed cache (or temporary fallback) that survives
+linking/execution. User
units implicitly import std.cps; normal transitive visibility applies. -no-std
-suppresses all default library inputs and objects. Explicit libraries retain the
+suppresses all default library inputs and objects. std.cps imports string.cps and
+memory.cps; keyword NEW/DELETE require the latter even with -no-std. Explicit libraries retain the
ordinary INCLUDE/command-line rules. Source files and objects are embedded by a
build-time Perl generator. Saved -S output remains IR only.
diff --git a/AGENTS/CONVENTIONS/STRINGS.md b/AGENTS/CONVENTIONS/STRINGS.md
index 9bb81cf..d07c217 100644
--- a/AGENTS/CONVENTIONS/STRINGS.md
+++ b/AGENTS/CONVENTIONS/STRINGS.md
@@ -26,5 +26,5 @@ handles. Records and BYVAL arrays containing STRING recursively copy their
string-bearing fields/elements; RETURN and temporary cleanup preserve ownership.
C_STRING casts borrow a STRING buffer or construct an owning STRING copy in the other
direction. FileHandler owns copied open-file names and frees them on close; READFILE
-buffers are copied into STRING and released. Explicit MemoryHandler allocations remain
+buffers are copied into STRING and released. Explicit memory-library allocations remain
separate from these internal objects.
diff --git a/AGENTS/EXTENDING.md b/AGENTS/EXTENDING.md
index 5728ac5..358e80e 100644
--- a/AGENTS/EXTENDING.md
+++ b/AGENTS/EXTENDING.md
@@ -23,7 +23,7 @@ already terminated the block.
`Builtins` table in the internal `lib/CodeGen/Builtins.h` (single source of truth — arity checking in
`emitCall`, the return type in `getExprTypeInfo`, and the reject-user-redefinition check
all read it), then implement IR emission as a method on the fitting handler
-(for example MemoryHandler) or inline, and add the name intercept in `CodeGen::emitCall` — null-check every emitted argument before use, like the existing
+(for example FileHandler) or inline, and add the name intercept in `CodeGen::emitCall` — null-check every emitted argument before use, like the existing
branches do. `emitCall` lives in `ExpressionGen.cc`. Builtins are plain identifiers — nothing is needed in lexer/parser.
**New binary operator:** token (if multi-char) → one line in `BinopPrecedence`
@@ -80,4 +80,4 @@ also be registered in EmbeddedRunner for static-runtime JIT symbol lookup.
`setupExternalFunctions()` (re-declaring the same symbol in two handlers is fine — it
dedupes by name).
-**Standard-library functions:** define ordinary functions/operators in pseudocode-lib/string.cps with C ABI helpers in string.cc as needed. std.cps imports all public library units. CMake rebuilds and embeds source/object changes; do not add string functions to Builtins.h. Ordinary string literals need STRING.NEW(C_STRING); the compiler bridges OUTPUT/casts/files through C_STR(), INPUT through READ_INPUT(), and READFILE through assignment from C_STRING.
+**Standard-library functions:** define ordinary functions/operators in the appropriate pseudocode-lib/*.cps unit with C ABI helpers in the matching .cc as needed. std.cps imports all public library units. CMake rebuilds and embeds source/object changes; do not add standard-library functions to Builtins.h. Memory allocation functions live in memory.cps/memory.cc; only keyword NEW/DELETE need the MemoryGen bridge. Ordinary string literals need STRING.NEW(C_STRING); the compiler bridges OUTPUT/casts/files through C_STR(), INPUT through READ_INPUT(), and READFILE through assignment from C_STRING.
diff --git a/AGENTS/PITFALLS/modules-and-stdlib.md b/AGENTS/PITFALLS/modules-and-stdlib.md
index 4f6c446..5394d78 100644
--- a/AGENTS/PITFALLS/modules-and-stdlib.md
+++ b/AGENTS/PITFALLS/modules-and-stdlib.md
@@ -13,11 +13,15 @@ Part of the [pitfalls index](../PITFALLS.md).
- GLOBAL accepts only the five primitive scalar types and literal initializers;
arrays, user types and computed initializers are rejected.
- Own top-level constants remain positional, imported constants do not.
-- **Default standard library.** std.cps and its imported STRING library are embedded
+- **Default standard library.** std.cps and its imported STRING and memory libraries are embedded
and automatically linked.
- Use -no-std before explicitly supplying a replacement STRING class/library;
otherwise duplicate definitions fail.
- Ordinary literals require a visible STRING class with NEW(C_STRING).
- C_TYPE/INCLUDE/EXTERN syntax strings are parser metadata and do not construct
STRING.
- - -S emits IR only; manual linking needs string.o and the C++ runtime.
+ - Keyword NEW/DELETE and MALLOC/REALLOC/FREE require memory.cps; -no-std users
+ must explicitly import it. Ordinary constructor/destructor methods still work
+ without it.
+ - -S emits IR only; default-library manual linking needs string.o, memory.o and
+ the C++ runtime.
diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md
index d3a7dba..4753ab1 100644
--- a/AGENTS/SUBSYSTEMS.md
+++ b/AGENTS/SUBSYSTEMS.md
@@ -18,8 +18,8 @@ Deep-dives on the CodeGen helper subsystems, split by topic under `SUBSYSTEMS/`.
- [Runtime checks and exceptions](SUBSYSTEMS/RUNTIME_CHECKS_EXCEPTIONS.md):
`RuntimeCheck`, TRY/CATCH/THROW lowering, cleanup pads, EH runtime per platform.
- [Files](SUBSYSTEMS/FILES.md): `FileHandler` text-file runtime and open-file table.
-- [Explicit memory](SUBSYSTEMS/MEMORY.md): `MemoryHandler` allocation tracking,
- MALLOC/REALLOC/FREE.
+- [Explicit memory](SUBSYSTEMS/MEMORY.md): standard-library MALLOC/REALLOC/FREE,
+ allocation tracking and keyword NEW/DELETE bridging.
- [Standard library](SUBSYSTEMS/STDLIB.md): `pseudocode-lib/`, embedding, STRING class.
- [Templates](SUBSYSTEMS/TEMPLATES.md): template declarations, resolution, cloning,
instantiation, body emission.
diff --git a/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md b/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
index eb7f039..98693e5 100644
--- a/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
+++ b/AGENTS/SUBSYSTEMS/CLASS_LIFETIME.md
@@ -18,7 +18,7 @@ Part of the [subsystem notes](../SUBSYSTEMS.md). Builds on [classes](CLASSES.md)
class parameters; `symbolAddress` loads their current object address for all value,
lvalue, address-of, receiver and BYREF paths. Field aliases, this and BYREF
parameters bind addresses directly.
-- Assignment-only `NewExprAST` uses checked MemoryHandler allocation (at least one byte
+- Assignment-only `NewExprAST` uses checked memory-library allocation (at least one byte
for method-only classes), zero initialization and construction, then rebinds
reference slots or copies into other destinations.
- Ordinary assignment invokes an exact member OPERATOR<- when available, otherwise it
@@ -31,7 +31,8 @@ Part of the [subsystem notes](../SUBSYSTEMS.md). Builds on [classes](CLASSES.md)
ordinary DELETE method first, then fields in reverse declaration order. Explicit
DELETE method calls remain ordinary calls without field recursion.
- Keyword DELETE resolves a class lvalue, validates its allocation start through
- MemoryHandler before any destruction, destroys it, then releases it through FREE;
+ the memory-library validator before any destruction, destroys it, then releases it
+ through the same runtime as FREE;
aliases remain dangling.
- Stack lifetimes use a per-function `StackObjects` list saved/restored around function
emission. DECLARE and BYVAL copies share ownership registration, including arrays and
diff --git a/AGENTS/SUBSYSTEMS/MEMORY.md b/AGENTS/SUBSYSTEMS/MEMORY.md
index 8b0ccfc..40cfe9e 100644
--- a/AGENTS/SUBSYSTEMS/MEMORY.md
+++ b/AGENTS/SUBSYSTEMS/MEMORY.md
@@ -3,29 +3,39 @@
Part of the [subsystem notes](../SUBSYSTEMS.md). Related:
[class lifetime](CLASS_LIFETIME.md).
-**Explicit memory** (`MemoryHandler`): lazily emits internal allocation/find/release/
-resize helpers and a linked list of live allocation start addresses.
+**Explicit memory** lives in `pseudocode-lib/memory.cps` and `memory.cc`.
+MALLOC/REALLOC/FREE are ordinary OVERLOAD functions calling `_memory_impl_*`
+EXTERN "C" helpers. `lib/CodeGen/MemoryGen.cc` only bridges keyword NEW/DELETE to
+visible helper declarations, checking their signatures and using FunctionGen's
+C ABI lowering, library call-line hook and exception-aware calls.
## Tracking
-- Explicit MALLOC/REALLOC and keyword NEW allocations enter the list; STRING/ARRAY
- internals are not tracked here and keep their own ownership.
-- 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.
+- memory.cc owns a linked list of live allocation start addresses. Explicit
+ MALLOC/REALLOC and keyword NEW share it; STRING/ARRAY internals keep their own
+ ownership outside the list.
+- Errors print the existing reason with __cps_user_line and throw 0. The #LIB call
+ hook supplies the user line, including keyword NEW/DELETE helper calls.
+- Sizes accept INTEGER and every supported C integer (including _Bool) through
+ ordinary overloads. Wrappers explicitly cast to unsigned long long; C++ converts
+ that value to native size_t, preserving the old integer conversion behavior.
+- std.cps imports memory.cps. With -no-std, explicitly import and supply memory.cps,
+ including for keyword NEW/DELETE. Missing visible helpers are compiler errors.
## Operations
-- `emitValidate` always calls the find helper, including for null, so keyword DELETE
+- `_memory_impl_validate` always searches, 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.
+- FREE validates non-null addresses, unlinks the tracking node, releases the block
+ and node, and returns the original address. Null is returned without searching.
- 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.
+- 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.
+- Keyword NEW reserves at least one byte for method-only classes. NEW constructs
+ objects and DELETE destroys them; FREE/REALLOC never invoke destruction.
## Limitation
diff --git a/AGENTS/SUBSYSTEMS/STDLIB.md b/AGENTS/SUBSYSTEMS/STDLIB.md
index d43899f..6c7b14c 100644
--- a/AGENTS/SUBSYSTEMS/STDLIB.md
+++ b/AGENTS/SUBSYSTEMS/STDLIB.md
@@ -15,10 +15,19 @@ import rules: [CONVENTIONS/EXCEPTIONS_AND_UNITS.md](../CONVENTIONS/EXCEPTIONS_AN
reused when identical, otherwise published by atomic rename; the cache is never deleted, so
a killed run leaks nothing. Only if no cache directory is usable does it fall back to a
temporary `cpsc-std` directory removed on exit. The driver
- implicitly imports std.cps unless -no-std is set. std.cps imports string.cps.
+ implicitly imports std.cps unless -no-std is set. std.cps imports string.cps and memory.cps.
- Source/object resources are embedded in installed/released cpsc, which needs no
separate library directory; manually linking saved IR still requires the matching
- string.o and the C++ runtime.
+ string.o, memory.o and the C++ runtime for default-library builds.
+
+## Explicit memory
+
+- memory.cps defines ordinary OVERLOAD MALLOC/REALLOC/FREE wrappers over memory.cc
+ C ABI helpers. Sizes support INTEGER and all supported C integers.
+- Keyword NEW/DELETE call visible EXTERN helpers through MemoryGen and FunctionGen;
+ no compiler allocation list or memory builtin dispatch remains. With -no-std,
+ explicitly import memory.cps, including when only keyword NEW/DELETE is needed.
+- Runtime errors print __cps_user_line and throw 0. See [MEMORY.md](MEMORY.md).
## STRING and I/O bridging
diff --git a/AGENTS/TESTING.md b/AGENTS/TESTING.md
index f3628d2..c00843c 100644
--- a/AGENTS/TESTING.md
+++ b/AGENTS/TESTING.md
@@ -24,4 +24,4 @@ Perl generators use Random.pm's SHA-256 sequence with explicit big-endian extrac
Before committing a test change, build the affected references and run the affected CTest cases. Compiler defects may fail: inspect retained diagnostics and document the failure accurately. Workflow changes follow the commit checks in [ARCH/NIGHTLY.md](ARCH/NIGHTLY.md). No compiler implementation changes belong in a tests-only task.
-The explicit STRING library integration fixture lives in `tests/library/exp-string`. CMake copies it to the build tree as `test-cases/i/exp-string`, where relative source paths reach the built library and its object file. It passes -no-std to avoid loading a second library copy. Manifests may supply compiler_args for every native/IR/runner compiler invocation. It uses the ordinary native/runner harness and appears as `i/exp-string` in CTest.
+The explicit library integration fixtures live in `tests/library/exp-string` and `tests/library/exp-memory`. CMake copies them to the build tree under `test-cases/i/`, where relative source paths reach the built libraries and their objects. Both pass -no-std to avoid loading a second library copy. exp-string imports std.cps, including memory.cps for its keyword NEW/DELETE; exp-memory imports only memory.cps and checks C integer sizes and shared tracking with NEW/DELETE. Manifests may supply compiler_args for every native/IR/runner compiler invocation. Both use the ordinary native/runner harness and appear as `i/exp-string` and `i/exp-memory` in CTest.