From 0dd0b0908300eee08a06ee51d9eb48b85fd97d74 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Tue, 27 Oct 2026 13:27:14 +0000 Subject: refactor(memory)!: move allocation functions into memory.cps Route keyword NEW and DELETE through the same library runtime and retain allocation tracking, runtime diagnostics and exception behavior. BREAKING CHANGE: -no-std programs using NEW or DELETE must explicitly import memory.cps. Co-Authored-By: Claude Opus 5.5 --- tests/CMakeLists.txt | 26 +++++----- tests/iii/memory-call-arity/case.json | 2 +- tests/iii/memory-no-std/case.json | 27 ++++++++++ tests/iii/memory-no-std/program.cps | 10 ++++ tests/iii/memory-pointer-type/case.json | 2 +- tests/iii/memory-size-type/case.json | 4 +- tests/iii/template-explicit-errors/case.json | 2 +- tests/library/exp-memory/case.json | 1 + tests/library/exp-memory/expected-stderr.txt | 3 ++ tests/library/exp-memory/expected.txt | 17 +++++++ tests/library/exp-memory/notes.md | 3 ++ tests/library/exp-memory/program.cps | 76 ++++++++++++++++++++++++++++ tests/library/exp-string/case.json | 2 +- tests/library/exp-string/program.cps | 2 +- 14 files changed, 158 insertions(+), 19 deletions(-) create mode 100644 tests/iii/memory-no-std/case.json create mode 100644 tests/iii/memory-no-std/program.cps create mode 100644 tests/library/exp-memory/case.json create mode 100644 tests/library/exp-memory/expected-stderr.txt create mode 100644 tests/library/exp-memory/expected.txt create mode 100644 tests/library/exp-memory/notes.md create mode 100644 tests/library/exp-memory/program.cps (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c5b33a1..b7b2e45 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,16 +31,18 @@ foreach(suite i ii iii) endforeach() endforeach() -# Keep the library beside its built objects without assuming a build directory name. -set(cpsc_library_case "${CMAKE_BINARY_DIR}/test-cases/i/exp-string") -foreach(file program.cps case.json expected.txt expected-stderr.txt) - configure_file("library/exp-string/${file}" "${cpsc_library_case}/${file}" COPYONLY) +# Keep the libraries beside their built objects without assuming a build directory name. +foreach(library exp-string exp-memory) + set(cpsc_library_case "${CMAKE_BINARY_DIR}/test-cases/i/${library}") + foreach(file program.cps case.json expected.txt expected-stderr.txt) + configure_file("library/${library}/${file}" "${cpsc_library_case}/${file}" COPYONLY) + endforeach() + add_test(NAME "i/${library}" COMMAND "${PERL_EXECUTABLE}" + "${CMAKE_CURRENT_SOURCE_DIR}/run.pl" + --case "${cpsc_library_case}/case.json" --cpsc "$" + --run-mode "${CPSC_RUN_MODE}" --perl "${PERL_EXECUTABLE}" + --cc "${CMAKE_C_COMPILER}" --cxx "${CMAKE_CXX_COMPILER}" + --seed "${CPSC_TEST_SEED}" --count "${CPSC_TEST_COUNT}" + --results "${CMAKE_BINARY_DIR}/test-results") + set_tests_properties("i/${library}" PROPERTIES LABELS "i" TIMEOUT 900) endforeach() -add_test(NAME "i/exp-string" COMMAND "${PERL_EXECUTABLE}" - "${CMAKE_CURRENT_SOURCE_DIR}/run.pl" - --case "${cpsc_library_case}/case.json" --cpsc "$" - --run-mode "${CPSC_RUN_MODE}" --perl "${PERL_EXECUTABLE}" - --cc "${CMAKE_C_COMPILER}" --cxx "${CMAKE_CXX_COMPILER}" - --seed "${CPSC_TEST_SEED}" --count "${CPSC_TEST_COUNT}" - --results "${CMAKE_BINARY_DIR}/test-results") -set_tests_properties("i/exp-string" PROPERTIES LABELS "i" TIMEOUT 900) diff --git a/tests/iii/memory-call-arity/case.json b/tests/iii/memory-call-arity/case.json index 3159635..08583d7 100644 --- a/tests/iii/memory-call-arity/case.json +++ b/tests/iii/memory-call-arity/case.json @@ -1,7 +1,7 @@ { "errors": [ { - "reason": "FREE\\ expects\\ 1\\ arg", + "reason": "No matching overload for FREE", "line": 1 } ] diff --git a/tests/iii/memory-no-std/case.json b/tests/iii/memory-no-std/case.json new file mode 100644 index 0000000..34a3e90 --- /dev/null +++ b/tests/iii/memory-no-std/case.json @@ -0,0 +1,27 @@ +{ + "compiler_args": [ + "-no-std" + ], + "errors": [ + { + "reason": "Call to undefined function MALLOC", + "line": 6 + }, + { + "reason": "Call to undefined function REALLOC", + "line": 7 + }, + { + "reason": "Call to undefined function FREE", + "line": 8 + }, + { + "reason": "NEW/DELETE requires memory.cps", + "line": 9 + }, + { + "reason": "NEW/DELETE requires memory.cps", + "line": 10 + } + ] +} diff --git a/tests/iii/memory-no-std/program.cps b/tests/iii/memory-no-std/program.cps new file mode 100644 index 0000000..69941d6 --- /dev/null +++ b/tests/iii/memory-no-std/program.cps @@ -0,0 +1,10 @@ +CLASS Item + Value : INTEGER +ENDCLASS +TYPE Raw = C_TYPE("void*") +DECLARE Obj : Item +MALLOC(8) +REALLOC((Raw)0, 8) +FREE((Raw)0) +Obj <- NEW Item() +DELETE Obj diff --git a/tests/iii/memory-pointer-type/case.json b/tests/iii/memory-pointer-type/case.json index 557c4b9..973a4c9 100644 --- a/tests/iii/memory-pointer-type/case.json +++ b/tests/iii/memory-pointer-type/case.json @@ -1,7 +1,7 @@ { "errors": [ { - "reason": "Cannot\\ implicitly\\ convert", + "reason": "No matching overload for FREE", "line": 4 } ] diff --git a/tests/iii/memory-size-type/case.json b/tests/iii/memory-size-type/case.json index 6354ba8..d5848f2 100644 --- a/tests/iii/memory-size-type/case.json +++ b/tests/iii/memory-size-type/case.json @@ -1,11 +1,11 @@ { "errors": [ { - "reason": "Allocation\\ size\\ must\\ be\\ INTEGER\\ or\\ a\\ C\\ integer", + "reason": "No matching overload for MALLOC", "line": 1 }, { - "reason": "Allocation size must be INTEGER or a C integer", + "reason": "No matching overload for REALLOC", "line": 4 } ] diff --git a/tests/iii/template-explicit-errors/case.json b/tests/iii/template-explicit-errors/case.json index 657f69e..e705356 100644 --- a/tests/iii/template-explicit-errors/case.json +++ b/tests/iii/template-explicit-errors/case.json @@ -4,7 +4,7 @@ {"reason": "No matching overload for Max", "line": 20}, {"reason": "Explicit template arguments require a function template: Plain", "line": 21}, {"reason": "Explicit template arguments are not allowed on builtin EOF", "line": 22}, - {"reason": "Explicit template arguments are not allowed on builtin MALLOC", "line": 23}, + {"reason": "Explicit template arguments require a function template: MALLOC", "line": 23}, {"reason": "Ambiguous call to Tied", "line": 24} ] } diff --git a/tests/library/exp-memory/case.json b/tests/library/exp-memory/case.json new file mode 100644 index 0000000..7a60233 --- /dev/null +++ b/tests/library/exp-memory/case.json @@ -0,0 +1 @@ +{"sources":["program.cps","../../../pseudocode-lib/memory.cps"],"compiler_args":["-no-std"]} diff --git a/tests/library/exp-memory/expected-stderr.txt b/tests/library/exp-memory/expected-stderr.txt new file mode 100644 index 0000000..9ade8ef --- /dev/null +++ b/tests/library/exp-memory/expected-stderr.txt @@ -0,0 +1,3 @@ +[Fatal] line 63: Invalid memory address (not an active allocation) +[Fatal] line 68: Memory allocation failed +[Fatal] line 73: Memory allocation failed diff --git a/tests/library/exp-memory/expected.txt b/tests/library/exp-memory/expected.txt new file mode 100644 index 0000000..b2272a2 --- /dev/null +++ b/tests/library/exp-memory/expected.txt @@ -0,0 +1,17 @@ +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +TRUETRUE +7 +17 +1 +2 +3 diff --git a/tests/library/exp-memory/notes.md b/tests/library/exp-memory/notes.md new file mode 100644 index 0000000..bc983f5 --- /dev/null +++ b/tests/library/exp-memory/notes.md @@ -0,0 +1,3 @@ +# Explicit memory library trace + +This compatibility fixture imports memory.cps with -no-std and no STRING library. Each supported C integer type produces null for zero allocation and resizing, then supports a nested allocation/resize/release. NEW storage retains 7 through REALLOC and is accepted by DELETE. MALLOC storage holds 17 and is accepted by DELETE. FREE releases NEW storage, so a subsequent DELETE throws before destruction. Negative signed-char and maximum unsigned-long-long sizes both fail allocation, confirming signed extension and unsigned range preservation. Expected values are derived directly from these assignments; human review pending. diff --git a/tests/library/exp-memory/program.cps b/tests/library/exp-memory/program.cps new file mode 100644 index 0000000..5b0eb07 --- /dev/null +++ b/tests/library/exp-memory/program.cps @@ -0,0 +1,76 @@ +INCLUDE "../../../pseudocode-lib/memory.cps" +TYPE Raw = C_TYPE("void*") +DECLARE Empty : Raw +TYPE Size0 = C_TYPE("_Bool") +TYPE Size1 = C_TYPE("char") +TYPE Size2 = C_TYPE("signed char") +TYPE Size3 = C_TYPE("unsigned char") +TYPE Size4 = C_TYPE("short") +TYPE Size5 = C_TYPE("unsigned short") +TYPE Size6 = C_TYPE("int") +TYPE Size7 = C_TYPE("unsigned int") +TYPE Size8 = C_TYPE("long") +TYPE Size9 = C_TYPE("unsigned long") +TYPE Size10 = C_TYPE("long long") +TYPE Size11 = C_TYPE("unsigned long long") +OUTPUT malloc((Size0)0) = Empty, realloc(Empty, (Size0)0) = Empty +FREE(REALLOC(MALLOC((Size0)1), (Size0)2)) +OUTPUT malloc((Size1)0) = Empty, realloc(Empty, (Size1)0) = Empty +FREE(REALLOC(MALLOC((Size1)1), (Size1)2)) +OUTPUT malloc((Size2)0) = Empty, realloc(Empty, (Size2)0) = Empty +FREE(REALLOC(MALLOC((Size2)1), (Size2)2)) +OUTPUT malloc((Size3)0) = Empty, realloc(Empty, (Size3)0) = Empty +FREE(REALLOC(MALLOC((Size3)1), (Size3)2)) +OUTPUT malloc((Size4)0) = Empty, realloc(Empty, (Size4)0) = Empty +FREE(REALLOC(MALLOC((Size4)1), (Size4)2)) +OUTPUT malloc((Size5)0) = Empty, realloc(Empty, (Size5)0) = Empty +FREE(REALLOC(MALLOC((Size5)1), (Size5)2)) +OUTPUT malloc((Size6)0) = Empty, realloc(Empty, (Size6)0) = Empty +FREE(REALLOC(MALLOC((Size6)1), (Size6)2)) +OUTPUT malloc((Size7)0) = Empty, realloc(Empty, (Size7)0) = Empty +FREE(REALLOC(MALLOC((Size7)1), (Size7)2)) +OUTPUT malloc((Size8)0) = Empty, realloc(Empty, (Size8)0) = Empty +FREE(REALLOC(MALLOC((Size8)1), (Size8)2)) +OUTPUT malloc((Size9)0) = Empty, realloc(Empty, (Size9)0) = Empty +FREE(REALLOC(MALLOC((Size9)1), (Size9)2)) +OUTPUT malloc((Size10)0) = Empty, realloc(Empty, (Size10)0) = Empty +FREE(REALLOC(MALLOC((Size10)1), (Size10)2)) +OUTPUT malloc((Size11)0) = Empty, realloc(Empty, (Size11)0) = Empty +FREE(REALLOC(MALLOC((Size11)1), (Size11)2)) +CLASS Item + Value : INTEGER +ENDCLASS +TYPE ItemPointer = ^Item +DECLARE Obj : Item +DECLARE P : ItemPointer +DECLARE Address : Raw +Obj <- NEW Item() +Obj.Value <- 7 +P <- ^Obj +Address <- REALLOC((Raw)P, 16) +P <- (ItemPointer)Address +OUTPUT P^.Value +DELETE P^ +P <- (ItemPointer)MALLOC(8) +P^.Value <- 17 +OUTPUT P^.Value +DELETE P^ +Obj <- NEW Item() +P <- ^Obj +Address <- (Raw)P +FREE(Address) +TRY + DELETE Obj +CATCH + OUTPUT 1 +ENDTRY +TRY + MALLOC((Size2)-1) +CATCH + OUTPUT 2 +ENDTRY +TRY + MALLOC((Size11)-1) +CATCH + OUTPUT 3 +ENDTRY diff --git a/tests/library/exp-string/case.json b/tests/library/exp-string/case.json index 4e37b1c..824231f 100644 --- a/tests/library/exp-string/case.json +++ b/tests/library/exp-string/case.json @@ -1 +1 @@ -{"sources":["program.cps","../../../pseudocode-lib/string.cps"],"compiler_args":["-no-std"]} +{"sources":["program.cps","../../../pseudocode-lib/std.cps","../../../pseudocode-lib/string.cps","../../../pseudocode-lib/memory.cps"],"compiler_args":["-no-std"]} diff --git a/tests/library/exp-string/program.cps b/tests/library/exp-string/program.cps index 2e45dc3..d66a01f 100644 --- a/tests/library/exp-string/program.cps +++ b/tests/library/exp-string/program.cps @@ -1,4 +1,4 @@ -INCLUDE "../../../pseudocode-lib/string.cps" +INCLUDE "../../../pseudocode-lib/std.cps" FUNCTION Echo(S : STRING) RETURNS STRING RETURN S ENDFUNCTION -- cgit v1.3.1-4-g156e