🐐 String indexing and slicing
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user