From 5097edca0619007eb4237e52fcc07f0e0b4b99e2 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sat, 17 Oct 2026 08:38:02 +0000 Subject: docs(classes): document destructors, DELETE and RAII Co-Authored-By: Claude Opus 5.5 --- doc/language/cpsc-language-overview.7.md | 3 +- doc/language/function/cpsc-function-free.7.md | 6 +-- doc/language/keyword/cpsc-keyword-class.7.md | 8 ++-- doc/language/keyword/cpsc-keyword-delete.7.md | 57 +++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 doc/language/keyword/cpsc-keyword-delete.7.md (limited to 'doc/language') diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md index 21fbaff..cb31d93 100644 --- a/doc/language/cpsc-language-overview.7.md +++ b/doc/language/cpsc-language-overview.7.md @@ -41,6 +41,7 @@ The compiler extensions TRY/CATCH/ENDTRY and THROW support anonymous exceptions - [cpsc-keyword-closefile(7)](keyword/cpsc-keyword-closefile.7.md): close a text file. - [cpsc-keyword-type(7)](keyword/cpsc-keyword-type.7.md): define enumerations, pointers, and records. - [cpsc-keyword-c_type(7)](keyword/cpsc-keyword-c_type.7.md): import native C types and explicitly cast values. +- [cpsc-keyword-delete(7)](keyword/cpsc-keyword-delete.7.md): destroy objects and release heap allocations. - [cpsc-keyword-class(7)](keyword/cpsc-keyword-class.7.md): define a class with fields and methods. - [cpsc-keyword-and(7)](keyword/cpsc-keyword-and.7.md): combine conditions with logical AND. - [cpsc-keyword-or(7)](keyword/cpsc-keyword-or.7.md): combine conditions with logical OR. @@ -70,7 +71,7 @@ Closing and auxiliary keywords are documented with their main constructs: THEN/E # UNSUPPORTED FEATURES -DATE, SET types and DEFINE, random-file operations (RANDOM/SEEK/GETRECORD/PUTRECORD), INT, RAND, string escapes, whole-array assignment or return, array fields, and class constructors/destructors/inheritance (NEW/INHERITS/SUPER). +DATE, SET types and DEFINE, random-file operations (RANDOM/SEEK/GETRECORD/PUTRECORD), INT, RAND, string escapes, whole-array assignment or return, array fields, and class inheritance (INHERITS/SUPER). The individual pages note relevant differences from the Cambridge 2026 pseudocode guide. This manual describes the compiler's current support. diff --git a/doc/language/function/cpsc-function-free.7.md b/doc/language/function/cpsc-function-free.7.md index e2c8f12..61a3558 100644 --- a/doc/language/function/cpsc-function-free.7.md +++ b/doc/language/function/cpsc-function-free.7.md @@ -12,11 +12,11 @@ FREE(pointer) # DESCRIPTION -FREE is a compiler extension. Its argument and return type are C `void*`. Explicitly cast other pointer types to a `void*` alias before passing them. A null pointer is accepted and returned. A non-null pointer must be the start of an active explicit MALLOC or REALLOC allocation; internal STRING/ARRAY storage, stack addresses, interior addresses and already released allocations are rejected with a source-line diagnostic on stdout and an anonymous exception. +FREE is a compiler extension. Its argument and return type are C `void*`. Explicitly cast other pointer types to a `void*` alias before passing them. A null pointer is accepted and returned. A non-null pointer must be the start of an active explicit MALLOC, REALLOC or keyword NEW allocation; internal STRING/ARRAY storage, stack addresses, interior addresses and already released allocations are rejected with a source-line diagnostic on stdout and an anonymous exception. FREE returns its input address after releasing the allocation. It does not clear the caller's variable. The returned address and all aliases are invalid for memory access. Calling FREE again on that address throws unless a subsequent allocation has reused the address. Tracking cannot distinguish stale aliases once an address is reused. -The result can be discarded with a standalone call. No user destructor is called. +The result can be discarded with a standalone call. No user destructor is called. Use keyword DELETE on a class object to destroy it and its fields before releasing its allocation. # EXAMPLE @@ -29,4 +29,4 @@ FREE(Memory) # SEE ALSO -[cpsc-function-malloc(7)](cpsc-function-malloc.7.md), [cpsc-function-realloc(7)](cpsc-function-realloc.7.md), [cpsc-keyword-function(7)](../keyword/cpsc-keyword-function.7.md), [cpsc-keyword-try(7)](../keyword/cpsc-keyword-try.7.md). +[cpsc-keyword-delete(7)](../keyword/cpsc-keyword-delete.7.md), [cpsc-function-malloc(7)](cpsc-function-malloc.7.md), [cpsc-function-realloc(7)](cpsc-function-realloc.7.md), [cpsc-keyword-function(7)](../keyword/cpsc-keyword-function.7.md), [cpsc-keyword-try(7)](../keyword/cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-class.7.md b/doc/language/keyword/cpsc-keyword-class.7.md index f0d2e12..a58e8a8 100644 --- a/doc/language/keyword/cpsc-keyword-class.7.md +++ b/doc/language/keyword/cpsc-keyword-class.7.md @@ -38,13 +38,15 @@ Classes retain record value semantics: zero initialization, whole-value copying, A constructor is a PROCEDURE named NEW, following guide section 10.2. It may be PUBLIC or PRIVATE; FUNCTION NEW and global PROCEDURE NEW are errors. Member names are case insensitive, so New and new also name the constructor. Only one NEW is allowed per class. Explicit `Object.NEW(arguments)`, `CALL Object.NEW(arguments)` and `this.NEW(arguments)` behave like ordinary member calls and may be repeated; they do not zero the object or reconstruct its fields. -`DECLARE Object : ClassName`, `DECLARE Object : ClassName()` and `DECLARE Object : ClassName(arguments)` zero the object's storage, construct its fields recursively in declaration order, then call its NEW procedure. These automatic DECLARE, field and array calls are compiler extensions. Array elements and class-valued fields in records or classes use parameterless construction, before the enclosing constructor runs. A required constructor argument cannot be omitted; supplying arguments to a class without NEW is an error. Empty parentheses are allowed for a class without NEW. Constructor arguments after ARRAY OF are unsupported. A declaration executed again, such as inside a loop, zeroes and constructs its original storage again. +`DECLARE Object : ClassName`, `DECLARE Object : ClassName()` and `DECLARE Object : ClassName(arguments)` zero the object's storage, construct its fields recursively in declaration order, then call its NEW procedure. These automatic DECLARE, field and array calls are compiler extensions. Array elements and class-valued fields in records or classes use parameterless construction, before the enclosing constructor runs. A required constructor argument cannot be omitted; supplying arguments to a class without NEW is an error. Empty parentheses are allowed for a class without NEW. Constructor arguments after ARRAY OF are unsupported. A declaration executed again, such as inside a loop, first destroys its previous live incarnation, then zeroes and constructs its original storage again. The keyword NEW is allowed only as the complete right side of assignment: `Target <- NEW ClassName`, `Target <- NEW ClassName()` or `Target <- NEW ClassName(arguments)`. Target must have exactly the named class type. NEW uses the checked MALLOC allocation path, zeroes storage and constructs fields before calling NEW. A method-only class receives at least one byte of heap storage so its object address is non-null. Allocation failure reports a runtime error and throws; constructor exceptions also propagate to TRY/CATCH. Private constructor access and argument checks follow ordinary member-call rules. When Target is a declared class variable, including a function local or BYVAL parameter, NEW rebinds that variable to the heap object. No `^` dereference is needed to access it. Address-of, BYREF calls and method calls use its current object. Pointers taken before rebinding continue to refer to the previous object. Ordinary `A <- B` remains a value copy into A's current object and does not rebind A. BYVAL parameters copy the caller's value and can rebind independently. -For an array element, field (including a bare field inside a method), BYREF parameter, this, or pointer dereference, NEW constructs a heap object and copies its value into the existing target. That temporary allocation is retained. There is no automatic reclamation, destructor or DELETE support; INHERITS, SUPER and array fields remain unsupported. +For an array element, field (including a bare field inside a method), BYREF parameter, this, or pointer dereference, NEW constructs a heap object and copies its value into the existing target. That temporary allocation is retained. INHERITS, SUPER and array fields remain unsupported. + +A parameterless PROCEDURE DELETE defines a destructor. Explicit DELETE method calls are ordinary calls; keyword DELETE validates a heap object, destroys it and its fields, then frees the allocation. DECLARE storage and BYVAL copies are automatically destroyed in reverse order at normal function exit and during unwinding; main-level objects are destroyed only at normal program end. NEW rebinding leaves automatic destruction attached to the original storage. See [cpsc-keyword-delete(7)](cpsc-keyword-delete.7.md) for lifetime and access rules. # EXAMPLE @@ -65,4 +67,4 @@ OUTPUT Item.Get() # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-function(7)](cpsc-keyword-function.7.md), [cpsc-keyword-procedure(7)](cpsc-keyword-procedure.7.md), [cpsc-keyword-call(7)](cpsc-keyword-call.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-delete(7)](cpsc-keyword-delete.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-function(7)](cpsc-keyword-function.7.md), [cpsc-keyword-procedure(7)](cpsc-keyword-procedure.7.md), [cpsc-keyword-call(7)](cpsc-keyword-call.7.md). diff --git a/doc/language/keyword/cpsc-keyword-delete.7.md b/doc/language/keyword/cpsc-keyword-delete.7.md new file mode 100644 index 0000000..6ee6284 --- /dev/null +++ b/doc/language/keyword/cpsc-keyword-delete.7.md @@ -0,0 +1,57 @@ +% CPSC-KEYWORD-DELETE(7) + +# NAME + +cpsc-keyword-delete - destroy objects and release heap allocations + +# SYNOPSIS + +```text +CLASS ClassName + PROCEDURE DELETE() + statements + ENDPROCEDURE +ENDCLASS +DELETE Object +DELETE Pointer^ +DELETE Array[Index] +DELETE this +Object.DELETE() +CALL Object.DELETE() +``` + +# DESCRIPTION + +Destructors, keyword DELETE and automatic destruction are compiler extensions; the Cambridge 2026 guide defines NEW constructors but no destructors. A destructor is a parameterless PROCEDURE named DELETE inside a CLASS. It may be PUBLIC or PRIVATE. Member names are case insensitive; only one DELETE is allowed per class. FUNCTION DELETE, global PROCEDURE DELETE and destructor parameters are errors. + +An explicit `Object.DELETE()`, `CALL Object.DELETE()` or `this.DELETE()` is an ordinary method call. It calls only the method, without automatically destroying fields or releasing memory. It does not end the object's automatic lifetime. + +The statement `DELETE Object` requires an addressable class object. It first checks that the address is the start of an active tracked heap allocation, including allocations created by keyword NEW. Stack objects, internal array storage, interior addresses and previously released allocations fail with a source-line runtime diagnostic and an anonymous exception before any destructor runs. Address reuse can make a stale alias indistinguishable from a current allocation. + +After validation, DELETE calls the object's DELETE method if present, then recursively destroys its class-valued fields in reverse declaration order, including through record fields, and releases the allocation through FREE. The variable and all aliases remain dangling. If destruction throws, memory release is not reached. Heap objects are never automatically destroyed. + +Automatic destruction (RAII) applies to original storage created by DECLARE, including main-level declarations, arrays and records containing class values, and to BYVAL copies containing class values. Destruction occurs in reverse declaration order on RETURN, at the end of a function or procedure, and at normal program end. Array elements are destroyed in reverse flat element order. Block exit alone does not destroy these function-scoped lifetimes. A declaration executed again first destroys its previous live incarnation, then zeroes and constructs the original storage again. + +A completed construction or BYVAL copy marks the object alive. Destruction clears this state before calling the method, so a throwing destructor is never retried automatically. BYVAL copies are shallow. NEW rebinding changes the variable's current address, while automatic destruction still targets its original storage; the heap object requires explicit DELETE. + +Exception unwinding destroys live objects in each function frame being left before the caller's CATCH runs. A CATCH inside the same function retains its objects until function exit. An uncaught exception reaching main's final handler skips destruction of main-level objects. If a destructor throws during unwinding, its exception propagates and interrupts the remaining cleanup instead of terminating as C++ would. + +Ordinary method access rules apply to explicit, keyword and automatic destruction. A private DELETE makes destruction outside the owning class a compile error. + +# EXAMPLE + +```text +CLASS Item + PROCEDURE DELETE() + OUTPUT "destroyed" + ENDPROCEDURE +ENDCLASS +DECLARE Object : Item +Object <- NEW Item() +DELETE Object +// Normal program end also destroys Object's original stack storage. +``` + +# SEE ALSO + +[cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md), [cpsc-function-free(7)](../function/cpsc-function-free.7.md). -- cgit v1.3.1-4-g156e