From 4dd85fd6ecd9a67e5c2b68380873e6e114714355 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sat, 17 Oct 2026 05:30:57 +0000 Subject: feat(memory): add tracked MALLOC and FREE builtins Co-Authored-By: Claude Fable 5.1 --- AGENTS/CONVENTIONS.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'AGENTS/CONVENTIONS.md') 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), -- cgit v1.3.1-4-g156e