codon/test/transform/str_opt.codon

71 lines
1.9 KiB
Python

cat_count = 0
# c/p from str.seq
def old_cat(*args):
total = 0
if staticlen(args) == 1 and hasattr(args[0], "__iter__") and hasattr(args[0], "__len__"):
for s in args[0]:
if not isinstance(s, str):
compile_error("not a string")
total += s.len
p = cobj(total)
n = 0
for s in args[0]:
str.memcpy(p + n, s.ptr, s.len)
n += s.len
return str(p, total)
elif staticlen(args) == 1 and hasattr(args[0], "__iter__"):
sz = 10
p = cobj(sz)
n = 0
for s in args[0]:
if not isinstance(s, str):
compile_error("not a string")
if n + s.len > sz:
sz = 1 + 3 * (n + s.len) // 2
pp = cobj(sz)
str.memcpy(pp, p, n)
p = pp
str.memcpy(p + n, s.ptr, s.len)
n += s.len
return str(p, n)
else:
total = 0
for i in args:
if not isinstance(i, str):
compile_error("not a string")
total += i.len
p = cobj(total)
n = 0
for i in args:
str.memcpy(p + n, i.ptr, i.len)
n += i.len
return str(p, total)
@extend
class str:
def cat(*args):
global cat_count
cat_count += 1
return old_cat(*args)
@test
def test_str_optimization():
assert 'hello ' + 'world' == "hello world" # no opt: just adding 2 strs
assert cat_count == 0
# assert 'a' + 'b' + 'c' == 'abc' # superseded by string statics
# assert cat_count == 1
assert 'a' * 2 == 'aa' # no opt: mul instead of add
assert cat_count == 0
# assert 'a' + ('b' + 'c') == 'abc'
# assert cat_count == 2
# assert 'a' + ('b' + ('c' + 'd')) == 'abcd'
# assert cat_count == 3
a = 'a'
b = 'b'
c = 'c'
assert (a*2 + b*3 + c*4) == 'aabbbcccc'
assert cat_count == 1
test_str_optimization()