🐐 String indexing and slicing

This commit is contained in:
2026-04-21 23:07:40 +02:00
parent 378c28102c
commit 9003d49b20
5 changed files with 153 additions and 1 deletions

View File

@@ -833,6 +833,17 @@ class ArrayIndex(Node):
if k not in d:
raise CentvrionError(f"Key not found in dict")
return vtable, d[k]
if isinstance(array, ValStr):
if isinstance(index, ValInt):
i = index.value()
elif isinstance(index, ValFrac) and index.value().denominator == 1:
i = index.value().numerator
else:
raise CentvrionError("String index must be a number")
s = array.value()
if i < 1 or i > len(s):
raise CentvrionError(f"Index {i} out of range for string of length {len(s)}")
return vtable, ValStr(s[i - 1])
if not isinstance(array, ValList):
raise CentvrionError("Cannot index a non-array value")
if isinstance(index, ValInt):
@@ -877,6 +888,16 @@ class ArraySlice(Node):
vtable, array = self.array.eval(vtable)
vtable, from_val = self.from_index.eval(vtable)
vtable, to_val = self.to_index.eval(vtable)
if isinstance(array, ValStr):
from_int = _to_index_int(from_val)
to_int = _to_index_int(to_val)
s = array.value()
if from_int < 1 or to_int > len(s) or from_int > to_int:
raise CentvrionError(
f"Slice [{from_int} VSQVE {to_int}] out of range"
f" for string of length {len(s)}"
)
return vtable, ValStr(s[from_int - 1 : to_int])
if not isinstance(array, ValList):
raise CentvrionError("Cannot slice a non-array value")
from_int = _to_index_int(from_val)

View File

@@ -721,6 +721,22 @@ void cent_list_push(CentValue *lst, CentValue v) {
CentValue cent_list_index(CentValue lst, CentValue idx) {
if (lst.type == CENT_DICT)
return cent_dict_get(lst, idx);
if (lst.type == CENT_STR) {
long i;
if (idx.type == CENT_INT)
i = idx.ival;
else if (idx.type == CENT_FRAC && idx.fval.den == 1)
i = idx.fval.num;
else
cent_type_error("string index must be an integer");
long slen = (long)strlen(lst.sval);
if (i < 1 || i > slen)
cent_runtime_error("string index out of range");
char *ch = cent_arena_alloc(cent_arena, 2);
ch[0] = lst.sval[i - 1];
ch[1] = '\0';
return cent_str(ch);
}
if (lst.type != CENT_LIST)
cent_type_error("index requires a list or dict");
long i;
@@ -736,6 +752,20 @@ CentValue cent_list_index(CentValue lst, CentValue idx) {
}
CentValue cent_list_slice(CentValue lst, CentValue lo, CentValue hi) {
if (lst.type == CENT_STR) {
if (lo.type != CENT_INT || hi.type != CENT_INT)
cent_type_error("slice indices must be integers");
long from = lo.ival;
long to = hi.ival;
long slen = (long)strlen(lst.sval);
if (from < 1 || to > slen || from > to)
cent_runtime_error("string slice out of range");
int len = (int)(to - from + 1);
char *buf = cent_arena_alloc(cent_arena, len + 1);
memcpy(buf, lst.sval + from - 1, len);
buf[len] = '\0';
return cent_str(buf);
}
if (lst.type != CENT_LIST)
cent_type_error("slice requires a list");
if (lo.type != CENT_INT || hi.type != CENT_INT)