aboutsummaryrefslogtreecommitdiff
path: root/AGENTS
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-17 05:30:57 +0000
committer_ov4 <ov4@ov4.org>2026-10-17 05:30:57 +0000
commit4dd85fd6ecd9a67e5c2b68380873e6e114714355 (patch)
treeb9dad1d0845f4c2ae7e6efed171fbee40ccd1f31 /AGENTS
parente782898e420c7f2abd83b97c160194d0e70598dd (diff)
feat(memory): add tracked MALLOC and FREE builtins
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'AGENTS')
-rw-r--r--AGENTS/ARCH.md1
-rw-r--r--AGENTS/CONVENTIONS.md16
-rw-r--r--AGENTS/EXTENDING.md5
-rw-r--r--AGENTS/SUBSYSTEMS.md4
4 files changed, 12 insertions, 14 deletions
diff --git a/AGENTS/ARCH.md b/AGENTS/ARCH.md
index 83a1923..edfa281 100644
--- a/AGENTS/ARCH.md
+++ b/AGENTS/ARCH.md
@@ -297,6 +297,7 @@ do not modify the real release for local verification.
| `lib/CodeGen/Designator.cc`, `TypeCheckGen.cc` | TYPE pre-pass 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 and release with a live-address tracking list |
| `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 |
| `lib/CodeGen/*Handler.cc`, `FunctionGen.cc`, `RuntimeCheck.cc`, `TypeSystem.cc` | Helpers owned by CodeGen (including exception emission) |
diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md
index bb1b836..75289da 100644
--- a/AGENTS/CONVENTIONS.md
+++ b/AGENTS/CONVENTIONS.md
@@ -89,12 +89,10 @@ remain unsupported.
**Strings are malloc'd and never freed — by design.** Every string-producing operation
(`&`, MID/LEFT/RIGHT/LCASE/UCASE, NUM_TO_STR, CHR, READFILE, CHAR/number→STRING
coercion) mallocs a fresh buffer; string literals and BOOLEAN→STRING coercion instead
-return pointers to shared module globals, so a STRING value may alias a global. `free`
-is never declared or called. Don't "fix" leaks piecemeal; it's a global design decision.
+return pointers to shared module globals, so a STRING value may alias a global. `MemoryHandler` declares `free` for explicit user memory only; it must never free internal STRING buffers. Don't "fix" leaks piecemeal; it's a global design decision.
Heap-string operations live in `StringHandler` (including `&` concatenation,
`emitConcat`), `StringConversionHandler` (NUM_TO_STR/STR_TO_NUM buffers) and
-`FileHandler` (READFILE line buffers — its `__cps_file_read` helper owns the project's
-only `realloc`); `CodeGen` also keeps its own `MallocFunc` for the char→STRING coercion
+`FileHandler` (READFILE line buffers — its `__cps_file_read` helper grows line buffers with `realloc`); `CodeGen` also keeps its own `MallocFunc` for the char→STRING coercion
and INPUT STRING buffers — declared in `SetupExternalFunctions`, never fetched with a
bare `getFunction("malloc")`.
@@ -159,15 +157,13 @@ The LLVM ABI flattens each rank-R array parameter into a data `ptr` plus
callback CodeGen injects into FunctionGen). BYVAL arrays are whole
malloc+memcpy copies at callee entry; BYREF binds the caller's buffer.
-**Builtins are plain identifiers backed by one table.** All 12 builtins
-(LENGTH/MID/RIGHT/LEFT/LCASE/UCASE/ASC/CHR/IS_NUM/NUM_TO_STR/STR_TO_NUM/EOF) parse as
+**Builtins are plain identifiers backed by one table.** Builtins
+(LENGTH/MID/RIGHT/LEFT/LCASE/UCASE/ASC/CHR/IS_NUM/NUM_TO_STR/STR_TO_NUM/EOF/MALLOC/FREE) 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: `emitExpr`'s `CallExprAST` branch checks arity against it
+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 is the
-odd one out: its intercept consumes `CallExprAST::getLine()` (runtime diagnostics) and
-it is the only builtin that touches mutable runtime state and can throw at run time.
+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.
**Program exceptions use the C++ ABI; compiler diagnostics do not.**
`ExceptionHandler` emits anonymous integer exceptions (an internal placeholder),
diff --git a/AGENTS/EXTENDING.md b/AGENTS/EXTENDING.md
index 5e104c8..b3f481a 100644
--- a/AGENTS/EXTENDING.md
+++ b/AGENTS/EXTENDING.md
@@ -17,10 +17,9 @@ already terminated the block.
**New builtin function:** add a `{Name, Arity, ReturnTypeName}` row to the shared
`Builtins` table in the internal `lib/CodeGen/Builtins.h` (single source of truth — arity checking in
-`emitExpr`, the return type in `getExprTypeInfo`, and the reject-user-redefinition check
+`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
-(String/StringConversion) or inline, and add the name intercept in `emitExpr`'s
-CallExprAST section — null-check every emitted argument before use, like the existing
+(String/StringConversion) or inline, and add the name intercept in `CodeGen::emitCall` — null-check every emitted argument before use, like the existing
branches do. Builtins are plain identifiers — nothing is needed in lexer/parser.
**New binary operator:** token (if multi-char) → one line in `BinopPrecedence`
diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md
index e58574e..6b4793c 100644
--- a/AGENTS/SUBSYSTEMS.md
+++ b/AGENTS/SUBSYSTEMS.md
@@ -98,7 +98,7 @@ CodeGen, AST nodes or the symbol table; `CodeGen::emitStmt`'s four file branches
intercept) evaluate/coerce operands and hand over `llvm::Value*`s plus the statement
line. Calls into throwing helpers go through ExceptionHandler. On first file use,
`ensureRuntime()` synthesizes the whole runtime once — the
-only module-level helper functions in the project: internal-linkage `__cps_file_find/
+file module-level helpers: internal-linkage `__cps_file_find/
open/read/write/close/eof` plus a 16-slot open-file table (`__cps_file_names/handles/
modes` parallel globals; mode byte 0 = free). Files are keyed by filename *content*
(strcmp scan), consistent with STRING comparison; the name pointer is stored as-is
@@ -107,3 +107,5 @@ malloc/realloc buffer per line and strips one trailing `\r`; fopen modes are tex
`"r"/"w"/"a"` (Windows CRT translates CRLF). File-free programs get byte-identical IR —
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 helpers and a linked list of live allocation start addresses. Only explicit MALLOC allocations enter the list; STRING/ARRAY internals retain their existing ownership. FREE validates non-null addresses, unlinks and frees the tracking node, releases the block and returns the original address. Zero-byte allocation returns null. 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.