diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-20 10:56:22 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-20 10:56:22 +0000 |
| commit | cf9af14fe749c52473fdf5a327c3e935e45bf0e7 (patch) | |
| tree | 4c22c4a919e3da709b16055ff6762ea1195b6237 | |
| parent | 1ed0e276a37d39386b22b08c1f9e575a8f8f8725 (diff) | |
feat(library): add experimental string LEFT function
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | pseudocode-lib/README.md | 4 | ||||
| -rw-r--r-- | pseudocode-lib/_exp_string.cc | 8 | ||||
| -rw-r--r-- | pseudocode-lib/_exp_string.cps | 6 | ||||
| -rw-r--r-- | tests/library/exp-string/expected.txt | 4 | ||||
| -rw-r--r-- | tests/library/exp-string/notes.md | 2 | ||||
| -rw-r--r-- | tests/library/exp-string/program.cps | 5 |
6 files changed, 28 insertions, 1 deletions
diff --git a/pseudocode-lib/README.md b/pseudocode-lib/README.md index 92a4bbb..b776d16 100644 --- a/pseudocode-lib/README.md +++ b/pseudocode-lib/README.md @@ -17,4 +17,6 @@ INCLUDE paths are relative to the program. Adjust them when the program is elsew `_EXP_STRING` owns an unbounded `std::string` through one handle. Constructors accept no arguments, another `_EXP_STRING`, `C_STRING`, or `(INTEGER count, C_CHAR character)`. Cast literals to C types explicitly; built-in STRING is not a constructor argument. Copy construction and assignment own independent strings. `_HANDLE` is public only for library implementation access; do not modify or free it. -The first version provides `&`, `_EXP_STRING_NUM_TO_STR` (INTEGER/REAL), `_EXP_STRING_STR_TO_NUM` (REAL), `_EXP_STRING_LENGTH` (byte length) and `_EXP_STRING_OUTPUT` (text plus newline). Numeric formatting uses `std::to_string`; parsing uses `std::stod` and requires full consumption. C++ standard exceptions print the user call line and are catchable with TRY/CATCH. The built-in STRING remains available with its existing lifetime and NUL limitations. Owning class values inside whole-record or BYVAL-array copies still have bitwise-copy limitations. +The library provides `&`, `_EXP_STRING_NUM_TO_STR` (INTEGER/REAL), `_EXP_STRING_STR_TO_NUM` (REAL), `_EXP_STRING_LENGTH` (byte length) and `_EXP_STRING_OUTPUT` (text plus newline). Numeric formatting uses `std::to_string`; parsing uses `std::stod` and requires full consumption. C++ standard exceptions print the user call line and are catchable with TRY/CATCH. The built-in STRING remains available with its existing lifetime and NUL limitations. Owning class values inside whole-record or BYVAL-array copies still have bitwise-copy limitations. + +`_EXP_STRING_LEFT(S : _EXP_STRING, Count : INTEGER)` returns a new `_EXP_STRING` containing up to Count bytes from the beginning. Nonpositive counts return an empty string; counts exceeding the length return the whole string. Embedded NUL bytes are preserved. diff --git a/pseudocode-lib/_exp_string.cc b/pseudocode-lib/_exp_string.cc index 248b718..ada7c8c 100644 --- a/pseudocode-lib/_exp_string.cc +++ b/pseudocode-lib/_exp_string.cc @@ -1,3 +1,4 @@ +#include <algorithm> #include <cstdio> #include <exception> #include <stdexcept> @@ -65,6 +66,13 @@ double _exp_string_impl_to_real(void *Handle) { long long _exp_string_impl_length(void *Handle) { return checked([&] { return static_cast<long long>(text(Handle).size()); }); } +void _exp_string_impl_left(void *Target, void *Handle, long long Count) { + checked([&] { + const auto &Source = text(Handle); + auto Length = Count <= 0 ? 0 : std::min(static_cast<std::size_t>(Count), Source.size()); + text(Target) = Source.substr(0, Length); + }); +} void _exp_string_impl_output(void *Handle) { checked([&] { const auto &Text = text(Handle); diff --git a/pseudocode-lib/_exp_string.cps b/pseudocode-lib/_exp_string.cps index 369e20f..34b1302 100644 --- a/pseudocode-lib/_exp_string.cps +++ b/pseudocode-lib/_exp_string.cps @@ -14,6 +14,7 @@ EXTERN "C" EXTERN_PROCEDURE _exp_string_impl_from_int(_EXP_STRING_HANDLE, _EXP_S EXTERN "C" EXTERN_PROCEDURE _exp_string_impl_from_real(_EXP_STRING_HANDLE, C_DOUBLE) EXTERN "C" EXTERN_FUNCTION _exp_string_impl_to_real(_EXP_STRING_HANDLE) RETURNS C_DOUBLE EXTERN "C" EXTERN_FUNCTION _exp_string_impl_length(_EXP_STRING_HANDLE) RETURNS _EXP_STRING_C_INTEGER +EXTERN "C" EXTERN_PROCEDURE _exp_string_impl_left(_EXP_STRING_HANDLE, _EXP_STRING_HANDLE, _EXP_STRING_C_INTEGER) EXTERN "C" EXTERN_PROCEDURE _exp_string_impl_output(_EXP_STRING_HANDLE) CLASS _EXP_STRING @@ -65,3 +66,8 @@ ENDFUNCTION PROCEDURE _EXP_STRING_OUTPUT(S : _EXP_STRING) CALL _exp_string_impl_output(S._HANDLE) ENDPROCEDURE +FUNCTION _EXP_STRING_LEFT(S : _EXP_STRING, Count : INTEGER) RETURNS _EXP_STRING + DECLARE Result : _EXP_STRING + CALL _exp_string_impl_left(Result._HANDLE, S._HANDLE, (_EXP_STRING_C_INTEGER)Count) + RETURN Result +ENDFUNCTION diff --git a/tests/library/exp-string/expected.txt b/tests/library/exp-string/expected.txt index fab16b1..19f0d9b 100644 --- a/tests/library/exp-string/expected.txt +++ b/tests/library/exp-string/expected.txt @@ -8,3 +8,7 @@ TRUE conversion caught length caught heap +ABC +0:0:0 +ABCDEFGH +4 diff --git a/tests/library/exp-string/notes.md b/tests/library/exp-string/notes.md index ca7d489..f44a2b3 100644 --- a/tests/library/exp-string/notes.md +++ b/tests/library/exp-string/notes.md @@ -3,3 +3,5 @@ Review status: pending human review. Copies of hello are independent; assigning world to the copy gives helloworld when concatenated. Empty length is zero, and three NUL bytes retain length three. One hundred appended five-byte words grow 20000 bytes to 20500, preserved by BYVAL and RETURN. C++17 formatting gives 42 and 1.250000. Parsing 12.5 compares equal to 12.5. Trailing junk and negative counts emit the explicit library reasons at user lines 27 and 32, then are caught. Discarded numeric and Echo results must release their owned strings at statement end. The explicitly deleted heap object prints heap. This fixture covers compiler/library extensions, including numeric text formatting. + +LEFT keeps ABC, returns zero bytes for an empty source or nonpositive count, and clamps 20 to all eight letters. Taking four bytes from three NULs followed by hello retains all four bytes. diff --git a/tests/library/exp-string/program.cps b/tests/library/exp-string/program.cps index 719d9a4..c9dad8a 100644 --- a/tests/library/exp-string/program.cps +++ b/tests/library/exp-string/program.cps @@ -39,3 +39,8 @@ DECLARE Heap : _EXP_STRING Heap <- NEW _EXP_STRING((C_STRING)"heap") CALL _EXP_STRING_OUTPUT(Heap) DELETE Heap +DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH") +CALL _EXP_STRING_OUTPUT(_EXP_STRING_LEFT(Letters, 3)) +OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Empty, 2)), ":", _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Letters, 0)), ":", _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Letters, -1)) +CALL _EXP_STRING_OUTPUT(_EXP_STRING_LEFT(Letters, 20)) +OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_LEFT(Nuls & A, 4)) |
