v.gen.js: port fully the array test suite & add fixes (#11073)
parent
c560d58f1e
commit
94c321c80d
|
@ -14,3 +14,13 @@ pub fn (mut m map) delete(key voidptr) {
|
||||||
pub fn (m &map) free() {}
|
pub fn (m &map) free() {}
|
||||||
|
|
||||||
#map.prototype[Symbol.iterator] = function () { return this.map[Symbol.iterator](); }
|
#map.prototype[Symbol.iterator] = function () { return this.map[Symbol.iterator](); }
|
||||||
|
|
||||||
|
#map.prototype.toString = function () {
|
||||||
|
#function fmtKey(key) { return typeof key == 'string' ? '\'' + key + '\'' : key}
|
||||||
|
#let res = '{'
|
||||||
|
#for (const entry of this) {
|
||||||
|
#res += fmtKey(entry[0]) + ': ' + entry[0];
|
||||||
|
#}
|
||||||
|
#res += '}'
|
||||||
|
#return res;
|
||||||
|
#}
|
||||||
|
|
|
@ -94,7 +94,10 @@ pub fn (s string) count(substr string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) ends_with(p string) bool {
|
pub fn (s string) ends_with(p string) bool {
|
||||||
return s.str.endsWith(p.str)
|
mut res := false
|
||||||
|
#res.val = s.str.endsWith(p.str)
|
||||||
|
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) starts_with(p string) bool {
|
pub fn (s string) starts_with(p string) bool {
|
||||||
|
@ -133,7 +136,7 @@ pub fn (s string) fields() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) find_between(start string, end string) string {
|
pub fn (s string) find_between(start string, end string) string {
|
||||||
return string(s.str.slice(s.str.indexOf(start.str), s.str.indexOf(end.str) + 1))
|
return string(s.str.slice(s.str.indexOf(start.str) + 1, s.str.indexOf(end.str)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// unnecessary in the JS backend, implemented for api parity.
|
// unnecessary in the JS backend, implemented for api parity.
|
||||||
|
@ -464,3 +467,77 @@ pub fn (s string) strip_margin_custom(del byte) string {
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// split_nth splits the string based on the passed `delim` substring.
|
||||||
|
// It returns the first Nth parts. When N=0, return all the splits.
|
||||||
|
// The last returned element has the remainder of the string, even if
|
||||||
|
// the remainder contains more `delim` substrings.
|
||||||
|
[direct_array_access]
|
||||||
|
pub fn (s string) split_nth(delim string, nth int) []string {
|
||||||
|
mut res := []string{}
|
||||||
|
mut i := 0
|
||||||
|
|
||||||
|
match delim.len {
|
||||||
|
0 {
|
||||||
|
i = 1
|
||||||
|
for ch in s {
|
||||||
|
if nth > 0 && i >= nth {
|
||||||
|
res << s[i..]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
res << ch.str()
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
1 {
|
||||||
|
mut start := 0
|
||||||
|
delim_byte := delim[0]
|
||||||
|
|
||||||
|
for i < s.len {
|
||||||
|
if s[i] == delim_byte {
|
||||||
|
was_last := nth > 0 && res.len == nth - 1
|
||||||
|
if was_last {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
val := s[start..i] //.substr(start, i)
|
||||||
|
res << val
|
||||||
|
start = i + delim.len
|
||||||
|
i = start
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then the remaining right part of the string
|
||||||
|
if nth < 1 || res.len < nth {
|
||||||
|
res << s[start..]
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mut start := 0
|
||||||
|
// Take the left part for each delimiter occurence
|
||||||
|
for i <= s.len {
|
||||||
|
is_delim := i + delim.len <= s.len && s[i..i + delim.len] == delim
|
||||||
|
if is_delim {
|
||||||
|
was_last := nth > 0 && res.len == nth - 1
|
||||||
|
if was_last {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
val := s[start..i] // .substr(start, i)
|
||||||
|
res << val
|
||||||
|
start = i + delim.len
|
||||||
|
i = start
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Then the remaining right part of the string
|
||||||
|
if nth < 1 || res.len < nth {
|
||||||
|
res << s[start..]
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ fn (mut g JsGen) to_js_typ_val(t ast.Type) string {
|
||||||
styp = '$prefix${g.sym_to_js_typ(sym)}("")'
|
styp = '$prefix${g.sym_to_js_typ(sym)}("")'
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
styp = 'new Map()'
|
styp = 'new map(new Map())'
|
||||||
}
|
}
|
||||||
.array {
|
.array {
|
||||||
styp = '$prefix${g.sym_to_js_typ(sym)}()'
|
styp = '$prefix${g.sym_to_js_typ(sym)}()'
|
||||||
|
@ -335,6 +335,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
||||||
typ_name: typ_name
|
typ_name: typ_name
|
||||||
default_value: 'new Boolean(false)'
|
default_value: 'new Boolean(false)'
|
||||||
to_jsval: '+this != 0'
|
to_jsval: '+this != 0'
|
||||||
|
eq: 'this.val === other.valueOf()'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
'string' {
|
'string' {
|
||||||
|
@ -354,7 +355,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
||||||
g.gen_builtin_prototype(
|
g.gen_builtin_prototype(
|
||||||
typ_name: typ_name
|
typ_name: typ_name
|
||||||
val_name: 'map'
|
val_name: 'map'
|
||||||
default_value: 'new Map()'
|
default_value: 'new map(new Map())'
|
||||||
constructor: 'this.map = map'
|
constructor: 'this.map = map'
|
||||||
value_of: 'this'
|
value_of: 'this'
|
||||||
to_string: 'this.map.toString()'
|
to_string: 'this.map.toString()'
|
||||||
|
|
|
@ -1831,17 +1831,16 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
} else {
|
} else {
|
||||||
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
||||||
|
|
||||||
mut needs_cast := is_arithmetic && it.left_type != it.right_type
|
|
||||||
mut greater_typ := 0
|
mut greater_typ := 0
|
||||||
// todo(playX): looks like this cast is always required to perform .eq operation on types.
|
// todo(playX): looks like this cast is always required to perform .eq operation on types.
|
||||||
if true || needs_cast {
|
if is_arithmetic {
|
||||||
greater_typ = g.greater_typ(it.left_type, it.right_type)
|
greater_typ = g.greater_typ(it.left_type, it.right_type)
|
||||||
if g.cast_stack.len > 0 {
|
if g.cast_stack.len > 0 {
|
||||||
needs_cast = g.cast_stack.last() != greater_typ
|
// needs_cast = g.cast_stack.last() != greater_typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if true || needs_cast {
|
if is_arithmetic {
|
||||||
if g.ns.name == 'builtin' {
|
if g.ns.name == 'builtin' {
|
||||||
g.write('new ')
|
g.write('new ')
|
||||||
}
|
}
|
||||||
|
@ -1855,7 +1854,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
|
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
|
|
||||||
if true || needs_cast {
|
if is_arithmetic {
|
||||||
g.cast_stack.delete_last()
|
g.cast_stack.delete_last()
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,6 +195,7 @@ true
|
||||||
[2, 3, 4]
|
[2, 3, 4]
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
|
[[1, 2, 3], [4, 5, 6]]
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
|
@ -292,5 +293,11 @@ true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
0
|
0
|
||||||
|
`exists`: true and `not exists`: false
|
||||||
[[], [], [], []]
|
[[], [], [], []]
|
||||||
[[], [], [123], []]
|
[[], [], [123], []]
|
||||||
|
[{}, {}, {}, {}]
|
||||||
|
[{}, {}, {'123': 123}, {}]
|
||||||
|
Numbers { odds: [1, 3, 5] , evens: [2, 4] }
|
||||||
|
Numbers { odds: [3, 5, 7] , evens: [2, 6, 10] }
|
||||||
|
[[10, 10, 10], [10, 10, 10], [10, 10, 10]]
|
||||||
|
|
|
@ -16,6 +16,11 @@ struct Coord {
|
||||||
z int
|
z int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Numbers {
|
||||||
|
odds []int
|
||||||
|
evens []int
|
||||||
|
}
|
||||||
|
|
||||||
struct Person {
|
struct Person {
|
||||||
name string
|
name string
|
||||||
nums []int
|
nums []int
|
||||||
|
@ -672,15 +677,13 @@ fn main() {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// test array str
|
// test array str
|
||||||
// todo(playX): JS array formatting should match what default builtin impl has.
|
|
||||||
/*
|
|
||||||
numbers := [1, 2, 3]
|
numbers := [1, 2, 3]
|
||||||
assert numbers == [1, 2, 3]
|
assert numbers == [1, 2, 3]
|
||||||
numbers2 := [numbers, [4, 5, 6]] // dup str() bug
|
numbers2 := [numbers, [4, 5, 6]] // dup str() bug
|
||||||
println(numbers2)
|
println(numbers2)
|
||||||
assert true
|
assert true
|
||||||
assert numbers.str() == '[1, 2, 3]'
|
assert numbers.str() == '[1, 2, 3]'
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// test eq
|
// test eq
|
||||||
|
@ -1110,8 +1113,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// test array struct contains
|
// test array struct contains
|
||||||
/*
|
|
||||||
todo: does not work
|
|
||||||
mut coords := []Coord{}
|
mut coords := []Coord{}
|
||||||
coord_1 := Coord{
|
coord_1 := Coord{
|
||||||
x: 1
|
x: 1
|
||||||
|
@ -1124,7 +1126,6 @@ fn main() {
|
||||||
println('`exists`: $exists and `not exists`: $not_exists')
|
println('`exists`: $exists and `not exists`: $not_exists')
|
||||||
assert exists == true
|
assert exists == true
|
||||||
assert not_exists == false
|
assert not_exists == false
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// test array of array append
|
// test array of array append
|
||||||
|
@ -1133,4 +1134,47 @@ fn main() {
|
||||||
x[2] << 123 // RTE
|
x[2] << 123 // RTE
|
||||||
println(x)
|
println(x)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// test array of map insert
|
||||||
|
mut x := []map[string]int{len: 4}
|
||||||
|
println(x) // OK
|
||||||
|
x[2]['123'] = 123 // RTE
|
||||||
|
println(x)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// todo(playX): does not work
|
||||||
|
/*
|
||||||
|
// test multi fixed array init
|
||||||
|
a := [3][3]int{}
|
||||||
|
println(a)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test array of multi filter
|
||||||
|
arr := [1, 2, 3, 4, 5]
|
||||||
|
nums := Numbers{
|
||||||
|
odds: arr.filter(it % 2 == 1)
|
||||||
|
evens: arr.filter(it % 2 == 0)
|
||||||
|
}
|
||||||
|
println(nums)
|
||||||
|
assert nums.odds == [1, 3, 5]
|
||||||
|
assert nums.evens == [2, 4]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test array of multi map
|
||||||
|
arr := [1, 3, 5]
|
||||||
|
nums := Numbers{
|
||||||
|
odds: arr.map(it + 2)
|
||||||
|
evens: arr.map(it * 2)
|
||||||
|
}
|
||||||
|
println(nums)
|
||||||
|
assert nums.odds == [3, 5, 7]
|
||||||
|
assert nums.evens == [2, 6, 10]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test multi fixed array with default init
|
||||||
|
a := [3][3]int{init: [3]int{init: 10}}
|
||||||
|
println(a)
|
||||||
|
assert a == [[10, 10, 10]!, [10, 10, 10]!, [10, 10, 10]!]!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
ab
|
||||||
|
1000
|
||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
man
|
||||||
|
true
|
|
@ -0,0 +1,200 @@
|
||||||
|
struct Foo {
|
||||||
|
bar int
|
||||||
|
mut:
|
||||||
|
str string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
{
|
||||||
|
// test add
|
||||||
|
mut a := 'a'
|
||||||
|
a += 'b'
|
||||||
|
println(a)
|
||||||
|
a = 'a'
|
||||||
|
for i := 1; i < 1000; i++ {
|
||||||
|
a += 'b'
|
||||||
|
}
|
||||||
|
println(a.len)
|
||||||
|
println(a.ends_with('bbbbb'))
|
||||||
|
a += '123'
|
||||||
|
println(a.ends_with('3'))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test ends with
|
||||||
|
a := 'browser.v'
|
||||||
|
println(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
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test between
|
||||||
|
s := 'hello [man] how you doing'
|
||||||
|
println(s.find_between('[', ']'))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// test compare
|
||||||
|
a := 'Music'
|
||||||
|
b := 'src'
|
||||||
|
println(b >= a)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// 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'
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// todo(playX): sort codegen
|
||||||
|
/*// 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'*/
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// todo: 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
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// 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] == ''
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue