Skip to content

Commit 3bb780e

Browse files
committed
Fix and enhance type casts to strings (#507, #508)
1 parent 7977e15 commit 3bb780e

File tree

6 files changed

+51
-6
lines changed

6 files changed

+51
-6
lines changed

doc/lang.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ If a value `s` of type `S` is given where a value `t` of some other type `T` is
417417
* `S` and `T` are compatible
418418
* `S` is an integer type and `T` is a real type
419419
* `S` is `char` and `T` is `str`
420-
* `S` is a `[]char` and `T` is `str`
420+
* `S` is `[]char` and `T` is `str`
421421
* `S` is `str` and `T` is `[]char` and `s` and `t` are not operands of a binary operator
422422
* `S` is an array type and `T` is a dynamic array type and the item types of `S` and `T` are equivalent and `s` and `t` are not operands of a binary operator
423423
* `S` is a dynamic array type and `T` is an array type and the item types of `S` and `T` are equivalent and `len(s) <= len(t)`
@@ -437,6 +437,8 @@ If a value `s` of type `S` is given where a value `t` of some other type `T` is
437437
* `S` and `T` are ordinal types
438438
* `S` and `T` are pointer types and `sizeof(s^) >= sizeof(t^)` and both `S` and `T` don't contain pointers
439439
* `S` is an interface type and `T` is a type (or a pointer to a type) that was actually converted to `S`
440+
* `S` is `[]int8` or `[]uint8` and `T` is `str`
441+
* `S` is `str` and `T` is `[]int8` or `[]uint8`
440442
* `S` is `[]U`, `T` is `[]V` and `U` can be explicitly converted to `V`
441443

442444
## Declarations

playground/umka.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/umka_expr.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,18 @@ void doExplicitTypeConv(Compiler *comp, Type *dest, Type **src, Const *constant)
712712
}
713713
}
714714

715+
// Dynamic array to string
716+
else if ((*src)->kind == TYPE_DYNARRAY && ((*src)->base->kind == TYPE_INT8 || (*src)->base->kind == TYPE_UINT8) && dest->kind == TYPE_STR)
717+
{
718+
doDynArrayToStrConv(comp, dest, src, constant, false);
719+
}
720+
721+
// String to dynamic array
722+
else if ((*src)->kind == TYPE_STR && dest->kind == TYPE_DYNARRAY && (dest->base->kind == TYPE_INT8 || dest->base->kind == TYPE_UINT8))
723+
{
724+
doStrToDynArrayConv(comp, dest, src, constant);
725+
}
726+
715727
// Dynamic array to dynamic array of another base type (covariant arrays)
716728
else if ((*src)->kind == TYPE_DYNARRAY && dest->kind == TYPE_DYNARRAY)
717729
{

src/umka_vm.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,7 +2072,7 @@ static FORCE_INLINE void doBuiltinMakefromarr(Fiber *fiber, HeapPages *pages, Er
20722072
}
20732073

20742074

2075-
// fn makefromstr(src: str): []char
2075+
// fn makefromstr(src: str): []char | []int8 | []uint8
20762076
static FORCE_INLINE void doBuiltinMakefromstr(Fiber *fiber, HeapPages *pages, Error *error)
20772077
{
20782078
DynArray *dest = (DynArray *)(fiber->top++)->ptrVal;
@@ -2118,7 +2118,7 @@ static FORCE_INLINE void doBuiltinMaketoarr(Fiber *fiber, HeapPages *pages, Erro
21182118
}
21192119

21202120

2121-
// fn maketostr(src: char | []char): str
2121+
// fn maketostr(src: char | []char | []int8 | []uint8): str
21222122
static FORCE_INLINE void doBuiltinMaketostr(Fiber *fiber, HeapPages *pages, Error *error)
21232123
{
21242124
char *dest = doGetEmptyStr();
@@ -2139,14 +2139,17 @@ static FORCE_INLINE void doBuiltinMaketostr(Fiber *fiber, HeapPages *pages, Erro
21392139
else
21402140
{
21412141
// Dynamic array to string
2142-
DynArray *src = (DynArray *)(fiber->top++)->ptrVal;
2142+
DynArray *src = (DynArray *)(fiber->top++)->ptrVal;
21432143

21442144
if (!src)
21452145
error->runtimeHandler(error->context, ERR_RUNTIME, "Dynamic array is null");
21462146

21472147
if (src->data)
21482148
{
2149-
const int64_t len = strlen((const char *)src->data);
2149+
int64_t len = 0;
2150+
while (len < getDims(src)->len && ((const char *)src->data)[len])
2151+
len++;
2152+
21502153
dest = doAllocStr(pages, len, error);
21512154
memcpy(dest, src->data, len);
21522155
}

tests/expected.log

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,12 @@ Hey Hello
749749
['H' 'e' 'l' 'l' 0x00] Hell
750750
HellHell
751751
HellHell
752+
[72 101 108 108 111 44 32 66 114 97 118 101 32 78 101 119 32 87 111 114 108 100 33]
753+
[72 101 108 108 111 44 32 -48 -76 -48 -72 -48 -78 -48 -67 -47 -117 -48 -71 32 -48 -67 -48 -66 -48 -78 -47 -117 -48 -71 32 -48 -68 -48 -72 -47 -128 33]
754+
Hello, Brave New World!
755+
Hello, дивный новый мир!
756+
['P' 'Q'] "PQ" 2 2
757+
['P' 'Q' 0x00 'R'] "PQ" 4 2
752758

753759

754760
>>> Non-local scope

tests/safecast.um

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,32 @@ fn test3() {
7070
std::assert(d + c == "abab")
7171
}
7272

73+
fn test4() {
74+
s := "Hello,"
75+
a := []uint8(s + " Brave New World!")
76+
b := []int8(s + " дивный новый мир!")
77+
printf("%v\n%v\n", a, b)
78+
printf("%s\n%s\n", str(a), str(b))
79+
}
80+
81+
fn test5() {
82+
b := []char{'P', 'Q'}
83+
b = append(b, 'R')
84+
b = delete(b, 2)
85+
printf("%v %v %v %v\n", b, str(b), len(b), len(str(b)))
86+
87+
c := []char{'P', 'Q', '\0', 'S'}
88+
c = append(c, 'R')
89+
c = delete(c, 3)
90+
printf("%v %v %v %v\n", c, str(c), len(c), len(str(c)))
91+
}
92+
7393
fn test*() {
7494
test1()
7595
test2()
7696
test3()
97+
test4()
98+
test5()
7799
}
78100

79101
fn main() {

0 commit comments

Comments
 (0)