aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-20 11:01:01 +0000
committer_ov4 <ov4@ov4.org>2026-10-20 11:01:01 +0000
commit65599524f5b41ffb6d8d55664611612c0b57ad47 (patch)
tree69eafa5e5651c13100c9509502efc1659b186d1c
parent0c4db4fea1960571318444bd39593533b04b3716 (diff)
feat(library): add experimental string MID function
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--pseudocode-lib/README.md2
-rw-r--r--pseudocode-lib/_exp_string.cc8
-rw-r--r--pseudocode-lib/_exp_string.cps6
-rw-r--r--tests/library/exp-string/expected.txt6
-rw-r--r--tests/library/exp-string/notes.md2
-rw-r--r--tests/library/exp-string/program.cps13
6 files changed, 37 insertions, 0 deletions
diff --git a/pseudocode-lib/README.md b/pseudocode-lib/README.md
index 6a4c23c..55367d0 100644
--- a/pseudocode-lib/README.md
+++ b/pseudocode-lib/README.md
@@ -22,3 +22,5 @@ The library provides `&`, `_EXP_STRING_NUM_TO_STR` (INTEGER/REAL), `_EXP_STRING_
`_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.
`_EXP_STRING_RIGHT(S : _EXP_STRING, Count : INTEGER)` returns a new `_EXP_STRING` containing up to Count bytes from the end. Nonpositive counts return an empty string; counts exceeding the length return the whole string. Embedded NUL bytes are preserved.
+
+`_EXP_STRING_MID(S : _EXP_STRING, Start : INTEGER, Count : INTEGER)` returns a new `_EXP_STRING` containing up to Count bytes from the one-based Start position. Starts below 1 clamp to 1; starts beyond the end and nonpositive counts return an empty string. Counts clamp to the remaining bytes. Embedded NUL bytes are preserved.
diff --git a/pseudocode-lib/_exp_string.cc b/pseudocode-lib/_exp_string.cc
index d881187..d406274 100644
--- a/pseudocode-lib/_exp_string.cc
+++ b/pseudocode-lib/_exp_string.cc
@@ -80,6 +80,14 @@ void _exp_string_impl_right(void *Target, void *Handle, long long Count) {
text(Target) = Source.substr(Source.size() - Length, Length);
});
}
+void _exp_string_impl_mid(void *Target, void *Handle, long long Start, long long Count) {
+ checked([&] {
+ const auto &Source = text(Handle);
+ auto Position = Start <= 1 ? 0 : std::min(static_cast<std::size_t>(Start - 1), Source.size());
+ auto Length = Count <= 0 ? 0 : std::min(static_cast<std::size_t>(Count), Source.size() - Position);
+ text(Target) = Source.substr(Position, 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 31e3b43..30eef71 100644
--- a/pseudocode-lib/_exp_string.cps
+++ b/pseudocode-lib/_exp_string.cps
@@ -16,6 +16,7 @@ EXTERN "C" EXTERN_FUNCTION _exp_string_impl_to_real(_EXP_STRING_HANDLE) RETURNS
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_right(_EXP_STRING_HANDLE, _EXP_STRING_HANDLE, _EXP_STRING_C_INTEGER)
+EXTERN "C" EXTERN_PROCEDURE _exp_string_impl_mid(_EXP_STRING_HANDLE, _EXP_STRING_HANDLE, _EXP_STRING_C_INTEGER, _EXP_STRING_C_INTEGER)
EXTERN "C" EXTERN_PROCEDURE _exp_string_impl_output(_EXP_STRING_HANDLE)
CLASS _EXP_STRING
@@ -77,3 +78,8 @@ FUNCTION _EXP_STRING_RIGHT(S : _EXP_STRING, Count : INTEGER) RETURNS _EXP_STRING
CALL _exp_string_impl_right(Result._HANDLE, S._HANDLE, (_EXP_STRING_C_INTEGER)Count)
RETURN Result
ENDFUNCTION
+FUNCTION _EXP_STRING_MID(S : _EXP_STRING, Start : INTEGER, Count : INTEGER) RETURNS _EXP_STRING
+ DECLARE Result : _EXP_STRING
+ CALL _exp_string_impl_mid(Result._HANDLE, S._HANDLE, (_EXP_STRING_C_INTEGER)Start, (_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 ef650f3..a3ce792 100644
--- a/tests/library/exp-string/expected.txt
+++ b/tests/library/exp-string/expected.txt
@@ -16,3 +16,9 @@ FGH
0:0:0
ABCDEFGH
4
+BCD
+AB
+GH
+0:0
+0:0
+4
diff --git a/tests/library/exp-string/notes.md b/tests/library/exp-string/notes.md
index ff25d0f..c05d6d7 100644
--- a/tests/library/exp-string/notes.md
+++ b/tests/library/exp-string/notes.md
@@ -9,3 +9,5 @@ LEFT keeps ABC, returns zero bytes for an empty source or nonpositive count, and
RIGHT keeps FGH, returns zero bytes for an empty source or nonpositive count, and clamps 20 to all eight letters. Taking four bytes from hello followed by three NULs retains the final o and all three NULs.
The added checks use separate procedures to keep generated temporary-object cleanup small enough for the ordinary runner timeout.
+
+MID positions 2..4 give BCD. The minimum INTEGER start clamps to 1 and gives AB; a maximum count from position 7 gives GH. Empty input, a maximum start, and nonpositive counts give length zero. Four bytes starting at the second of three NULs retain two NULs and AB.
diff --git a/tests/library/exp-string/program.cps b/tests/library/exp-string/program.cps
index f8c037f..0b6c977 100644
--- a/tests/library/exp-string/program.cps
+++ b/tests/library/exp-string/program.cps
@@ -41,6 +41,7 @@ CALL _EXP_STRING_OUTPUT(Heap)
DELETE Heap
CALL CheckLeft()
CALL CheckRight()
+CALL CheckMid()
PROCEDURE CheckLeft()
DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH")
@@ -63,3 +64,15 @@ PROCEDURE CheckRight()
CALL _EXP_STRING_OUTPUT(_EXP_STRING_RIGHT(Letters, 20))
OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_RIGHT(A & Nuls, 4))
ENDPROCEDURE
+
+PROCEDURE CheckMid()
+ DECLARE Letters : _EXP_STRING((C_STRING)"ABCDEFGH")
+ DECLARE Empty : _EXP_STRING
+ DECLARE Nuls : _EXP_STRING(3, (C_CHAR)'\0')
+ CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(Letters, 2, 3))
+ CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(Letters, -9223372036854775808, 2))
+ CALL _EXP_STRING_OUTPUT(_EXP_STRING_MID(Letters, 7, 9223372036854775807))
+ OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_MID(Empty, 1, 2)), ":", _EXP_STRING_LENGTH(_EXP_STRING_MID(Letters, 9223372036854775807, 2))
+ OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_MID(Letters, 2, 0)), ":", _EXP_STRING_LENGTH(_EXP_STRING_MID(Letters, 2, -1))
+ OUTPUT _EXP_STRING_LENGTH(_EXP_STRING_MID(Nuls & Letters, 2, 4))
+ENDPROCEDURE