js: add more tests to builtin/js and implement more builtin functions (#12049)

pull/12051/head
playX 2021-10-03 10:08:21 +03:00 committed by GitHub
parent 129c81f34d
commit 9145cd66ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 2384 additions and 18 deletions

View File

@ -194,13 +194,6 @@ pub fn (mut a array) insert_many(i int, val voidptr, size int) {
#a.val.arr.arr.splice(i,0,...val.arr.slice(0,+size))
}
pub fn (mut a array) join(separator string) string {
mut res := ''
#res = new string(a.val.arr.arr.join(separator +''));
return res
}
fn (mut a array) push(val voidptr) {
#a.val.arr.make_copy()
#if (arguments[2] && arguments[2].valueOf()) {a.val.arr.arr.push(...val)} else {
@ -246,7 +239,7 @@ struct array_iterator {
#}
#array_iterator.prototype[Symbol.iterator] = function () { return this; }
#array.prototype[Symbol.iterator] = function () { console.log(this.arr.index_start); return new array_iterator({ix: new int(0),end: new int(this.arr.len),arr: this}); }
#array.prototype[Symbol.iterator] = function () { return new array_iterator({ix: new int(0),end: new int(this.arr.len),arr: this}); }
#array.prototype.entries = function () { let result = []; for (let key = this.arr.index_start.val;key < this.arr.len.val;key++) { result.push([new int(key), this.arr.get(new int(key))]); } return result[Symbol.iterator](); }
#array.prototype.map = function(callback) { return v_map(this,callback); }
#array.prototype.filter = function(callback) { return v_filter(this,callback); }

View File

@ -21,3 +21,19 @@ pub fn (c byte) str() string {
return res
}
pub fn (c byte) ascii_str() string {
res := ''
#res.str = String.fromCharCode(c.val)
return res
}
pub fn (c byte) repeat(count int) string {
mut res := ''
for _ in 0 .. count {
res += c.ascii_str()
}
return res
}

View File

@ -1,5 +1,26 @@
module builtin
pub fn (i i8) str() string {
mut res := ''
#res.str = i.val.toString()
return res
}
pub fn (i i16) str() string {
mut res := ''
#res.str = i.val.toString()
return res
}
pub fn (i u16) str() string {
mut res := ''
#res.str = i.val.toString()
return res
}
pub fn (i int) str() string {
mut res := ''
#res = new string( i )
@ -48,3 +69,82 @@ pub fn (i int_literal) str() string {
return res
}
pub fn (x u64) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x i64) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x u32) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x u16) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x i8) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x i16) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x int) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x int_literal) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
pub fn (x byte) hex() string {
res := ''
#res.str = x.val.toString(16)
return res
}
// hex returns a string with the hexadecimal representation
// of the byte elements of the array.
pub fn (b []byte) hex() string {
mut hex := ''
for i in b {
mut z := i
z = z
#let n0 = i.val >> 4
#hex.str += n0 < 10 ? String.fromCharCode(n0) : String.fromCharCode(n0 + 87)
#let n1 = i.val & 0xF
#hex.str += n1 < 10 ? String.fromCharCode(n1) : String.fromCharCode(n1 + 87)
}
return hex
}

View File

@ -0,0 +1,244 @@
const (
a = 3
u = u64(1)
)
fn test_const() {
b := (true && true) || false
assert b == true
assert a == 3
assert u == u64(1)
assert u == 1 // make sure this works without the cast
}
fn test_str_methods() {
assert i8(1).str() == '1'
assert i8(-1).str() == '-1'
assert i16(1).str() == '1'
assert i16(-1).str() == '-1'
assert int(1).str() == '1'
assert int(-1).str() == '-1'
assert int(2147483647).str() == '2147483647'
// todo: overflow check for integers
// assert int(2147483648).str() == '-2147483648'
// assert int(-2147483648).str() == '-2147483648'
assert i64(1).str() == '1'
assert i64(-1).str() == '-1'
assert u16(1).str() == '1'
// assert u16(-1).str() == '65535'
assert u32(1).str() == '1'
// assert u32(-1).str() == '4294967295'
assert u64(1).str() == '1'
// assert u64(-1).str() == '18446744073709551615'
}
fn test_and_precendence() {
assert (2 & 0 == 0) == ((2 & 0) == 0)
assert (2 & 0 != 0) == ((2 & 0) != 0)
assert (0 & 0 >= 0) == ((0 & 0) >= 0)
assert (0 & 0 <= 0) == ((0 & 0) <= 0)
assert (0 & 0 < 1) == ((0 & 0) < 1)
assert (1 & 2 > 0) == ((1 & 2) > 0)
}
fn test_or_precendence() {
assert (1 | 0 == 0) == ((1 | 0) == 0)
assert (1 | 0 != 1) == ((1 | 0) != 1)
assert (1 | 0 >= 2) == ((1 | 0) >= 2)
assert (1 | 0 <= 0) == ((1 | 0) <= 0)
assert (1 | 0 < 0) == ((1 | 0) < 0)
assert (1 | 0 > 1) == ((1 | 0) > 1)
}
fn test_xor_precendence() {
assert (1 ^ 0 == 2) == ((1 ^ 0) == 2)
assert (1 ^ 0 != 2) == ((1 ^ 0) != 2)
assert (1 ^ 0 >= 0) == ((1 ^ 0) >= 0)
assert (1 ^ 0 <= 1) == ((1 ^ 0) <= 1)
assert (1 ^ 0 < 0) == ((1 ^ 0) < 0)
assert (1 ^ 0 > 1) == ((1 ^ 0) > 1)
}
fn test_left_shift_precendence() {
assert (2 << 4 | 3) == ((2 << 4) | 3)
assert (2 << 4 | 3) != (2 << (4 | 3))
}
fn test_right_shift_precendence() {
assert (256 >> 4 | 3) == ((256 >> 4) | 3)
assert (256 >> 4 | 3) != (256 >> (4 | 3))
}
fn test_i8_print() {
b := i8(0)
println(b)
c := i16(7)
println(c)
d := u16(6)
println(d)
assert true
}
/*
fn test_cmp() {
assert 1 2
assert 1 2
assert 1 0
}
*/
type MyInt = int
fn test_int_alias() {
i := MyInt(2)
assert i + 10 == 12
}
fn test_hex() {
x := u64(10)
assert x.hex() == 'a'
b := 1234
assert b.hex() == '4d2'
b1 := -1
// assert b1.hex() == 'ffffffff'
// unsigned tests
// assert u8(12).hex() == '0c'
// assert u8(255).hex() == 'ff'
assert u16(65535).hex() == 'ffff'
// assert u32(-1).hex() == 'ffffffff'
// assert u64(-1).hex() == 'ffffffffffffffff'
// signed tests
// assert i8(-1).hex() == 'ff'
assert i8(12).hex() == 'c'
assert i16(32767).hex() == '7fff'
assert int(2147483647).hex() == '7fffffff'
assert i64(9223372036854775807).hex() == '7fffffffffffffff'
}
fn test_bin() {
x1 := 0b10
assert x1 == 2
x2 := 0b10101010
assert x2 == 0xAA
x3 := -0b0000001
assert x3 == -1
x4 := 0b11111111
assert x4 == 255
x5 := byte(0b11111111)
assert x5 == 255
x6 := char(0b11111111)
assert int(x6) == -1
x7 := 0b0
assert x7 == 0
x8 := -0b0
assert x8 == 0
}
fn test_oct() {
x1 := 0o12
assert x1 == 10
x2 := 0o350
assert x2 == 232
x3 := 0o00073
assert x3 == 59
x4 := 0
assert x4 == 0
x5 := 195
assert x5 == 195
x6 := -0o744
assert x6 == -484
x7 := -0o000042
assert x7 == -34
x8 := -112
assert x8 == -112
x9 := -0
assert x9 == 0
}
fn test_num_separator() {
// int
assert 100_000_0 == 1000000
assert -2_23_4_6 == -22346
// bin
assert 0b0_11 == 3
assert -0b0_100 == -4
// oct
assert 0o1_73 == 123
assert -0o17_5 == -125
assert -0o175 == -125
// hex
assert 0xFF == 255
assert 0xF_F == 255
// f32 or f64
assert 312_2.55 == 3122.55
assert 312_2.55 == 3122.55
}
fn test_int_decl() {
x1 := 0
x2 := 1333
x3 := -88955
x4 := 2000000000
x5 := -1999999999
assert typeof(x1).name == 'int'
assert typeof(x2).name == 'int'
assert typeof(x3).name == 'int'
assert typeof(x4).name == 'int'
assert typeof(x5).name == 'int'
x7 := u64(-321314588900011)
assert typeof(x7).name == 'u64'
}
fn test_int_to_hex() {
// array hex
/*
st := [byte(`V`), `L`, `A`, `N`, `G`]
assert st.hex() == '564c414e47'
assert st.hex().len == 10
st1 := [byte(0x41)].repeat(100)
assert st1.hex() == '41'.repeat(100)*/
// --- int to hex tests
c0 := 12
// 8Bit
assert byte(0).hex() == '0'
assert byte(c0).hex() == 'c'
assert i8(c0).hex() == 'c'
assert byte(127).hex() == '7f'
assert i8(127).hex() == '7f'
assert byte(255).hex() == 'ff'
// assert byte(-1).hex() == 'ff'
// 16bit
assert u16(0).hex() == '0'
assert i16(c0).hex() == 'c'
assert u16(c0).hex() == 'c'
assert i16(32767).hex() == '7fff'
assert u16(32767).hex() == '7fff'
// assert i16(-1).hex() == 'ffff'
assert u16(65535).hex() == 'ffff'
// 32bit
assert u32(0).hex() == '0'
assert c0.hex() == 'c'
assert u32(c0).hex() == 'c'
assert 2147483647.hex() == '7fffffff'
assert u32(2147483647).hex() == '7fffffff'
// assert (-1).hex() == 'ffffffffffffffff'
assert u32(4294967295).hex() == 'ffffffff'
// 64 bit
assert u64(0).hex() == '0'
assert i64(c0).hex() == 'c'
assert u64(c0).hex() == 'c'
assert i64(9223372036854775807).hex() == '7fffffffffffffff'
assert u64(9223372036854775807).hex() == '7fffffffffffffff'
// assert i64(-1).hex() == 'ffffffffffffffff'
assert u64(18446744073709551615).hex() == 'ffffffffffffffff'
}
fn test_repeat() {
b := byte(`V`)
assert b.repeat(5) == 'VVVVV'
assert b.repeat(1) == b.ascii_str()
assert b.repeat(0) == ''
}

View File

@ -25,3 +25,5 @@ pub fn (m &map) free() {}
#res += '}'
#return res;
#}
#map.prototype.getOrSet = function (key, init) { if (this.map.has(key)) { return this.map.get(key); } else { this.map.set(key,init); return init; } }

View File

@ -0,0 +1,949 @@
import rand
const (
strings = unique_strings(200, 10)
)
fn unique_strings(arr_len int, str_len int) []string {
mut arr := []string{cap: arr_len}
for arr.len < arr_len {
str := rand.string(str_len)
if str !in arr {
arr << str
}
}
return arr
}
fn test_get_and_set_many() {
mut m := map[string]int{}
for i, s in strings {
m[s] = i
assert m[s] == i
assert m.len == i + 1
}
for i, s in strings {
assert m[s] == i
}
assert m.len == strings.len
}
fn test_for_in_many() {
mut m := map[string]int{}
for i, s in strings {
m[s] = i
}
for k, v in m {
assert m[k] == v
}
}
fn test_keys_many() {
mut m := map[string]int{}
for i, s in strings {
m[s] = i
}
keys := m.keys()
assert keys.len == strings.len
assert keys.len == m.len
assert keys == strings
}
fn test_deletes_many() {
mut m := map[string]int{}
for i, s in strings {
m[s] = i
}
for i, s in strings {
m.delete(s)
assert m[s] == 0
assert m.len == strings.len - (i + 1)
}
assert m.len == 0
assert m.keys().len == 0
}
struct User {
mut:
name string
}
struct Aaa {
mut:
m map[string]int
users map[string]User
}
fn (mut a Aaa) set(key string, val int) {
a.m[key] = val
}
fn test_map() {
mut m := map[string]int{}
assert m.len == 0
m['hi'] = 80
m['hello'] = 101
assert m['hi'] == 80
assert m['hello'] == 101
assert m.len == 2
assert 'hi' in m
mut sum := 0
// Test `for in`
for _, val in m {
sum += val
}
assert sum == 80 + 101
// Test `.keys()`
keys := m.keys()
assert keys.len == 2
assert 'hi' in keys
assert 'hello' in keys
m.delete('hi')
assert m.len == 1
m.delete('aloha')
assert m.len == 1
assert m['hi'] == 0
assert m.keys().len == 1
assert m.keys()[0] == 'hello'
// //
mut users := map[string]User{}
users['1'] = User{'Peter'}
peter := users['1']
assert peter.name == 'Peter'
mut a := Aaa{
m: map[string]int{}
users: map[string]User{}
}
a.users['Bob'] = User{'Bob'}
q := a.users['Bob']
assert q.name == 'Bob'
// test struct field change
a.users['Bob'].name = 'bob'
q2 := a.users['Bob']
assert q2.name == 'bob'
a.m['one'] = 1
a.set('two', 2)
assert a.m['one'] == 1
assert a.m['two'] == 2
}
fn test_map_init() {
one := 'one'
three := 'three'
m := {
one: 1
'two': 2
three: 1 + 2
}
assert m['one'] == 1
assert m['two'] == 2
assert m['three'] == 3
assert m['unknown'] == 0
}
fn test_string_map() {
// m := map[string]Fn
}
fn test_large_map() {
// ticks := time.ticks()
mut nums := map[string]int{}
n := 30 * 1000
for i in 0 .. n {
key := i.str()
nums[key] = i
}
assert nums['1'] == 1
assert nums['999'] == 999
assert nums['1000000'] == 0
// println(time.ticks() - ticks)
}
fn test_various_map_value() {
mut m1 := map[string]int{}
m1['test'] = 1
assert m1['test'] == 1
mut m2 := map[string]string{}
m2['test'] = 'test'
assert m2['test'] == 'test'
mut m3 := map[string]i8{}
m3['test'] = i8(0)
assert m3['test'] == i8(0)
mut m4 := map[string]i16{}
m4['test'] = i16(0)
assert m4['test'] == i16(0)
mut m7 := map[string]u16{}
m7['test'] = u16(0)
assert m7['test'] == u16(0)
mut m8 := map[string]u32{}
m8['test'] = u32(0)
assert m8['test'] == u32(0)
mut m9 := map[string]bool{}
m9['test'] = true
assert m9['test'] == true
mut m10 := map[string]byte{}
m10['test'] = byte(0)
assert m10['test'] == byte(0)
mut m11 := map[string]f32{}
m11['test'] = f32(0.0)
assert m11['test'] == f32(0.0)
mut m12 := map[string]f64{}
m12['test'] = f64(0.0)
assert m12['test'] == f64(0.0)
// mut m13 := map[string]rune
// m13['test'] = rune(0)
// assert m13['test'] == rune(0)
// todo(playX): pointer equality does not work yet
/*
mut m14 := map[string]voidptr{}
m14['test'] = voidptr(0)
assert m14['test'] == voidptr(0)
mut m15 := map[string]&byte{}
m15['test'] = &byte(0)
assert m15['test'] == &byte(0)
mut m16 := map[string]i64{}
m16['test'] = i64(0)
assert m16['test'] == i64(0)
mut m17 := map[string]u64{}
m17['test'] = u64(0)
assert m17['test'] == u64(0)
mut m18 := map[string]&int{}
m18['test'] = &int(0)
assert m18['test'] == &int(0)*/
}
fn test_string_arr() {
mut m := map[string][]string{}
m['a'] = ['one', 'two']
assert m['a'].len == 2
assert m['a'][0] == 'one'
assert m['a'][1] == 'two'
}
fn mut_map(mut m map[string]int) {
m['a'] = 10
}
fn test_mut_arg() {
mut m := map[string]int{}
mut_map(mut m)
a := m['a']
assert a == 10
}
fn test_delete() {
mut m := map[string]int{}
m['one'] = 1
m['two'] = 2
println(m['two']) // => "2"
m.delete('two')
println(m['two'].str()) // => 0
assert ('two' in m) == false
println('two' in m) // => true, on Linux and Windows <-- wrong !
}
fn test_delete_size() {
arr := ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
mut m := map[string]int{}
for _ in 0 .. 10 {
for i in 0 .. 10 {
m[arr[i]] = i
}
assert m.len == 10
println(m.len)
for i in 0 .. 10 {
m.delete(arr[i])
}
}
}
fn test_nested_for_in() {
mut m := map[string]int{}
for i in 0 .. 1000 {
m[i.str()] = i
}
mut i := 0
for key1, _ in m {
assert key1 == i.str()
i++
mut j := 0
for key2, _ in m {
assert key2 == j.str()
j++
}
}
}
fn test_delete_in_for_in() {
mut m := map[string]string{}
for i in 0 .. 1000 {
m[i.str()] = i.str()
}
mut i := 0
for key, _ in m {
assert key == i.str()
m.delete(key)
i++
}
assert m.str() == '{}'
assert m.len == 0
}
fn test_set_in_for_in() {
mut m := map[string]string{}
for i in 0 .. 10 {
m[i.str()] = i.str()
}
mut last_key := ''
mut i := 0
for key, _ in m {
m['10'] = '10'
assert key == i.str()
last_key = key
i++
}
assert last_key == '10'
}
fn test_delete_and_set_in_for_in() {
mut m := map[string]string{}
for i in 0 .. 1000 {
m[i.str()] = i.str()
}
mut i := 0
for key, _ in m {
assert key == i.str()
m.delete(key)
m[key] = i.str()
if i == 999 {
break
}
i++
}
assert m.len == 1000
i = 0
for key, _ in m {
assert m[key] == i.str()
i++
}
assert i == 1000
}
struct Mstruct1 {
pub mut:
mymap map[string]int
}
struct Mstruct2 {
pub mut:
mymap map[string]f64
}
struct Mstruct3 {
pub mut:
mymap map[string]u16
}
fn test_map_assign() {
mut a := map[string]f64{}
mut b := map[string]int{}
mut c := map[string]u16{}
a = {
'x': 12.4
'y': 3
}
b = {
'u': -13
'v': 12
}
c = {
's': u16(5)
't': 3
}
_ := Mstruct1{{
'p': 12
}}
_ := Mstruct2{{
'q': 1.7
}}
_ := Mstruct3{{
'r': u16(6)
's': 5
}}
}
fn test_postfix_op_directly() {
mut a := map[string]int{}
a['aaa']++
assert a['aaa'] == 1
a['aaa']++
assert a['aaa'] == 2
a['bbb']--
assert a['bbb'] == -1
a['bbb']--
assert a['bbb'] == -2
}
fn test_map_push_directly() {
mut a := map[string][]string{}
a['aaa'] << ['a', 'b', 'c']
assert a['aaa'].len == 3
assert a['aaa'] == ['a', 'b', 'c']
}
fn test_assign_directly() {
mut a := map[string]int{}
a['aaa'] += 4
assert a['aaa'] == 4
a['aaa'] -= 2
assert a['aaa'] == 2
}
fn test_map_in_directly() {
for k, v in {
'aa': 1
} {
assert k == 'aa'
assert v == 1
}
}
fn test_plus_assign_string() {
mut m := {
'one': ''
}
m['one'] += '1'
assert m.len == 1
assert m['one'] == '1'
}
fn test_map_keys_to_array() {
m := {
'a': 'b'
'c': 'd'
}
mut arr := []string{}
for k, _ in m {
arr << k
}
sarr := arr.str()
println(sarr)
assert sarr == "['a', 'c']"
}
fn map_in_mut(mut m map[string]int) {
if 'one' in m {
m['one'] = 2
}
}
fn test_map_in_mut() {
mut m := {
'one': 1
}
map_in_mut(mut m)
assert m['one'] == 2
}
fn test_map_in() {
m := {
'Foo': 'bar'
}
if 'foo'.capitalize() in m {
println('ok')
} else {
assert false
}
}
fn mut_map_with_relation_op_in_fn(mut m map[string]int) {
if m['one'] == 1 {
m['three'] = 3
}
if m['two'] != 1 {
m['four'] = 4
}
if m['one'] > 0 {
m['five'] = 5
}
if m['one'] < 2 {
m['six'] = 6
}
if m['two'] >= 2 {
m['seven'] = 7
}
if m['two'] <= 2 {
m['eight'] = 8
}
}
fn test_mut_map_with_relation_op_in_fn() {
mut m := {
'one': 1
'two': 2
}
mut_map_with_relation_op_in_fn(mut m)
assert 'three' in m
assert 'four' in m
assert 'five' in m
assert 'six' in m
assert 'seven' in m
assert 'eight' in m
}
fn test_map_str_after_delete() {
mut m := {
'first': 1
'second': 2
'third': 3
}
osm := '$m'
m.delete('second')
nsm := '$m'
println('m: $m')
assert osm == "{'first': 1, 'second': 2, 'third': 3}"
assert nsm == "{'first': 1, 'third': 3}"
}
fn test_modify_map_value() {
mut m1 := {
'foo': 3
'bar': -7
}
m1['foo'] += 5
m1['bar'] *= -2
assert m1['foo'] == 8
assert m1['bar'] == 14
}
fn test_map_clone() {
mut nums := {
'foo': 1
'bar': 2
}
mut nums2 := nums.clone()
nums2['foo']++
nums2['bar'] *= 4
assert nums['foo'] == 1
assert nums['bar'] == 2
assert nums2['foo'] == 2
assert nums2['bar'] == 8
}
struct MValue {
name string
misc map[string]string
}
fn test_map_default_zero() {
m := map[string]MValue{}
v := m['unknown']
x := v.misc['x']
println(x)
assert x == ''
}
fn test_map_or() {
m := {
'first': 1
'second': 2
'third': 3
}
_ = m
// num := m['first'] or { return }
}
fn test_int_keys() {
mut m := map[int]int{}
m[3] = 9
m[4] = 16
assert m.len == 2
assert m[3] == 9
assert m[4] == 16
m[5] += 24
m[5]++
assert m[5] == 25
mut m2 := {
3: 9
4: 16
5: 25
}
four := 4
m2.delete(3)
m2.delete(four)
m2.delete(5)
assert m2.len == 0
assert m2[3] == 0
assert m2[4] == 0
assert m2[5] == 0
assert m2.keys() == []
m2 = {
3: 9
4: 16
5: 25
}
assert m2.len == 3
// clone
mc := m.clone()
same := mc == m
assert same
assert mc.len == 3
assert mc.keys() == [3, 4, 5]
mut all := []int{}
for k, v in mc {
assert m[k] == v
all << k
all << v
}
assert all == [3, 9, 4, 16, 5, 25]
mut m3 := {
1: 'one'
2: 'two'
}
assert m3[1] == 'one'
m3.delete(1)
}
enum Color {
red
green
blue
}
type ColorAlias = Color
fn test_alias_enum() {
mut m := map[ColorAlias]string{}
m[Color.red] = 'hi'
assert m[Color.red] == 'hi'
}
fn test_enum_in_map() {
mut m := map[Color]string{}
m[Color.red] = 'hi'
assert Color.red in m
assert Color.green !in m
assert Color.blue !in m
}
fn test_voidptr_keys() {
mut m := map[voidptr]string{}
v := 5
m[&v] = 'var'
m[&m] = 'map'
assert m[&v] == 'var'
assert m[&m] == 'map'
assert m.len == 2
}
fn test_rune_keys() {
mut m := {
`!`: 2
`%`: 3
}
assert typeof(m).name == 'map[rune]int'
assert m[`!`] == 2
m[`@`] = 7
assert m.len == 3
println(m)
assert '$m' == '{`!`: 2, `%`: 3, `@`: 7}'
mut a := []rune{}
for k, v in m {
a << k
a << rune(v) + `0`
}
assert a == [`!`, `2`, `%`, `3`, `@`, `7`]
}
fn test_eq() {
a := {
'a': 1
'b': 2
}
assert a == {
'a': 1
'b': 2
}
b := {
'a': [[1]]
'b': [[2]]
}
assert b == {
'a': [[1]]
'b': [[2]]
}
c := {
'a': {
'11': 1
}
'b': {
'22': 2
}
}
assert c == {
'a': {
'11': 1
}
'b': {
'22': 2
}
}
d := {
'a': MValue{
name: 'aa'
misc: {
'11': '1'
}
}
'b': MValue{
name: 'bb'
misc: {
'22': '2'
}
}
}
assert d == {
'a': MValue{
name: 'aa'
misc: {
'11': '1'
}
}
'b': MValue{
name: 'bb'
misc: {
'22': '2'
}
}
}
}
fn test_non_string_key_map_str() {
assert {
23: 4
}.str() == '{23: 4}'
assert {
`a`: 12
`b`: 13
}.str() == '{`a`: 12, `b`: 13}'
assert {
23: 'foo'
25: 'bar'
}.str() == "{23: 'foo', 25: 'bar'}"
}
fn test_map_assign_empty_map_init() {
mut a := {
'one': 1
}
a = {}
println(a)
assert a == map[string]int{}
assert '$a' == '{}'
}
fn test_in_map_literal() {
assert 1 in {
1: 'one'
}
}
fn test_byte_keys() {
mut m := map[byte]byte{}
byte_max := byte(255)
for i in byte(0) .. byte_max {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in byte(0) .. 100 {
m[i]++
assert m[i] == i + 1
}
assert m.len == byte_max
keys := m.keys()
for i in byte(0) .. byte_max {
assert keys[i] == i
}
for i in byte(0) .. byte_max {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_i16_keys() {
mut m := map[i16]i16{}
end := i16(1000)
for i in i16(0) .. end {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in i16(0) .. 500 {
m[i]++
assert m[i] == i + 1
}
assert m.len == end
keys := m.keys()
for i in i16(0) .. end {
assert keys[i] == i
}
for i in i16(0) .. end {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_u16_keys() {
mut m := map[u16]u16{}
end := u16(1000)
for i in u16(0) .. end {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in u16(0) .. 500 {
m[i]++
assert m[i] == i + 1
}
assert m.len == end
keys := m.keys()
for i in u16(0) .. end {
assert keys[i] == i
}
for i in u16(0) .. end {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_u32_keys() {
mut m := map[u32]u32{}
end := u32(1000)
for i in u32(0) .. end {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in u32(0) .. 500 {
m[i]++
assert m[i] == i + 1
}
assert m.len == end
keys := m.keys()
for i in u32(0) .. end {
assert keys[i] == i
}
for i in u32(0) .. end {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_int_keys2() {
mut m := map[int]int{}
end := 1000
for i in int(0) .. end {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in int(0) .. 500 {
m[i]++
assert m[i] == i + 1
}
assert m.len == end
keys := m.keys()
for i in int(0) .. end {
assert keys[i] == i
}
for i in int(0) .. end {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_i64_keys() {
mut m := map[i64]i64{}
end := i64(1000)
for i in i64(0) .. end {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in i64(0) .. 500 {
m[i]++
assert m[i] == i + 1
}
assert m.len == end
keys := m.keys()
for i in i64(0) .. end {
assert keys[i] == i
}
for i in i64(0) .. end {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_u64_keys() {
mut m := map[u64]u64{}
end := u64(1000)
for i in u64(0) .. end {
m[i] = i
assert m[i] == i
}
for k, v in m {
assert k == v
}
for i in u64(0) .. 500 {
m[i]++
assert m[i] == i + 1
}
assert m.len == end
keys := m.keys()
for i in u64(0) .. end {
assert keys[i] == i
}
for i in u64(0) .. end {
m.delete(i)
assert m[i] == 0
}
assert m.len == 0
}
fn test_map_set_fixed_array_variable() {
mut m := map[string][2]f64{}
m['A'] = [1.1, 2.2]!
println(m)
assert '$m' == "{'A': [1.1, 2.2]}"
mut m2 := map[string][2]f64{}
arr := [1.1, 2.2]!
m2['A'] = arr
println(m2)
assert '$m2' == "{'A': [1.1, 2.2]}"
}

View File

@ -10,6 +10,10 @@ pub fn (s string) slice(a int, b int) string {
return string(s.str.slice(a, b))
}
pub fn (s string) substr(start int, end int) string {
return s.slice(start, end)
}
pub fn (s string) after(dot string) string {
return string(s.str.slice(s.str.lastIndexOf(dot.str) + 1, int(s.str.length)))
}
@ -20,20 +24,37 @@ pub fn (s string) after_char(dot byte) string {
}
pub fn (s string) all_after(dot string) string {
return string(s.str.slice(s.str.indexOf(dot.str) + 1, int(s.str.length)))
pos := if dot.len == 0 { -1 } else { s.str.indexOf(dot.str) }
if pos == -1 {
return s.clone()
}
return s[pos + dot.len..]
}
// why does this exist?
pub fn (s string) all_after_last(dot string) string {
return s.after(dot)
pos := if dot.len == 0 { -1 } else { s.str.lastIndexOf(dot.str) }
if pos == -1 {
return s.clone()
}
return s[pos + dot.len..]
}
pub fn (s string) all_before(dot string) string {
return string(s.str.slice(0, s.str.indexOf(dot.str)))
pos := if dot.len == 0 { -1 } else { s.str.indexOf(dot.str) }
if pos == -1 {
return s.clone()
}
return s[..pos]
// return string(s.str.slice(0, s.str.indexOf(dot.str)))
}
pub fn (s string) all_before_last(dot string) string {
return string(s.str.slice(0, s.str.lastIndexOf(dot.str)))
pos := if dot.len == 0 { -1 } else { s.str.lastIndexOf(dot.str) }
if pos == -1 {
return s.clone()
}
return s[..pos]
}
pub fn (s string) bool() bool {
@ -79,6 +100,9 @@ pub fn (s string) contains_any(chars string) bool {
}
pub fn (s string) contains_any_substr(chars []string) bool {
if chars.len == 0 {
return true
}
for x in chars {
if s.str.includes(x.str) {
return true
@ -726,3 +750,131 @@ pub fn (s string) replace_once(rep string, with_ string) string {
return s2
}
pub fn (s string) title() string {
words := s.split(' ')
mut tit := []string{}
for word in words {
tit << word.capitalize()
}
title := tit.join(' ')
return title
}
// index_any returns the position of any of the characters in the input string - if found.
pub fn (s string) index_any(chars string) int {
for i, ss in s {
for c in chars {
if c == ss {
return i
}
}
}
return -1
}
/*
// limit returns a portion of the string, starting at `0` and extending for a given number of characters afterward.
// 'hello'.limit(2) => 'he'
// 'hi'.limit(10) => 'hi'
pub fn (s string) limit(max int) string {
u := s.runes()
if u.len <= max {
return s.clone()
}
return u[0..max].string()
}
*/
// is_title returns true if all words of the string is capitalized.
// Example: assert 'Hello V Developer'.is_title() == true
pub fn (s string) is_title() bool {
words := s.split(' ')
for word in words {
if !word.is_capital() {
return false
}
}
return true
}
// is_capital returns `true` if the first character in the string is a capital letter.
// Example: assert 'Hello'.is_capital() == true
[direct_array_access]
pub fn (s string) is_capital() bool {
if s.len == 0 || !(s[0] >= `A` && s[0] <= `Z`) {
return false
}
for i in 1 .. s.len {
if s[i] >= `A` && s[i] <= `Z` {
return false
}
}
return true
}
// is_upper returns `true` if all characters in the string is uppercase.
// Example: assert 'HELLO V'.is_upper() == true
pub fn (s string) is_upper() bool {
res := false
#res.val = s.str == s.str.toUpperCase() && s.str != s.str.toLowerCase()
return res
}
// is_upper returns `true` if all characters in the string is uppercase.
// Example: assert 'HELLO V'.is_upper() == true
pub fn (s string) is_lower() bool {
res := false
#res.val = s.str == s.str.toLowerCase() && s.str != s.str.toUpperCase()
return res
}
pub fn (s string) reverse() string {
res := ''
#res.str = [...s.str].reverse().join('')
return res
}
pub fn (s string) trim(cutset string) string {
if s.len < 1 || cutset.len < 1 {
return s.clone()
}
mut pos_left := 0
mut pos_right := s.len - 1
mut cs_match := true
for pos_left <= s.len && pos_right >= -1 && cs_match {
cs_match = false
for cs in cutset {
if s[pos_left] == cs {
pos_left++
cs_match = true
break
}
}
for cs in cutset {
if s[pos_right] == cs {
pos_right--
cs_match = true
break
}
}
if pos_left > pos_right {
return ''
}
}
return s.substr(pos_left, pos_right + 1)
}
pub fn (s []string) join(sep string) string {
mut res := ''
for i, str in s {
res += str
if i != s.len - 1 {
res += sep
}
}
return res
}

View File

@ -0,0 +1,897 @@
import strings
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
struct Foo {
bar int
mut:
str string
}
fn test_add() {
mut a := 'a'
a += 'b'
assert a == ('ab')
a = 'a'
for i := 1; i < 1000; i++ {
a += 'b'
}
assert a.len == 1000
assert a.ends_with('bbbbb')
a += '123'
assert a.ends_with('3')
}
fn test_ends_with() {
a := 'browser.v'
assert a.ends_with('.v')
s := 'V Programming Language'
assert s.ends_with('guage') == true
assert s.ends_with('Language') == true
assert s.ends_with('Programming Language') == true
assert s.ends_with('V') == false
}
fn test_between() {
s := 'hello [man] how you doing'
assert s.find_between('[', ']') == 'man'
}
fn test_compare() {
a := 'Music'
b := 'src'
assert b >= a
}
fn test_lt() {
a := ''
b := 'a'
c := 'a'
d := 'b'
e := 'aa'
f := 'ab'
assert a < b
assert !(b < c)
assert c < d
assert !(d < e)
assert c < e
assert e < f
}
fn test_ge() {
a := 'aa'
b := 'aa'
c := 'ab'
d := 'abc'
e := 'aaa'
assert b >= a
assert c >= b
assert d >= c
assert !(c >= d)
assert e >= a
}
fn test_compare_strings() {
a := 'aa'
b := 'aa'
c := 'ab'
d := 'abc'
e := 'aaa'
assert compare_strings(a, b) == 0
assert compare_strings(b, c) == -1
assert compare_strings(c, d) == -1
assert compare_strings(d, e) == 1
assert compare_strings(a, e) == -1
assert compare_strings(e, a) == 1
}
fn test_sort() {
mut vals := [
'arr',
'an',
'a',
'any',
]
len := vals.len
vals.sort()
assert len == vals.len
assert vals[0] == 'a'
assert vals[1] == 'an'
assert vals[2] == 'any'
assert vals[3] == 'arr'
}
fn test_sort_reverse() {
mut vals := [
'arr',
'an',
'a',
'any',
]
len := vals.len
vals.sort(b > a)
assert len == vals.len
assert vals[0] == 'a'
assert vals[1] == 'an'
assert vals[2] == 'any'
assert vals[3] == 'arr'
}
fn test_split_nth() {
a := '1,2,3'
assert a.split(',').len == 3
assert a.split_nth(',', -1).len == 3
assert a.split_nth(',', 0).len == 3
assert a.split_nth(',', 1).len == 1
assert a.split_nth(',', 2).len == 2
assert a.split_nth(',', 10).len == 3
b := '1::2::3'
assert b.split('::').len == 3
assert b.split_nth('::', -1).len == 3
assert b.split_nth('::', 0).len == 3
assert b.split_nth('::', 1).len == 1
assert b.split_nth('::', 2).len == 2
assert b.split_nth('::', 10).len == 3
c := 'ABCDEF'
println(c.split('').len)
assert c.split('').len == 6
assert c.split_nth('', 3).len == 3
assert c.split_nth('BC', -1).len == 2
d := ','
assert d.split(',').len == 2
assert d.split_nth('', 3).len == 1
assert d.split_nth(',', -1).len == 2
assert d.split_nth(',', 3).len == 2
e := ',,,0,,,,,a,,b,'
assert e.split(',,').len == 5
assert e.split_nth(',,', 3).len == 3
assert e.split_nth(',', -1).len == 12
assert e.split_nth(',', 3).len == 3
}
fn test_split_nth_values() {
line := 'CMD=eprintln(phase=1)'
a0 := line.split_nth('=', 0)
assert a0.len == 3
assert a0[0] == 'CMD'
assert a0[1] == 'eprintln(phase'
assert a0[2] == '1)'
a1 := line.split_nth('=', 1)
assert a1.len == 1
assert a1[0] == 'CMD=eprintln(phase=1)'
a2 := line.split_nth('=', 2)
assert a2.len == 2
assert a2[0] == 'CMD'
assert a2[1] == 'eprintln(phase=1)'
a3 := line.split_nth('=', 3)
assert a3.len == 3
assert a3[0] == 'CMD'
assert a3[1] == 'eprintln(phase'
assert a3[2] == '1)'
a4 := line.split_nth('=', 4)
assert a4.len == 3
assert a4[0] == 'CMD'
assert a4[1] == 'eprintln(phase'
assert a4[2] == '1)'
}
fn test_split() {
mut s := 'volt/twitch.v:34'
mut vals := s.split(':')
assert vals.len == 2
assert vals[0] == 'volt/twitch.v'
assert vals[1] == '34'
// /////////
s = '2018-01-01z13:01:02'
vals = s.split('z')
assert vals.len == 2
assert vals[0] == '2018-01-01'
assert vals[1] == '13:01:02'
// //////////
s = '4627a862c3dec29fb3182a06b8965e0025759e18___1530207969___blue'
vals = s.split('___')
assert vals.len == 3
assert vals[0] == '4627a862c3dec29fb3182a06b8965e0025759e18'
assert vals[1] == '1530207969'
assert vals[2] == 'blue'
// /////////
s = 'lalala'
vals = s.split('a')
assert vals.len == 4
assert vals[0] == 'l'
assert vals[1] == 'l'
assert vals[2] == 'l'
assert vals[3] == ''
// /////////
s = 'awesome'
a := s.split('')
assert a.len == 7
assert a[0] == 'a'
assert a[1] == 'w'
assert a[2] == 'e'
assert a[3] == 's'
assert a[4] == 'o'
assert a[5] == 'm'
assert a[6] == 'e'
// /////////
s = 'wavy turquoise bags'
vals = s.split(' bags')
assert vals.len == 2
assert vals[0] == 'wavy turquoise'
assert vals[1] == ''
}
/*
fn test_trim_space() {
a := ' a '
assert a.trim_space() == 'a'
code := '
fn main() {
println(2)
}
'
code_clean := 'fn main() {
println(2)
}'
assert code.trim_space() == code_clean
}*/
/*
fn test_join() {
mut strings := ['a', 'b', 'c']
mut s := strings.join(' ')
assert s == 'a b c'
strings = [
'one
two ',
'three!
four!',
]
s = strings.join(' ')
assert s.contains('one') && s.contains('two ') && s.contains('four')
empty := []string{len: 0}
assert empty.join('A') == ''
}*/
fn test_clone() {
mut a := 'a'
a += 'a'
a += 'a'
b := a
c := a.clone()
assert c == a
assert c == 'aaa'
assert b == 'aaa'
}
fn test_replace() {
a := 'hello man!'
mut b := a.replace('man', 'world')
assert b == ('hello world!')
b = b.replace('!', '')
assert b == ('hello world')
b = b.replace('h', 'H')
assert b == ('Hello world')
b = b.replace('foo', 'bar')
assert b == ('Hello world')
s := 'hey man how are you'
assert s.replace('man ', '') == 'hey how are you'
lol := 'lol lol lol'
assert lol.replace('lol', 'LOL') == 'LOL LOL LOL'
b = 'oneBtwoBBthree'
assert b.replace('B', '') == 'onetwothree'
b = '*charptr'
assert b.replace('charptr', 'byteptr') == '*byteptr'
c := 'abc'
println(c.replace('', '-'))
// assert c.replace('', '-') == c
v := 'a b c d'
assert v.replace(' ', ' ') == 'a b c d'
}
fn test_replace_each() {
s := 'hello man man :)'
q := s.replace_each([
'man',
'dude',
'hello',
'hey',
])
assert q == 'hey dude dude :)'
bb := '[b]bold[/b] [code]code[/code]'
assert bb.replace_each([
'[b]',
'<b>',
'[/b]',
'</b>',
'[code]',
'<code>',
'[/code]',
'</code>',
]) == '<b>bold</b> <code>code</code>'
bb2 := '[b]cool[/b]'
assert bb2.replace_each([
'[b]',
'<b>',
'[/b]',
'</b>',
]) == '<b>cool</b>'
t := 'aaaaaaaa'
y := t.replace_each([
'aa',
'b',
])
assert y == 'bbbb'
s2 := 'hello_world hello'
assert s2.replace_each(['hello_world', 'aaa', 'hello', 'bbb']) == 'aaa bbb'
}
fn test_itoa() {
num := 777
assert num.str() == '777'
big := 7779998
assert big.str() == '7779998'
a := 3
assert a.str() == '3'
b := 5555
assert b.str() == '5555'
zero := 0
assert zero.str() == '0'
neg := -7
assert neg.str() == '-7'
}
fn test_reassign() {
a := 'hi'
mut b := a
b += '!'
assert a == 'hi'
assert b == 'hi!'
}
/*
fn test_runes() {
s := 'привет'
assert s.len == 12
s2 := 'privet'
assert s2.len == 6
u := s.runes()
assert u.len == 6
assert s2.substr(1, 4).len == 3
assert s2.substr(1, 4) == 'riv'
assert s2[1..4].len == 3
assert s2[1..4] == 'riv'
assert s2[..4].len == 4
assert s2[..4] == 'priv'
assert s2[2..].len == 4
assert s2[2..] == 'ivet'
assert u[1..4].string().len == 6
assert u[1..4].string() == 'рив'
assert s2.substr(1, 2) == 'r'
assert u[1..2].string() == 'р'
assert s2.runes()[1] == `r`
assert u[1] == `р`
first := u[0]
last := u[u.len - 1]
assert first.str().len == 2
assert last.str().len == 2
}*/
fn test_contains() {
s := 'view.v'
assert s.contains('vi')
assert !s.contains('random')
assert ''.contains('')
assert 'abc'.contains('')
}
fn test_contains_any() {
assert !'team'.contains_any('i')
assert 'fail'.contains_any('ui')
assert 'ure'.contains_any('ui')
assert 'failure'.contains_any('ui')
assert !'foo'.contains_any('')
assert !''.contains_any('')
}
fn test_contains_any_substr() {
s := 'Some random text'
assert s.contains_any_substr(['false', 'not', 'rand'])
assert !s.contains_any_substr(['ABC', 'invalid'])
assert ''.contains_any_substr([])
assert 'abc'.contains_any_substr([''])
}
fn test_arr_contains() {
a := ['a', 'b', 'c']
assert a.contains('b')
ints := [1, 2, 3]
assert ints.contains(2)
}
/*
fn test_to_num() {
s := '7'
assert s.int() == 7
assert s.byte() == 7
assert s.u64() == 7
f := '71.5 hasdf'
// QTODO
assert f.f32() == 71.5
vals := ['9']
assert vals[0].int() == 9
big := '93993993939322'
assert big.u64() == 93993993939322
assert big.i64() == 93993993939322
}*/
/*
fn test_inter_format_string() {
float_num := 1.52345
float_num_string := '-${float_num:.3f}-'
//assert float_num_string == '-1.523-'
int_num := 7
int_num_string := '-${int_num:03d}-'
//assert int_num_string == '-007-'
ch := `a`
ch_string := '-${ch:c}-'
//assert ch_string == '-a-'
hex_n := 192
hex_n_string := '-${hex_n:x}-'
assert hex_n_string == '-c0-'
oct_n := 192
oct_n_string := '-${oct_n:o}-'
assert oct_n_string == '-300-'
str := 'abc'
str_string := '-${str:s}-'
assert str_string == '-abc-'
}*/
/*
fn test_hash() {
s := '10000'
assert s.hash() == 46730161
s2 := '24640'
assert s2.hash() == 47778736
s3 := 'Content-Type'
assert s3.hash() == 949037134
s4 := 'bad_key'
assert s4.hash() == -346636507
s5 := '24640'
// From a map collision test
assert s5.hash() % ((1 << 20) - 1) == s.hash() % ((1 << 20) - 1)
assert s5.hash() % ((1 << 20) - 1) == 592861
}*/
fn test_trim() {
assert 'banana'.trim('bna') == ''
assert 'abc'.trim('ac') == 'b'
assert 'aaabccc'.trim('ac') == 'b'
}
fn test_trim_left() {
mut s := 'module main'
assert s.trim_left(' ') == 'module main'
s = ' module main'
assert s.trim_left(' ') == 'module main'
// test cutset
s = 'banana'
assert s.trim_left('ba') == 'nana'
assert s.trim_left('ban') == ''
}
fn test_trim_right() {
mut s := 'module main'
assert s.trim_right(' ') == 'module main'
s = 'module main '
assert s.trim_right(' ') == 'module main'
// test cutset
s = 'banana'
assert s.trim_right('na') == 'b'
assert s.trim_right('ban') == ''
}
fn test_all_before() {
s := 'fn hello fn'
assert s.all_before(' ') == 'fn'
assert s.all_before('2') == s
assert s.all_before('') == s
}
fn test_all_before_last() {
s := 'fn hello fn'
assert s.all_before_last(' ') == 'fn hello'
assert s.all_before_last('2') == s
assert s.all_before_last('') == s
}
fn test_all_after() {
s := 'fn hello'
assert s.all_after('fn ') == 'hello'
assert s.all_after('test') == s
assert s.all_after('') == s
assert s.after('e') == 'llo'
x := s.after('e')
assert x == 'llo'
}
fn test_reverse() {
println('hello'.reverse())
assert 'hello'.reverse() == 'olleh'
assert ''.reverse() == ''
assert 'a'.reverse() == 'a'
}
fn test_count() {
assert ''.count('') == 0
assert ''.count('a') == 0
assert 'a'.count('') == 0
assert 'aa'.count('a') == 2
assert 'aa'.count('aa') == 1
assert 'aabbaa'.count('aa') == 2
assert 'bbaabb'.count('aa') == 1
}
fn test_lower() {
mut s := 'A'
assert !s.is_lower()
assert s.to_lower() == 'a'
assert s.to_lower().len == 1
s = 'HELLO'
assert !s.is_lower()
assert s.to_lower() == 'hello'
assert s.to_lower().len == 5
s = 'Aloha'
assert !s.is_lower()
assert s.to_lower() == 'aloha'
s = 'Have A nice Day!'
assert !s.is_lower()
assert s.to_lower() == 'have a nice day!'
s = 'hi'
assert s.is_lower()
assert s.to_lower() == 'hi'
assert 'aloha!'[0] == `a`
assert 'aloha!'[5] == `!`
}
fn test_upper() {
mut s := 'a'
assert !s.is_upper()
assert s.to_upper() == 'A'
assert s.to_upper().len == 1
s = 'hello'
assert !s.is_upper()
assert s.to_upper() == 'HELLO'
assert s.to_upper().len == 5
s = 'Aloha'
assert !s.is_upper()
assert s.to_upper() == 'ALOHA'
s = 'have a nice day!'
assert !s.is_upper()
assert s.to_upper() == 'HAVE A NICE DAY!'
s = 'HI'
assert s.is_upper()
assert s.to_upper() == 'HI'
}
fn test_capitalize() {
mut s := 'hello'
assert !s.is_capital()
assert s.capitalize() == 'Hello'
s = 'test'
assert !s.is_capital()
assert s.capitalize() == 'Test'
s = 'i am ray'
assert !s.is_capital()
assert s.capitalize() == 'I am ray'
s = ''
assert !s.is_capital()
assert s.capitalize() == ''
s = 'TEST IT'
assert !s.is_capital()
assert s.capitalize() == 'TEST IT'
s = 'Test it'
assert s.is_capital()
assert s.capitalize() == 'Test it'
assert 'GameMission_t'.capitalize() == 'GameMission_t'
}
fn test_title() {
mut s := 'hello world'
assert !s.is_title()
assert s.title() == 'Hello World'
s = 'HELLO WORLD'
assert !s.is_title()
assert s.title() == 'HELLO WORLD'
s = 'Hello World'
assert s.is_title()
assert s.title() == 'Hello World'
}
fn test_for_loop() {
mut i := 0
s := 'abcd'
for c in s {
assert c == s[i]
i++
}
}
fn test_for_loop_two() {
s := 'abcd'
for i, c in s {
assert c == s[i]
}
}
fn test_quote() {
a := `'`
println('testing double quotes')
b := 'hi'
assert b == 'hi'
// assert a.str() == "'"
}
/*
fn test_limit() {
s := 'hello'
assert s.limit(2) == 'he'
assert s.limit(9) == s
assert s.limit(0) == ''
// assert s.limit(-1) == ''
}*/
fn test_repeat() {
s1 := 'V! '
assert s1.repeat(5) == 'V! V! V! V! V! '
assert s1.repeat(1) == s1
assert s1.repeat(0) == ''
s2 := ''
assert s2.repeat(5) == s2
assert s2.repeat(1) == s2
assert s2.repeat(0) == s2
// TODO Add test for negative values
}
fn test_starts_with() {
s := 'V Programming Language'
assert s.starts_with('V') == true
assert s.starts_with('V Programming') == true
assert s.starts_with('Language') == false
}
fn test_trim_prefix() {
s := 'V Programming Language'
assert s.trim_prefix('V ') == 'Programming Language'
assert s.trim_prefix('V Programming ') == 'Language'
assert s.trim_prefix('Language') == s
s2 := 'TestTestTest'
assert s2.trim_prefix('Test') == 'TestTest'
assert s2.trim_prefix('TestTest') == 'Test'
s3 := '123Test123Test'
assert s3.trim_prefix('123') == 'Test123Test'
assert s3.trim_prefix('123Test') == '123Test'
}
fn test_trim_suffix() {
s := 'V Programming Language'
assert s.trim_suffix(' Language') == 'V Programming'
assert s.trim_suffix(' Programming Language') == 'V'
assert s.trim_suffix('V') == s
s2 := 'TestTestTest'
assert s2.trim_suffix('Test') == 'TestTest'
assert s2.trim_suffix('TestTest') == 'Test'
s3 := '123Test123Test'
assert s3.trim_suffix('123') == s3
assert s3.trim_suffix('123Test') == '123Test'
}
fn test_raw() {
raw := r'raw\nstring'
lines := raw.split('\n')
println(lines)
assert lines.len == 1
println('raw string: "$raw"')
raw2 := r'Hello V\0'
assert raw2[7] == `\\`
assert raw2[8] == `0`
raw3 := r'Hello V\x00'
assert raw3[7] == `\\`
assert raw3[8] == `x`
assert raw3[9] == `0`
assert raw3[10] == `0`
}
fn test_raw_with_quotes() {
raw := r"some'" + r'"thing' // " should be escaped in the generated C code
// assert raw[0] == `s`
// assert raw[5] == `"`
// assert raw[6] == `t`
}
fn test_escape() {
a := 10
println("\"$a")
// assert "\"$a" == '"10'
}
fn test_atoi() {
assert '234232'.int() == 234232
assert '-9009'.int() == -9009
assert '0'.int() == 0
for n in -10000 .. 100000 {
s := n.str()
assert s.int() == n
}
}
fn test_raw_inter() {
world := 'world'
println(world)
s := r'hello\n$world'
assert s == r'hello\n$world'
assert s.contains('$')
}
fn test_c_r() {
// This used to break because of r'' and c''
c := 42
println('$c')
r := 50
println('$r')
}
fn test_inter_before_comp_if() {
s := '123'
// This used to break ('123 $....')
$if linux {
println(s)
}
assert s == '123'
}
fn test_double_quote_inter() {
a := 1
b := 2
println('$a $b')
assert '$a $b' == '1 2'
assert '$a $b' == '1 2'
}
fn foo(b byte) byte {
return b - 10
}
fn filter(b byte) bool {
return b != `a`
}
/*
fn test_split_into_lines() {
line_content := 'Line'
text_crlf := '$line_content\r\n$line_content\r\n$line_content'
lines_crlf := text_crlf.split_into_lines()
assert lines_crlf.len == 3
for line in lines_crlf {
assert line == line_content
}
text_lf := '$line_content\n$line_content\n$line_content'
lines_lf := text_lf.split_into_lines()
assert lines_lf.len == 3
for line in lines_lf {
assert line == line_content
}
}
*/
fn test_string_literal_with_backslash() {
a := 'HelloWorld'
assert a == 'HelloWorld'
b := 'OneTwoThree'
assert b == 'OneTwoThree'
}
/*
type MyString = string
fn test_string_alias() {
s := MyString('hi')
ss := s + '!'
}
*/
// sort an array of structs, by their string field values
struct Ka {
s string
i int
}
fn test_sorter() {
mut arr := [
Ka{
s: 'bbb'
i: 100
},
Ka{
s: 'aaa'
i: 101
},
Ka{
s: 'ccc'
i: 102
},
]
cmp := fn (a &Ka, b &Ka) int {
return compare_strings(a.s, b.s)
}
arr.sort_with_compare(cmp)
assert arr[0].s == 'aaa'
assert arr[0].i == 101
assert arr[1].s == 'bbb'
assert arr[1].i == 100
assert arr[2].s == 'ccc'
assert arr[2].i == 102
}
fn test_fields() {
assert 'a bcde'.fields() == ['a', 'bcde']
assert ' sss \t ssss '.fields() == ['sss', 'ssss']
assert '\n xyz \t abc def'.fields() == ['xyz', 'abc', 'def']
assert 'hello'.fields() == ['hello']
assert ''.fields() == []
}
/*
fn test_interpolation_after_quoted_variable_still_works() {
rr := 'abc'
tt := 'xyz'
// Basic interpolation, no internal quotes
yy := 'Replacing $rr with $tt'
assert yy == 'Replacing abc with xyz'
// Interpolation after quoted variable ending with 'r'quote
// that may be mistaken with the start of a raw string,
// ensure that it is not.
ss := 'Replacing "$rr" with "$tt"'
assert ss == 'Replacing "abc" with "xyz"'
zz := "Replacing '$rr' with '$tt'"
assert zz == "Replacing 'abc' with 'xyz'"
// Interpolation after quoted variable ending with 'c'quote
// may be mistaken with the start of a c string, so
// check it is not.
cc := 'abc'
ccc := "Replacing '$cc' with '$tt'"
assert ccc == "Replacing 'abc' with 'xyz'"
cccq := 'Replacing "$cc" with "$tt"'
assert cccq == 'Replacing "abc" with "xyz"'
}
*/
fn test_index_any() {
x := 'abcdefghij'
assert x.index_any('ef') == 4
assert x.index_any('fe') == 4
}

View File

@ -287,7 +287,11 @@ fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
g.gen_deref_ptr(node.right_type)
g.write(',')
g.expr(node.left)
g.write('))')
g.write(')')
if node.op == .not_in {
g.write('.valueOf()')
}
g.write(')')
return
} else if r_sym.unaliased_sym.kind == .map {
g.expr(node.right)

View File

@ -145,7 +145,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
g.gen_builtin_type_defs()
g.writeln('Object.defineProperty(array.prototype,"len", { get: function() {return new int(this.arr.arr.length);}, set: function(l) { this.arr.arr.length = l.valueOf(); } }); ')
g.writeln('Object.defineProperty(string.prototype,"len", { get: function() {return new int(this.str.length);}, set: function(l) {/* ignore */ } }); ')
g.writeln('Object.defineProperty(map.prototype,"len", { get: function() {return new int(this.map.length);}, set: function(l) { this.map.length = l.valueOf(); } }); ')
g.writeln('Object.defineProperty(map.prototype,"len", { get: function() {return new int(this.map.size);}, set: function(l) { this.map.size = l.valueOf(); } }); ')
g.writeln('Object.defineProperty(array.prototype,"length", { get: function() {return new int(this.arr.arr.length);}, set: function(l) { this.arr.arr.length = l.valueOf(); } }); ')
g.generated_builtin = true
}
@ -1182,7 +1182,7 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
g.write('.val')
}
if g.inside_map_set && op == .assign {
if false && g.inside_map_set && op == .assign {
g.inside_map_set = false
g.write(', ')
g.expr(val)
@ -2338,15 +2338,24 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
if expr.is_setter {
g.inside_map_set = true
g.write('.map.set(')
g.write('.getOrSet(')
} else {
g.write('.map.get(')
}
g.expr(expr.index)
g.write('.\$toJS()')
if !expr.is_setter {
g.write(')')
if expr.is_setter {
// g.write(', ${g.to_js_typ_val(left_typ.)')
match left_typ.info {
ast.Map {
g.write(', ${g.to_js_typ_val(left_typ.info.value_type)}')
}
else {
verror('unreachable')
}
}
}
g.write(')')
} else if left_typ.kind == .string {
if expr.is_setter {
// TODO: What's the best way to do this?