js: array improvements (#11952)
parent
f3757a7cd1
commit
863dd0b23e
|
@ -1,12 +1,69 @@
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
struct array {
|
/// Internal representation of `array` type. It is used to implement slices and to make slices behave correctly
|
||||||
|
/// it simply stores reference to original array and to index them properly it does index array relative to `index_start`.
|
||||||
|
struct array_buffer {
|
||||||
arr JS.Array
|
arr JS.Array
|
||||||
|
index_start int
|
||||||
|
len int
|
||||||
|
cap int
|
||||||
|
has_slice bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut a array_buffer) make_copy() {
|
||||||
|
if a.index_start != 0 || a.has_slice {
|
||||||
|
mut new_arr := JS.makeEmtpyJSArray()
|
||||||
|
for mut i in 0 .. a.len {
|
||||||
|
#new_arr.push(a.val.get(i))
|
||||||
|
|
||||||
|
mut x := i
|
||||||
|
x = x
|
||||||
|
}
|
||||||
|
new_arr = new_arr
|
||||||
|
#a.val.arr = new_arr
|
||||||
|
#a.val.index_start = new int(0)
|
||||||
|
#a.val.has_slice = new bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#array_buffer.prototype.make_copy = function() { return array_buffer_make_copy(this) }
|
||||||
|
// TODO(playX): Should this be implemented fully in JS, use generics or just voidptr?
|
||||||
|
fn (a array_buffer) get(ix int) voidptr {
|
||||||
|
mut res := voidptr(0)
|
||||||
|
#res = a.arr[a.index_start.val + ix.val];
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut a array_buffer) set(ix int, val voidptr) {
|
||||||
|
#a.val.arr[a.val.index_start.valueOf() + ix.valueOf()] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#array_buffer.prototype.get = function(ix) { return array_buffer_get(this,ix);}
|
||||||
|
#array_buffer.prototype.set = function(ix,val) { array_buffer_set(this,ix,val); }
|
||||||
|
|
||||||
|
struct array {
|
||||||
|
arr array_buffer
|
||||||
pub:
|
pub:
|
||||||
len int
|
len int
|
||||||
cap int
|
cap int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn v_sort(mut arr array, comparator fn (voidptr, voidptr) int) {
|
||||||
|
mut need_iter := true
|
||||||
|
for need_iter {
|
||||||
|
need_iter = false
|
||||||
|
for i := 1; i < arr.len; i++ {
|
||||||
|
if comparator(arr[i], arr[i - 1]) != 1 {
|
||||||
|
tmp := arr[i]
|
||||||
|
arr[i] = arr[i - 1]
|
||||||
|
arr[i - 1] = tmp
|
||||||
|
need_iter = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#function flatIntoArray(target, source, sourceLength, targetIndex, depth) {
|
#function flatIntoArray(target, source, sourceLength, targetIndex, depth) {
|
||||||
#"use strict";
|
#"use strict";
|
||||||
#
|
#
|
||||||
|
@ -43,25 +100,32 @@ pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||||
panic('array.repeat: count is negative: $count')
|
panic('array.repeat: count is negative: $count')
|
||||||
}
|
}
|
||||||
mut arr := empty_array()
|
mut arr := empty_array()
|
||||||
#let tmp = new Array(a.arr.length * +count);
|
|
||||||
#tmp.fill(a.arr);
|
|
||||||
#
|
|
||||||
#arr.arr = flatArray(tmp,depth+1);
|
|
||||||
|
|
||||||
|
if a.len > 0 {
|
||||||
|
for _ in 0 .. count {
|
||||||
|
for i in 0 .. a.len {
|
||||||
|
if depth > 0 {
|
||||||
|
// TODO
|
||||||
|
} else {
|
||||||
|
arr.push(a.arr.get(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
// last returns the last element of the array.
|
// last returns the last element of the array.
|
||||||
pub fn (a array) last() voidptr {
|
pub fn (a array) last() voidptr {
|
||||||
mut res := voidptr(0)
|
mut res := voidptr(0)
|
||||||
#res = a.arr[a.len-1];
|
#res = a.arr.get(new int(a.len-1));
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (a array) get(ix int) voidptr {
|
fn (a array) get(ix int) voidptr {
|
||||||
mut result := voidptr(0)
|
mut result := voidptr(0)
|
||||||
#result = a.arr[ix]
|
#result = a.arr.get(ix)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -72,28 +136,34 @@ pub fn (a array) repeat(count int) array {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn empty_array() array {
|
#function makeEmptyArray() { return new array(new array_buffer({})); }
|
||||||
mut arr := array{}
|
#function makeEmtpyJSArray() { return new Array(); }
|
||||||
#arr = new array([])
|
|
||||||
|
|
||||||
return arr
|
fn JS.makeEmptyArray() array
|
||||||
|
fn JS.makeEmtpyJSArray() JS.Array
|
||||||
|
fn empty_array() array {
|
||||||
|
return JS.makeEmptyArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (a &array) set_len(i int) {
|
fn (a &array) set_len(i int) {
|
||||||
#a.arr.length=i
|
#a.arr.arr.length=i
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) sort_with_compare(compare voidptr) {
|
pub fn (mut a array) sort_with_compare(compare voidptr) {
|
||||||
#a.val.arr.sort(compare)
|
v_sort(mut a, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut a array) sort_with_compare_old(compare voidptr) {
|
||||||
|
#a.val.arr.arr.sort(compare)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) sort() {
|
pub fn (mut a array) sort() {
|
||||||
#a.val.arr.sort($sortComparator)
|
#a.val.arr.arr.sort($sortComparator)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (a array) index(v string) int {
|
pub fn (a array) index(v string) int {
|
||||||
for i in 0 .. a.len {
|
for i in 0 .. a.len {
|
||||||
#if (a.arr[i].toString() == v.toString())
|
#if (a.arr.get(i).toString() == v.toString())
|
||||||
|
|
||||||
{
|
{
|
||||||
return i
|
return i
|
||||||
|
@ -104,39 +174,80 @@ pub fn (a array) index(v string) int {
|
||||||
|
|
||||||
pub fn (a array) slice(start int, end int) array {
|
pub fn (a array) slice(start int, end int) array {
|
||||||
mut result := a
|
mut result := a
|
||||||
#result = new array(a.arr.slice(start,end))
|
#let slice = a.arr.arr.slice(start,end)
|
||||||
|
#result = new array(new array_buffer({arr: a.arr.arr, len: new int(slice.length),cap: new int(slice.length),index_start: new int(start)}))
|
||||||
|
#a.arr.has_slice = true
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) insert(i int, val voidptr) {
|
pub fn (mut a array) insert(i int, val voidptr) {
|
||||||
#a.val.arr.splice(i,0,val)
|
#a.val.arr.make_copy()
|
||||||
|
#a.val.arr.arr.splice(i,0,val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||||
#a.val.arr.splice(i,0,...val.slice(0,+size))
|
#a.val.arr.arr.splice(i,0,...val.arr.slice(0,+size))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) join(separator string) string {
|
pub fn (mut a array) join(separator string) string {
|
||||||
mut res := ''
|
mut res := ''
|
||||||
#res = new string(a.val.arr.join(separator +''));
|
#res = new string(a.val.arr.arr.join(separator +''));
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (a array) push(val voidptr) {
|
fn (mut a array) push(val voidptr) {
|
||||||
#a.arr.push(val)
|
#a.val.arr.make_copy()
|
||||||
|
#a.val.arr.arr.push(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
#array.prototype[Symbol.iterator] = function () { return this.arr[Symbol.iterator](); }
|
fn v_filter(arr array, callback fn (voidptr) bool) array {
|
||||||
#array.prototype.entries = function () { let result = []; for (const [key,val] of this.arr.entries()) { result.push([new int(key), val]); } return result[Symbol.iterator](); }
|
mut filtered := empty_array()
|
||||||
#array.prototype.map = function(callback) { return new array(this.arr.map(callback)); }
|
|
||||||
#array.prototype.filter = function(callback) { return new array(this.arr.filter( function (it) { return (+callback(it)) != 0; } )); }
|
for i := 0; i < arr.arr.len; i++ {
|
||||||
|
if callback(arr.arr.get(i)) {
|
||||||
|
filtered.push(arr.arr.get(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn v_map(arr array, callback fn (voidptr) voidptr) array {
|
||||||
|
mut maped := empty_array()
|
||||||
|
|
||||||
|
for i := 0; i < arr.arr.len; i++ {
|
||||||
|
maped.push(callback(arr.arr.get(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return maped
|
||||||
|
}
|
||||||
|
|
||||||
|
struct array_iterator {
|
||||||
|
ix int
|
||||||
|
end int
|
||||||
|
arr JS.Array
|
||||||
|
}
|
||||||
|
|
||||||
|
#array_iterator.prototype.next = function () {
|
||||||
|
#if (this.ix.val < this.end.val) {
|
||||||
|
#this.ix.val++;
|
||||||
|
#return {done: false, value: this.arr.arr.get(new int(this.ix.val-1))}
|
||||||
|
#} else {
|
||||||
|
#return {done: true, value: undefined}
|
||||||
|
#}
|
||||||
|
#}
|
||||||
|
#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.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); }
|
||||||
#Object.defineProperty(array.prototype,'cap',{ get: function () { return this.len; } })
|
#Object.defineProperty(array.prototype,'cap',{ get: function () { return this.len; } })
|
||||||
#array.prototype.any = function (value) {
|
#array.prototype.any = function (value) {
|
||||||
#let val ;if (typeof value == 'function') { val = function (x) { return value(x); } } else { val = function (x) { return vEq(x,value); } }
|
#let val ;if (typeof value == 'function') { val = function (x) { return value(x); } } else { val = function (x) { return vEq(x,value); } }
|
||||||
#for (let i = 0;i < this.arr.length;i++)
|
#for (let i = 0;i < this.arr.arr.length;i++)
|
||||||
#if (val(this.arr[i]))
|
#if (val(this.arr.get(i)))
|
||||||
#return true;
|
#return true;
|
||||||
#
|
#
|
||||||
#return false;
|
#return false;
|
||||||
|
@ -144,12 +255,17 @@ fn (a array) push(val voidptr) {
|
||||||
|
|
||||||
#array.prototype.all = function (value) {
|
#array.prototype.all = function (value) {
|
||||||
#let val ;if (typeof value == 'function') { val = function (x) { return value(x); } } else { val = function (x) { return vEq(x,value); } }
|
#let val ;if (typeof value == 'function') { val = function (x) { return value(x); } } else { val = function (x) { return vEq(x,value); } }
|
||||||
#for (let i = 0;i < this.arr.length;i++)
|
#for (let i = 0;i < this.arr.arr.length;i++)
|
||||||
#if (!val(this.arr[i]))
|
#if (!val(this.arr.get(i)))
|
||||||
#return false;
|
#return false;
|
||||||
#
|
#
|
||||||
#return true;
|
#return true;
|
||||||
#}
|
#}
|
||||||
|
//#Object.defineProperty(array_buffer.prototype,"len", { get: function() {return new int(this.arr.length);}, set: function(l) { this.arr.length = l.valueOf(); } })
|
||||||
|
//#Object.defineProperty(array_buffer.prototype,"cap", { get: function() {return new int(this.arr.length);}, set: function(l) { this.arr.length = l.valueOf(); } })
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#function v_makeSlice(array) { Object.defineProperty(array,'len', {get: function() { return this.arr.len; }, set: function(l) { this.arr.len = l; }}) }
|
||||||
// delete deletes array element at index `i`.
|
// delete deletes array element at index `i`.
|
||||||
pub fn (mut a array) delete(i int) {
|
pub fn (mut a array) delete(i int) {
|
||||||
a.delete_many(i, 1)
|
a.delete_many(i, 1)
|
||||||
|
@ -157,7 +273,8 @@ pub fn (mut a array) delete(i int) {
|
||||||
|
|
||||||
// delete_many deletes `size` elements beginning with index `i`
|
// delete_many deletes `size` elements beginning with index `i`
|
||||||
pub fn (mut a array) delete_many(i int, size int) {
|
pub fn (mut a array) delete_many(i int, size int) {
|
||||||
#a.val.arr.splice(i.valueOf(),size.valueOf())
|
#a.val.arr.make_copy()
|
||||||
|
#a.val.arr.arr.splice(i.valueOf(),size.valueOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepend prepends one value to the array.
|
// prepend prepends one value to the array.
|
||||||
|
@ -172,48 +289,52 @@ pub fn (mut a array) prepend_many(val voidptr, size int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (a array) reverse() array {
|
pub fn (a array) reverse() array {
|
||||||
mut res := array{}
|
mut res := empty_array()
|
||||||
#res.arr = Array.from(a.arr).reverse()
|
#res.arr.arr = Array.from(a.arr).reverse()
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) reverse_in_place() {
|
pub fn (mut a array) reverse_in_place() {
|
||||||
#a.val.arr.reverse()
|
#a.val.arr.arr.reverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
#array.prototype.$includes = function (elem) { return this.arr.find(function(e) { return vEq(elem,e); }) !== undefined;}
|
#array.prototype.$includes = function (elem) { return this.arr.arr.find(function(e) { return vEq(elem,e); }) !== undefined;}
|
||||||
|
|
||||||
// reduce executes a given reducer function on each element of the array,
|
// reduce executes a given reducer function on each element of the array,
|
||||||
// resulting in a single output value.
|
// resulting in a single output value.
|
||||||
pub fn (a array) reduce(iter fn (int, int) int, accum_start int) int {
|
pub fn (a array) reduce(iter fn (int, int) int, accum_start int) int {
|
||||||
mut accum_ := accum_start
|
mut accum_ := accum_start
|
||||||
#for (let i = 0;i < a.arr.length;i++) {
|
/*#for (let i = 0;i < a.arr.length;i++) {
|
||||||
#accum_ = iter(accum_, a.arr[i])
|
#accum_ = iter(accum_, a.arr[i])
|
||||||
#}
|
#}*/
|
||||||
|
for i in 0 .. a.len {
|
||||||
|
accum_ = iter(accum_, a.get(i))
|
||||||
|
}
|
||||||
|
|
||||||
return accum_
|
return accum_
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a array) pop() voidptr {
|
pub fn (mut a array) pop() voidptr {
|
||||||
mut res := voidptr(0)
|
mut res := voidptr(0)
|
||||||
#res = a.val.arr.pop()
|
#a.val.arr.make_copy()
|
||||||
|
#res = a.val.arr.arr.pop()
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (a array) first() voidptr {
|
pub fn (a array) first() voidptr {
|
||||||
mut res := voidptr(0)
|
mut res := voidptr(0)
|
||||||
#res = a.arr[0]
|
#res = a.arr.get(new int(0))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
#array.prototype.toString = function () {
|
#array.prototype.toString = function () {
|
||||||
#let res = "["
|
#let res = "["
|
||||||
#for (let i = 0; i < this.arr.length;i++) {
|
#for (let i = 0; i < this.arr.arr.length;i++) {
|
||||||
#res += this.arr[i].toString();
|
#res += this.arr.get(i).toString();
|
||||||
#if (i != this.arr.length-1)
|
#if (i != this.arr.arr.length-1)
|
||||||
#res += ', '
|
#res += ', '
|
||||||
#}
|
#}
|
||||||
#res += ']'
|
#res += ']'
|
||||||
|
@ -221,16 +342,11 @@ pub fn (a array) first() voidptr {
|
||||||
#
|
#
|
||||||
#}
|
#}
|
||||||
|
|
||||||
pub fn (a array) contains(key voidptr) bool {
|
pub fn (a array) contains(key voidptr) bool
|
||||||
#for (let i = 0; i < a.arr.length;i++)
|
|
||||||
#if (vEq(a.arr[i],key)) return new bool(true);
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete_last effectively removes last element of an array.
|
// delete_last effectively removes last element of an array.
|
||||||
pub fn (mut a array) delete_last() {
|
pub fn (mut a array) delete_last() {
|
||||||
#a.val.arr.pop();
|
#a.val.arr.arr.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
[unsafe]
|
[unsafe]
|
||||||
|
@ -240,7 +356,7 @@ pub fn (a &array) free() {
|
||||||
// todo: once (a []byte) will work rewrite this
|
// todo: once (a []byte) will work rewrite this
|
||||||
pub fn (a array) bytestr() string {
|
pub fn (a array) bytestr() string {
|
||||||
res := ''
|
res := ''
|
||||||
#a.arr.forEach((item) => res.str += String.fromCharCode(+item))
|
#a.arr.arr.forEach((item) => res.str += String.fromCharCode(+item))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub fn (s string) bool() bool {
|
||||||
|
|
||||||
pub fn (s string) split(dot string) []string {
|
pub fn (s string) split(dot string) []string {
|
||||||
mut arr := s.str.split(dot.str).map(string(it))
|
mut arr := s.str.split(dot.str).map(string(it))
|
||||||
#arr = new array(arr)
|
#arr = new array(new array_buffer({arr,index_start: new int(0),len: new int(arr.length)}))
|
||||||
|
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub fn (mut b Builder) writeln(s string) {
|
||||||
pub fn (mut b Builder) str() string {
|
pub fn (mut b Builder) str() string {
|
||||||
s := ''
|
s := ''
|
||||||
|
|
||||||
#for (const c of b.val.buf.arr)
|
#for (const c of b.val.buf.arr.arr)
|
||||||
#s.str += String.fromCharCode(+c)
|
#s.str += String.fromCharCode(+c)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
|
@ -29,19 +29,22 @@ fn (mut g JsGen) gen_array_index_method(left_type ast.Type) string {
|
||||||
mut fn_builder := strings.new_builder(512)
|
mut fn_builder := strings.new_builder(512)
|
||||||
fn_builder.writeln('function ${fn_name}(a, v) {')
|
fn_builder.writeln('function ${fn_name}(a, v) {')
|
||||||
fn_builder.writeln('\tlet pelem = a.arr;')
|
fn_builder.writeln('\tlet pelem = a.arr;')
|
||||||
fn_builder.writeln('\tfor (let i = 0; i < pelem.length; ++i) {')
|
fn_builder.writeln('\tfor (let i = 0; i < pelem.arr.length; ++i) {')
|
||||||
if elem_sym.kind == .string {
|
if elem_sym.kind == .string {
|
||||||
fn_builder.writeln('\t\tif (pelem[i].str == v.str) {')
|
fn_builder.writeln('\t\tif (pelem.get(new int(i)).str == v.str) {')
|
||||||
} else if elem_sym.kind == .array && !info.elem_type.is_ptr() {
|
} else if elem_sym.kind == .array && !info.elem_type.is_ptr() {
|
||||||
fn_builder.writeln('\t\tif (vEq(pelem[i], v)) {')
|
ptr_typ := g.gen_array_equality_fn(info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_arr_eq(pelem.get(new int(i)), v).val) {')
|
||||||
} else if elem_sym.kind == .function && !info.elem_type.is_ptr() {
|
} else if elem_sym.kind == .function && !info.elem_type.is_ptr() {
|
||||||
fn_builder.writeln('\t\tif ( vEq(pelem[i], v)) {')
|
fn_builder.writeln('\t\tif (pelem.get(new int(i)) == v) {')
|
||||||
} else if elem_sym.kind == .map && !info.elem_type.is_ptr() {
|
} else if elem_sym.kind == .map && !info.elem_type.is_ptr() {
|
||||||
fn_builder.writeln('\t\tif (vEq(pelem[i], v)) {')
|
ptr_typ := g.gen_map_equality_fn(info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_map_eq(pelem.get(new int(i)), v).val) {')
|
||||||
} else if elem_sym.kind == .struct_ && !info.elem_type.is_ptr() {
|
} else if elem_sym.kind == .struct_ && !info.elem_type.is_ptr() {
|
||||||
fn_builder.writeln('\t\tif (vEq(pelem[i], v)) {')
|
ptr_typ := g.gen_struct_equality_fn(info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_struct_eq(pelem.get(new int(i)), v)) {')
|
||||||
} else {
|
} else {
|
||||||
fn_builder.writeln('\t\tif (pelem[i].valueOf() == v.valueOf()) {')
|
fn_builder.writeln('\t\tif (vEq(pelem.get(new int(i)), v)) {')
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\t\t\treturn new int(i);')
|
fn_builder.writeln('\t\t\treturn new int(i);')
|
||||||
fn_builder.writeln('\t\t}')
|
fn_builder.writeln('\t\t}')
|
||||||
|
@ -131,49 +134,7 @@ fn (mut g JsGen) gen_array_method_call(it ast.CallExpr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
'sort' {
|
'sort' {
|
||||||
g.write('array')
|
g.gen_array_sort(node)
|
||||||
rec_sym := g.table.get_type_symbol(node.receiver_type)
|
|
||||||
if rec_sym.kind != .array {
|
|
||||||
println(node.name)
|
|
||||||
println(g.typ(node.receiver_type))
|
|
||||||
// println(rec_sym.kind)
|
|
||||||
verror('.sort() is an array method')
|
|
||||||
}
|
|
||||||
|
|
||||||
// `users.sort(a.age > b.age)`
|
|
||||||
|
|
||||||
if node.args.len == 0 {
|
|
||||||
g.write('_sort(')
|
|
||||||
g.expr(it.left)
|
|
||||||
mut ltyp := it.left_type
|
|
||||||
for ltyp.is_ptr() {
|
|
||||||
g.write('.val')
|
|
||||||
ltyp = ltyp.deref()
|
|
||||||
}
|
|
||||||
|
|
||||||
g.write(')')
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
g.expr(it.left)
|
|
||||||
mut ltyp := it.left_type
|
|
||||||
for ltyp.is_ptr() {
|
|
||||||
g.write('.val')
|
|
||||||
ltyp = ltyp.deref()
|
|
||||||
}
|
|
||||||
g.write('.')
|
|
||||||
infix_expr := node.args[0].expr as ast.InfixExpr
|
|
||||||
left_name := infix_expr.left.str()
|
|
||||||
is_reverse := (left_name.starts_with('a') && infix_expr.op == .gt)
|
|
||||||
|| (left_name.starts_with('b') && infix_expr.op == .lt)
|
|
||||||
if is_reverse {
|
|
||||||
g.write('arr.sort(function (b,a) {')
|
|
||||||
} else {
|
|
||||||
g.write('arr.sort(function (a,b) {')
|
|
||||||
}
|
|
||||||
g.write('return ')
|
|
||||||
g.write('\$sortComparator(a,b)')
|
|
||||||
g.write('})')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -219,17 +180,20 @@ fn (mut g JsGen) gen_array_contains_method(left_type ast.Type) string {
|
||||||
fn_builder.writeln('function ${fn_name}(a,v) {')
|
fn_builder.writeln('function ${fn_name}(a,v) {')
|
||||||
fn_builder.writeln('\tfor (let i = 0; i < a.len; ++i) {')
|
fn_builder.writeln('\tfor (let i = 0; i < a.len; ++i) {')
|
||||||
if elem_sym.kind == .string {
|
if elem_sym.kind == .string {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i].str == v.str) {')
|
fn_builder.writeln('\t\tif (a.arr.arr[i].str == v.str) {')
|
||||||
} else if elem_sym.kind == .array && left_info.elem_type.nr_muls() == 0 {
|
} else if elem_sym.kind == .array && left_info.elem_type.nr_muls() == 0 {
|
||||||
fn_builder.writeln('\t\tif (vEq(a.arr[i], v)) {')
|
ptr_typ := g.gen_array_equality_fn(left_info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_arr_eq(a.arr.arr[i],v)) {')
|
||||||
} else if elem_sym.kind == .function {
|
} else if elem_sym.kind == .function {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i] == v) {')
|
fn_builder.writeln('\t\tif (a.arr.arr[i] == v) {')
|
||||||
} else if elem_sym.kind == .map && left_info.elem_type.nr_muls() == 0 {
|
} else if elem_sym.kind == .map && left_info.elem_type.nr_muls() == 0 {
|
||||||
fn_builder.writeln('\t\tif (vEq(a.arr[i], v)) {')
|
ptr_typ := g.gen_map_equality_fn(left_info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_map_eq(a.arr.arr[i],v)) {')
|
||||||
} else if elem_sym.kind == .struct_ && left_info.elem_type.nr_muls() == 0 {
|
} else if elem_sym.kind == .struct_ && left_info.elem_type.nr_muls() == 0 {
|
||||||
fn_builder.writeln('\t\tif (vEq(a.arr[i],v)) {')
|
ptr_typ := g.gen_struct_equality_fn(left_info.elem_type)
|
||||||
|
fn_builder.writeln('\t\tif (${ptr_typ}_struct_eq(a.arr.arr[i],v)) {')
|
||||||
} else {
|
} else {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i].valueOf() == v.valueOf()) {')
|
fn_builder.writeln('\t\tif (vEq(a.arr.arr[i],v)) {')
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\t\t\treturn new bool(true);')
|
fn_builder.writeln('\t\t\treturn new bool(true);')
|
||||||
fn_builder.writeln('\t\t}')
|
fn_builder.writeln('\t\t}')
|
||||||
|
@ -248,3 +212,80 @@ fn (mut g JsGen) gen_array_contains_method(left_type ast.Type) string {
|
||||||
}
|
}
|
||||||
return fn_name
|
return fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g JsGen) gen_array_sort(node ast.CallExpr) {
|
||||||
|
rec_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
|
if rec_sym.kind != .array {
|
||||||
|
println(node.name)
|
||||||
|
verror('.sort() is an array method')
|
||||||
|
}
|
||||||
|
|
||||||
|
info := rec_sym.info as ast.Array
|
||||||
|
|
||||||
|
elem_stype := g.typ(info.elem_type)
|
||||||
|
mut compare_fn := 'compare_${elem_stype.replace('*', '_ptr')}'
|
||||||
|
mut comparison_type := g.unwrap(ast.void_type)
|
||||||
|
mut left_expr, mut right_expr := '', ''
|
||||||
|
|
||||||
|
if node.args.len == 0 {
|
||||||
|
comparison_type = g.unwrap(info.elem_type.set_nr_muls(0))
|
||||||
|
if compare_fn in g.array_sort_fn {
|
||||||
|
g.gen_array_sort_call(node, compare_fn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
left_expr = 'a'
|
||||||
|
right_expr = 'b'
|
||||||
|
} else {
|
||||||
|
infix_expr := node.args[0].expr as ast.InfixExpr
|
||||||
|
comparison_type = g.unwrap(infix_expr.left_type.set_nr_muls(0))
|
||||||
|
left_name := infix_expr.left.str()
|
||||||
|
if left_name.len > 1 {
|
||||||
|
compare_fn += '_by' + left_name[1..].replace_each(['.', '_', '[', '_', ']', '_'])
|
||||||
|
}
|
||||||
|
// is_reverse is `true` for `.sort(a > b)` and `.sort(b < a)`
|
||||||
|
is_reverse := (left_name.starts_with('a') && infix_expr.op == .gt)
|
||||||
|
|| (left_name.starts_with('b') && infix_expr.op == .lt)
|
||||||
|
if is_reverse {
|
||||||
|
compare_fn += '_reverse'
|
||||||
|
}
|
||||||
|
if compare_fn in g.array_sort_fn {
|
||||||
|
g.gen_array_sort_call(node, compare_fn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if left_name.starts_with('a') != is_reverse {
|
||||||
|
left_expr = g.expr_string(infix_expr.left)
|
||||||
|
right_expr = g.expr_string(infix_expr.right)
|
||||||
|
} else {
|
||||||
|
left_expr = g.expr_string(infix_expr.right)
|
||||||
|
right_expr = g.expr_string(infix_expr.left)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register a new custom `compare_xxx` function for qsort()
|
||||||
|
// TODO: move to checker
|
||||||
|
g.table.register_fn(name: compare_fn, return_type: ast.int_type)
|
||||||
|
g.array_sort_fn[compare_fn] = true
|
||||||
|
|
||||||
|
g.definitions.writeln('function ${compare_fn}(a,b) {')
|
||||||
|
c_condition := if comparison_type.sym.has_method('<') {
|
||||||
|
'${g.typ(comparison_type.typ)}__lt($left_expr, $right_expr)'
|
||||||
|
} else if comparison_type.unaliased_sym.has_method('<') {
|
||||||
|
'${g.typ(comparison_type.unaliased)}__lt($left_expr, $right_expr)'
|
||||||
|
} else {
|
||||||
|
'${left_expr}.valueOf() < ${right_expr}.valueOf()'
|
||||||
|
}
|
||||||
|
g.definitions.writeln('\tif ($c_condition) return -1;')
|
||||||
|
g.definitions.writeln('\telse return 1;')
|
||||||
|
g.definitions.writeln('}\n')
|
||||||
|
|
||||||
|
// write call to the generated function
|
||||||
|
g.gen_array_sort_call(node, compare_fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g JsGen) gen_array_sort_call(node ast.CallExpr, compare_fn string) {
|
||||||
|
g.write('v_sort(')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.gen_deref_ptr(node.left_type)
|
||||||
|
g.write(',$compare_fn)')
|
||||||
|
}
|
||||||
|
|
|
@ -182,29 +182,29 @@ fn (mut g JsGen) gen_array_equality_fn(left_type ast.Type) string {
|
||||||
fn_builder.writeln('\tfor (let i = 0; i < a.len; ++i) {')
|
fn_builder.writeln('\tfor (let i = 0; i < a.len; ++i) {')
|
||||||
// compare every pair of elements of the two arrays
|
// compare every pair of elements of the two arrays
|
||||||
if elem.sym.kind == .string {
|
if elem.sym.kind == .string {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i].str != b.arr[i].str) {')
|
fn_builder.writeln('\t\tif (a.arr.get(new int(i)).str != b.arr.get(new int(i)).str) {')
|
||||||
} else if elem.sym.kind == .sum_type && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .sum_type && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_sumtype_equality_fn(elem.typ)
|
eq_fn := g.gen_sumtype_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(a.arr[i],b.arr[i]).val) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(a.arr.get(new int(i)),b.arr.get(new int(i))).val) {')
|
||||||
} else if elem.sym.kind == .struct_ && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .struct_ && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_struct_equality_fn(elem.typ)
|
eq_fn := g.gen_struct_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(a.arr[i],b.arr[i]).val) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(a.arr.get(new int(i)),b.arr.get(new int(i))).val) {')
|
||||||
} else if elem.sym.kind == .array && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .array && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_array_equality_fn(elem.typ)
|
eq_fn := g.gen_array_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr[i],b.arr[i]).val) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr.get(new int(i)),b.arr.get(new int(i))).val) {')
|
||||||
} else if elem.sym.kind == .array_fixed && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .array_fixed && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_fixed_array_equality_fn(elem.typ)
|
eq_fn := g.gen_fixed_array_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr[i],b.arr[i]).val) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr.get(new int(i)),b.arr.get(new int(i))).val) {')
|
||||||
} else if elem.sym.kind == .map && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .map && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_map_equality_fn(elem.typ)
|
eq_fn := g.gen_map_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(a.arr[i],b.arr[i]).val) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(a.arr.get(new int(i)),b.arr.get(new int(i))).val) {')
|
||||||
} else if elem.sym.kind == .alias && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .alias && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_alias_equality_fn(elem.typ)
|
eq_fn := g.gen_alias_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(a.arr[i],b.arr[i]).val) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(a.arr.get(new int(i)),b.arr.get(new int(i))).val) {')
|
||||||
} else if elem.sym.kind == .function {
|
} else if elem.sym.kind == .function {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i] != b.arr[i]) {')
|
fn_builder.writeln('\t\tif (a.arr.get(new int(i)) != b.arr.get(new int(i))) {')
|
||||||
} else {
|
} else {
|
||||||
fn_builder.writeln('\t\tif (!vEq(a.arr[i],b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!vEq(a.arr.get(new int(i)),b.arr.get(new int(i)))) {')
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\t\t\treturn new bool(false);')
|
fn_builder.writeln('\t\t\treturn new bool(false);')
|
||||||
fn_builder.writeln('\t\t}')
|
fn_builder.writeln('\t\t}')
|
||||||
|
@ -234,29 +234,29 @@ fn (mut g JsGen) gen_fixed_array_equality_fn(left_type ast.Type) string {
|
||||||
fn_builder.writeln('\tfor (let i = 0; i < $size; ++i) {')
|
fn_builder.writeln('\tfor (let i = 0; i < $size; ++i) {')
|
||||||
// compare every pair of elements of the two fixed arrays
|
// compare every pair of elements of the two fixed arrays
|
||||||
if elem.sym.kind == .string {
|
if elem.sym.kind == .string {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i].str != b.arr[i].str) {')
|
fn_builder.writeln('\t\tif (a.arr.get(new int(i)).str != b.arr.get(new int(i)).str) {')
|
||||||
} else if elem.sym.kind == .sum_type && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .sum_type && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_sumtype_equality_fn(elem.typ)
|
eq_fn := g.gen_sumtype_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(a.arr[i], b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(a.arr.get(new int(i)), b.arr.get(new int(i)))) {')
|
||||||
} else if elem.sym.kind == .struct_ && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .struct_ && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_struct_equality_fn(elem.typ)
|
eq_fn := g.gen_struct_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(a.arr[i], b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(a.arr.get(new int(i)), b.arr.get(new int(i)))) {')
|
||||||
} else if elem.sym.kind == .array && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .array && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_array_equality_fn(elem.typ)
|
eq_fn := g.gen_array_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr[i], b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr.get(new int(i)), b.arr.get(new int(i)))) {')
|
||||||
} else if elem.sym.kind == .array_fixed && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .array_fixed && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_fixed_array_equality_fn(elem.typ)
|
eq_fn := g.gen_fixed_array_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr[i], b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a.arr.get(new int(i)), b.arr.get(new int(i)))) {')
|
||||||
} else if elem.sym.kind == .map && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .map && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_map_equality_fn(elem.typ)
|
eq_fn := g.gen_map_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(a.arr[i], b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(a.arr.get(new int(i)), b.arr.get(new int(i)))) {')
|
||||||
} else if elem.sym.kind == .alias && !elem.typ.is_ptr() {
|
} else if elem.sym.kind == .alias && !elem.typ.is_ptr() {
|
||||||
eq_fn := g.gen_alias_equality_fn(elem.typ)
|
eq_fn := g.gen_alias_equality_fn(elem.typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(a.arr[i], b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(a.arr.get(new int(i)), b.arr.get(new int(i)))) {')
|
||||||
} else if elem.sym.kind == .function {
|
} else if elem.sym.kind == .function {
|
||||||
fn_builder.writeln('\t\tif (a.arr[i] != b.arr[i]) {')
|
fn_builder.writeln('\t\tif (a.arr.get(new int(i)) != b.arr.get(new int(i))) {')
|
||||||
} else {
|
} else {
|
||||||
fn_builder.writeln('\t\tif (!vEq(a.arr[i],b.arr[i])) {')
|
fn_builder.writeln('\t\tif (!vEq(a.arr.get(new int(i)),b.arr.get(new int(i)))) {')
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\t\t\treturn new bool(false);')
|
fn_builder.writeln('\t\t\treturn new bool(false);')
|
||||||
fn_builder.writeln('\t\t}')
|
fn_builder.writeln('\t\t}')
|
||||||
|
@ -281,7 +281,7 @@ fn (mut g JsGen) gen_map_equality_fn(left_type ast.Type) string {
|
||||||
g.definitions.writeln(fn_builder.str())
|
g.definitions.writeln(fn_builder.str())
|
||||||
}
|
}
|
||||||
fn_builder.writeln('function ${ptr_styp}_map_eq(a,b) {')
|
fn_builder.writeln('function ${ptr_styp}_map_eq(a,b) {')
|
||||||
fn_builder.writeln('\tif (a.map.size() != b.map.size()) {')
|
fn_builder.writeln('\tif (a.map.size != b.map.size) {')
|
||||||
fn_builder.writeln('\t\treturn false;')
|
fn_builder.writeln('\t\treturn false;')
|
||||||
fn_builder.writeln('\t}')
|
fn_builder.writeln('\t}')
|
||||||
fn_builder.writeln('\tfor (let [key,value] of a.map) {')
|
fn_builder.writeln('\tfor (let [key,value] of a.map) {')
|
||||||
|
|
|
@ -444,7 +444,7 @@ fn (mut g JsGen) gen_str_for_array(info ast.Array, styp string, str_fn_name stri
|
||||||
if sym.kind == .function {
|
if sym.kind == .function {
|
||||||
g.definitions.writeln('\t\tlet it = ${elem_str_fn_name}();')
|
g.definitions.writeln('\t\tlet it = ${elem_str_fn_name}();')
|
||||||
} else {
|
} else {
|
||||||
g.definitions.writeln('\t\tlet it = a.arr[i];')
|
g.definitions.writeln('\t\tlet it = a.arr.get(new int(i));')
|
||||||
|
|
||||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||||
if is_elem_ptr {
|
if is_elem_ptr {
|
||||||
|
@ -506,23 +506,23 @@ fn (mut g JsGen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_f
|
||||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||||
if is_elem_ptr {
|
if is_elem_ptr {
|
||||||
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string("$deref_label"));')
|
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string("$deref_label"));')
|
||||||
g.definitions.writeln('\t\tif ( 0 == a.arr[i] ) {')
|
g.definitions.writeln('\t\tif ( 0 == a.arr.get(new int(i)) ) {')
|
||||||
g.definitions.writeln('\t\t\tstrings__Builder_write_string(sb, new string("0"));')
|
g.definitions.writeln('\t\t\tstrings__Builder_write_string(sb, new string("0"));')
|
||||||
g.definitions.writeln('\t\t}else{')
|
g.definitions.writeln('\t\t}else{')
|
||||||
g.definitions.writeln('\t\t\tstrings__Builder_write_string(sb, ${elem_str_fn_name}(a.arr[i] $deref) );')
|
g.definitions.writeln('\t\t\tstrings__Builder_write_string(sb, ${elem_str_fn_name}(a.arr.get(new int(i)) $deref) );')
|
||||||
g.definitions.writeln('\t\t}')
|
g.definitions.writeln('\t\t}')
|
||||||
} else {
|
} else {
|
||||||
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, ${elem_str_fn_name}(a.arr[i]) );')
|
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, ${elem_str_fn_name}(a.arr.get(new int(i))) );')
|
||||||
}
|
}
|
||||||
} else if sym.kind in [.f32, .f64] {
|
} else if sym.kind in [.f32, .f64] {
|
||||||
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string(a.arr[i].val.toString()) );')
|
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, new string(a.arr.get(new int(i)).val.toString()) );')
|
||||||
} else if sym.kind == .string {
|
} else if sym.kind == .string {
|
||||||
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, a.arr[i].str);')
|
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, a.arr.get(new int(i)));')
|
||||||
} else if sym.kind == .rune {
|
} else if sym.kind == .rune {
|
||||||
// tmp_str := str_intp_rune('${elem_str_fn_name}( a[i] $deref)')
|
// tmp_str := str_intp_rune('${elem_str_fn_name}( a[i] $deref)')
|
||||||
// g.definitions.writeln('\t\tstrings__Builder_write_string(sb, $tmp_str);')
|
// g.definitions.writeln('\t\tstrings__Builder_write_string(sb, $tmp_str);')
|
||||||
} else {
|
} else {
|
||||||
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, ${elem_str_fn_name}(a.arr[i] $deref));')
|
g.definitions.writeln('\t\tstrings__Builder_write_string(sb, ${elem_str_fn_name}(a.arr.get(new int(i)) $deref));')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.definitions.writeln('\t\tif (i < ${info.size - 1}) {')
|
g.definitions.writeln('\t\tif (i < ${info.size - 1}) {')
|
||||||
|
|
|
@ -405,8 +405,8 @@ 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: 'arr'
|
val_name: 'arr'
|
||||||
default_value: 'new Array()'
|
default_value: 'new array_buffer({})'
|
||||||
constructor: 'this.arr = arr'
|
constructor: 'this.arr = arr\nif (arr.index_start.val != 0) { v_makeSlice(this); } '
|
||||||
value_of: 'this'
|
value_of: 'this'
|
||||||
to_string: 'JSON.stringify(this.arr.map(it => it.valueOf()))'
|
to_string: 'JSON.stringify(this.arr.map(it => it.valueOf()))'
|
||||||
eq: 'new bool(vEq(self, other))'
|
eq: 'new bool(vEq(self, other))'
|
||||||
|
|
|
@ -482,7 +482,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) {
|
||||||
is_varg := i == args.len - 1 && it.is_variadic
|
is_varg := i == args.len - 1 && it.is_variadic
|
||||||
arg_name := g.js_name(arg.name)
|
arg_name := g.js_name(arg.name)
|
||||||
if is_varg {
|
if is_varg {
|
||||||
g.writeln('$arg_name = new array($arg_name);')
|
g.writeln('$arg_name = new array(new array_buffer({arr: $arg_name,len: new int(${arg_name}.length),index_start: new int(0)}));')
|
||||||
} else {
|
} else {
|
||||||
if arg.typ.is_ptr() || arg.is_mut {
|
if arg.typ.is_ptr() || arg.is_mut {
|
||||||
g.writeln('$arg_name = new \$ref($arg_name)')
|
g.writeln('$arg_name = new \$ref($arg_name)')
|
||||||
|
|
|
@ -236,15 +236,15 @@ fn (mut g JsGen) infix_expr_left_shift_op(node ast.InfixExpr) {
|
||||||
if right.unaliased_sym.kind == .array && array_info.elem_type != right.typ {
|
if right.unaliased_sym.kind == .array && array_info.elem_type != right.typ {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.gen_deref_ptr(left.typ)
|
g.gen_deref_ptr(left.typ)
|
||||||
g.write('.arr,...')
|
g.write('.arr.arr,...')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.gen_deref_ptr(right.typ)
|
g.gen_deref_ptr(right.typ)
|
||||||
g.write('.arr')
|
g.write('.arr.arr')
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.gen_deref_ptr(left.typ)
|
g.gen_deref_ptr(left.typ)
|
||||||
g.write('.arr,')
|
g.write('.arr.arr,')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
@ -254,13 +254,45 @@ fn (mut g JsGen) infix_expr_left_shift_op(node ast.InfixExpr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
|
fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
|
||||||
l_sym := g.table.get_final_type_symbol(node.left_type)
|
l_sym := g.unwrap(node.left_type)
|
||||||
r_sym := g.table.get_final_type_symbol(node.right_type)
|
r_sym := g.unwrap(node.right_type)
|
||||||
if node.op == .not_in {
|
if node.op == .not_in {
|
||||||
g.write('!')
|
g.write('!')
|
||||||
}
|
}
|
||||||
|
if r_sym.unaliased_sym.kind == .array {
|
||||||
|
fn_name := g.gen_array_contains_method(node.right_type)
|
||||||
|
g.write('(${fn_name}(')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.gen_deref_ptr(node.right_type)
|
g.gen_deref_ptr(node.right_type)
|
||||||
|
g.write(',')
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write('))')
|
||||||
|
return
|
||||||
|
} else if r_sym.unaliased_sym.kind == .map {
|
||||||
|
g.expr(node.right)
|
||||||
|
g.gen_deref_ptr(node.right_type)
|
||||||
|
g.write('.map.has(')
|
||||||
|
g.expr(node.left)
|
||||||
|
if l_sym.sym.kind == .string {
|
||||||
|
g.write('.str')
|
||||||
|
} else {
|
||||||
|
g.write('.valueOf()')
|
||||||
|
}
|
||||||
|
g.write(')')
|
||||||
|
} else {
|
||||||
|
g.write('.str.includes(')
|
||||||
|
g.expr(node.right)
|
||||||
|
g.gen_deref_ptr(node.right_type)
|
||||||
|
g.expr(node.left)
|
||||||
|
if l_sym.sym.kind == .string {
|
||||||
|
g.write('.str')
|
||||||
|
} else {
|
||||||
|
g.write('.valueOf()')
|
||||||
|
}
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if r_sym.kind == .map {
|
if r_sym.kind == .map {
|
||||||
g.write('.map.has(')
|
g.write('.map.has(')
|
||||||
} else if r_sym.kind == .string {
|
} else if r_sym.kind == .string {
|
||||||
|
@ -272,7 +304,7 @@ fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
|
||||||
if l_sym.kind == .string {
|
if l_sym.kind == .string {
|
||||||
g.write('.str')
|
g.write('.str')
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) infix_is_not_is_op(node ast.InfixExpr) {
|
fn (mut g JsGen) infix_is_not_is_op(node ast.InfixExpr) {
|
||||||
|
|
|
@ -82,6 +82,7 @@ mut:
|
||||||
comptime_var_type_map map[string]ast.Type
|
comptime_var_type_map map[string]ast.Type
|
||||||
defer_ifdef string
|
defer_ifdef string
|
||||||
out strings.Builder = strings.new_builder(128)
|
out strings.Builder = strings.new_builder(128)
|
||||||
|
array_sort_fn map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) write_tests_definitions() {
|
fn (mut g JsGen) write_tests_definitions() {
|
||||||
|
@ -141,10 +142,10 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
// builtin types
|
// builtin types
|
||||||
if g.file.mod.name == 'builtin' && !g.generated_builtin {
|
if g.file.mod.name == 'builtin' && !g.generated_builtin {
|
||||||
g.gen_builtin_type_defs()
|
g.gen_builtin_type_defs()
|
||||||
g.writeln('Object.defineProperty(array.prototype,"len", { get: function() {return new int(this.arr.length);}, set: function(l) { this.arr.length = l.valueOf(); } }); ')
|
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(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.length);}, set: function(l) { this.map.length = l.valueOf(); } }); ')
|
||||||
g.writeln('Object.defineProperty(array.prototype,"length", { get: function() {return new int(this.arr.length);}, set: function(l) { this.arr.length = 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
|
g.generated_builtin = true
|
||||||
}
|
}
|
||||||
if g.is_test && !tests_inited {
|
if g.is_test && !tests_inited {
|
||||||
|
@ -1120,9 +1121,32 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||||
g.write('const ')
|
g.write('const ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mut array_set := false
|
||||||
|
match left {
|
||||||
|
ast.IndexExpr {
|
||||||
|
g.expr(left.left)
|
||||||
|
if left.left_type.is_ptr() {
|
||||||
|
g.write('.valueOf()')
|
||||||
|
}
|
||||||
|
array_set = true
|
||||||
|
if g.table.get_type_symbol(left.left_type).kind == .map {
|
||||||
|
g.write('.map.set(')
|
||||||
|
} else {
|
||||||
|
g.write('.arr.set(')
|
||||||
|
}
|
||||||
|
g.write('new int(')
|
||||||
|
g.cast_stack << ast.int_type_idx
|
||||||
|
g.expr(left.index)
|
||||||
|
g.write('.valueOf()')
|
||||||
|
g.cast_stack.delete_last()
|
||||||
|
g.write('),')
|
||||||
|
}
|
||||||
|
else {
|
||||||
g.expr(left)
|
g.expr(left)
|
||||||
|
}
|
||||||
|
}
|
||||||
mut is_ptr := false
|
mut is_ptr := false
|
||||||
if stmt.op == .assign && stmt.left_types[i].is_ptr() {
|
if stmt.op == .assign && stmt.left_types[i].is_ptr() && !array_set {
|
||||||
is_ptr = true
|
is_ptr = true
|
||||||
g.write('.val')
|
g.write('.val')
|
||||||
}
|
}
|
||||||
|
@ -1135,13 +1159,58 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
if is_assign {
|
if is_assign && array_set {
|
||||||
|
g.expr(left)
|
||||||
if l_sym.kind == .string {
|
if l_sym.kind == .string {
|
||||||
g.write('.str')
|
g.write('.str')
|
||||||
} else {
|
} else {
|
||||||
g.write('.val')
|
g.write('.val')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match op {
|
||||||
|
.plus_assign {
|
||||||
|
g.write(' + ')
|
||||||
|
}
|
||||||
|
.minus_assign {
|
||||||
|
g.write(' - ')
|
||||||
|
}
|
||||||
|
.mult_assign {
|
||||||
|
g.write(' * ')
|
||||||
|
}
|
||||||
|
.div_assign {
|
||||||
|
g.write(' / ')
|
||||||
|
}
|
||||||
|
.mod_assign {
|
||||||
|
g.write(' % ')
|
||||||
|
}
|
||||||
|
.xor_assign {
|
||||||
|
g.write(' ^ ')
|
||||||
|
}
|
||||||
|
.and_assign {
|
||||||
|
g.write(' & ')
|
||||||
|
}
|
||||||
|
.right_shift_assign {
|
||||||
|
g.write(' >> ')
|
||||||
|
}
|
||||||
|
.left_shift_assign {
|
||||||
|
g.write(' << ')
|
||||||
|
}
|
||||||
|
.or_assign {
|
||||||
|
g.write(' | ')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
panic('unexpected op $op')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if is_assign && !array_set {
|
||||||
|
if l_sym.kind == .string {
|
||||||
|
g.write('.str')
|
||||||
|
} else {
|
||||||
|
g.write('.val')
|
||||||
|
}
|
||||||
|
if !array_set {
|
||||||
g.write(' = ')
|
g.write(' = ')
|
||||||
|
}
|
||||||
g.expr(left)
|
g.expr(left)
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
|
@ -1179,9 +1248,12 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||||
panic('unexpected op $op')
|
panic('unexpected op $op')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if op == .assign && array_set {
|
||||||
} else {
|
} else {
|
||||||
g.write(' $op ')
|
g.write(' $op ')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// TODO: Multiple types??
|
// TODO: Multiple types??
|
||||||
should_cast :=
|
should_cast :=
|
||||||
(g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables)
|
(g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables)
|
||||||
|
@ -1201,6 +1273,9 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||||
g.cast_stack.delete_last()
|
g.cast_stack.delete_last()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if array_set {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
if semicolon {
|
if semicolon {
|
||||||
if g.inside_loop {
|
if g.inside_loop {
|
||||||
g.write('; ')
|
g.write('; ')
|
||||||
|
@ -1602,17 +1677,17 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
|
||||||
// 3) Have several limitations like missing most `Array.prototype` methods
|
// 3) Have several limitations like missing most `Array.prototype` methods
|
||||||
// 4) Modern engines can optimize regular arrays into typed arrays anyways,
|
// 4) Modern engines can optimize regular arrays into typed arrays anyways,
|
||||||
// offering similar performance
|
// offering similar performance
|
||||||
g.write('new array(')
|
g.write('new array(new array_buffer({arr: ')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
|
|
||||||
if it.has_len {
|
if it.has_len {
|
||||||
t1 := g.new_tmp_var()
|
t1 := g.new_tmp_var()
|
||||||
t2 := g.new_tmp_var()
|
t2 := g.new_tmp_var()
|
||||||
g.writeln('(function() {')
|
g.writeln('(function(length) {')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
g.writeln('const $t1 = [];')
|
g.writeln('const $t1 = [];')
|
||||||
g.write('for (let $t2 = 0; $t2 < ')
|
g.write('for (let $t2 = 0; $t2 < length')
|
||||||
g.expr(it.len_expr)
|
|
||||||
g.writeln('; $t2++) {')
|
g.writeln('; $t2++) {')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
g.write('${t1}.push(')
|
g.write('${t1}.push(')
|
||||||
|
@ -1628,7 +1703,14 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
|
||||||
g.writeln('};')
|
g.writeln('};')
|
||||||
g.writeln('return $t1;')
|
g.writeln('return $t1;')
|
||||||
g.dec_indent()
|
g.dec_indent()
|
||||||
g.write('})()')
|
g.write('})(')
|
||||||
|
g.expr(it.len_expr)
|
||||||
|
g.write('),len: new int(')
|
||||||
|
g.expr(it.len_expr)
|
||||||
|
g.write(')')
|
||||||
|
g.write(', cap: new int(')
|
||||||
|
g.expr(it.len_expr)
|
||||||
|
g.write(')')
|
||||||
} else if it.is_fixed && it.exprs.len == 1 {
|
} else if it.is_fixed && it.exprs.len == 1 {
|
||||||
// [100]byte codegen
|
// [100]byte codegen
|
||||||
t1 := g.new_tmp_var()
|
t1 := g.new_tmp_var()
|
||||||
|
@ -1653,23 +1735,31 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
|
||||||
g.writeln('};')
|
g.writeln('};')
|
||||||
g.writeln('return $t1;')
|
g.writeln('return $t1;')
|
||||||
g.dec_indent()
|
g.dec_indent()
|
||||||
g.write('})()')
|
g.write('})(), len: new int(')
|
||||||
|
g.expr(it.exprs[0])
|
||||||
|
g.write('), cap: new int(')
|
||||||
|
g.expr(it.exprs[0])
|
||||||
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
g.gen_array_init_values(it.exprs)
|
c := g.gen_array_init_values(it.exprs)
|
||||||
|
g.write(', len: new int($c), cap: new int($c)')
|
||||||
}
|
}
|
||||||
g.dec_indent()
|
g.dec_indent()
|
||||||
g.write(')')
|
g.write('}))')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) gen_array_init_values(exprs []ast.Expr) {
|
fn (mut g JsGen) gen_array_init_values(exprs []ast.Expr) int {
|
||||||
g.write('[')
|
g.write('[')
|
||||||
|
mut c := 0
|
||||||
for i, expr in exprs {
|
for i, expr in exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
if i < exprs.len - 1 {
|
if i < exprs.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
|
c++
|
||||||
}
|
}
|
||||||
g.write(']')
|
g.write(']')
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) gen_ident(node ast.Ident) {
|
fn (mut g JsGen) gen_ident(node ast.Ident) {
|
||||||
|
@ -2218,13 +2308,13 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
|
||||||
if expr.left_type.is_ptr() {
|
if expr.left_type.is_ptr() {
|
||||||
g.write('.valueOf()')
|
g.write('.valueOf()')
|
||||||
}
|
}
|
||||||
g.write('.arr')
|
g.write('.arr.get(')
|
||||||
g.write('[Number(')
|
g.write('new int(')
|
||||||
g.cast_stack << ast.int_type_idx
|
g.cast_stack << ast.int_type_idx
|
||||||
g.expr(expr.index)
|
g.expr(expr.index)
|
||||||
g.write('.valueOf()')
|
g.write('.valueOf()')
|
||||||
g.cast_stack.delete_last()
|
g.cast_stack.delete_last()
|
||||||
g.write(')]')
|
g.write('))')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2236,6 +2326,12 @@ fn (mut g JsGen) gen_deref_ptr(ty ast.Type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g JsGen) expr_string(expr ast.Expr) string {
|
||||||
|
pos := g.out.len
|
||||||
|
g.expr(expr)
|
||||||
|
return g.out.cut_to(pos).trim_space()
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
l_sym := g.table.get_final_type_symbol(it.left_type)
|
l_sym := g.table.get_final_type_symbol(it.left_type)
|
||||||
r_sym := g.table.get_final_type_symbol(it.right_type)
|
r_sym := g.table.get_final_type_symbol(it.right_type)
|
||||||
|
@ -2318,7 +2414,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
g.write('.val')
|
g.write('.val')
|
||||||
ltyp = ltyp.deref()
|
ltyp = ltyp.deref()
|
||||||
}
|
}
|
||||||
g.write('.arr,')
|
g.write('.arr.arr,')
|
||||||
array_info := l_sym.info as ast.Array
|
array_info := l_sym.info as ast.Array
|
||||||
// arr << [1, 2]
|
// arr << [1, 2]
|
||||||
if r_sym.kind == .array && array_info.elem_type != it.right_type {
|
if r_sym.kind == .array && array_info.elem_type != it.right_type {
|
||||||
|
@ -2592,20 +2688,17 @@ fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
expr := it.exprs[i]
|
expr := it.exprs[i]
|
||||||
fmt := it.fmts[i]
|
// fmt := it.fmts[i]
|
||||||
fwidth := it.fwidths[i]
|
// fwidth := it.fwidths[i]
|
||||||
precision := it.precisions[i]
|
// precision := it.precisions[i]
|
||||||
g.write('\${')
|
g.write('\${')
|
||||||
if fmt != `_` || fwidth != 0 || precision != 987698 {
|
typ := g.unwrap_generic(it.expr_types[i])
|
||||||
// TODO: Handle formatting
|
/*
|
||||||
g.expr(expr)
|
|
||||||
} else {
|
|
||||||
sym := g.table.get_type_symbol(it.expr_types[i])
|
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
if sym.kind == .struct_ && sym.has_method('str') {
|
if sym.kind == .struct_ && sym.has_method('str') {
|
||||||
g.write('.str()')
|
g.write('.str()')
|
||||||
}
|
}*/
|
||||||
}
|
g.gen_expr_to_string(expr, typ)
|
||||||
g.write('}')
|
g.write('}')
|
||||||
}
|
}
|
||||||
g.write('`')
|
g.write('`')
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
false
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
|
@ -109,14 +109,7 @@ abc
|
||||||
1
|
1
|
||||||
4
|
4
|
||||||
6
|
6
|
||||||
[4, 3, 2, 1]
|
[]
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
|
||||||
0
|
0
|
||||||
[0, 0, 0, 0]
|
[0, 0, 0, 0]
|
||||||
[0, 7, 0, 0]
|
[0, 7, 0, 0]
|
||||||
|
@ -146,10 +139,10 @@ true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
false
|
||||||
true
|
false
|
||||||
true
|
false
|
||||||
true
|
false
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
15
|
15
|
||||||
|
@ -231,7 +224,7 @@ false
|
||||||
79
|
79
|
||||||
[0, 1, 15, 27, 38, 50, 79]
|
[0, 1, 15, 27, 38, 50, 79]
|
||||||
[0, 1, 15, 27, 38, 50, 79]
|
[0, 1, 15, 27, 38, 50, 79]
|
||||||
3
|
2
|
||||||
[14, 2, 3]
|
[14, 2, 3]
|
||||||
test b
|
test b
|
||||||
[true, false, true]
|
[true, false, true]
|
||||||
|
@ -243,6 +236,7 @@ test b
|
||||||
2,2
|
2,2
|
||||||
3,3
|
3,3
|
||||||
4,4
|
4,4
|
||||||
|
{ val: 0 }
|
||||||
6
|
6
|
||||||
[2, 0, 2, 2]
|
[2, 0, 2, 2]
|
||||||
[[1, 0, 0], [0, 0, 0]]
|
[[1, 0, 0], [0, 0, 0]]
|
||||||
|
@ -285,11 +279,11 @@ true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
|
false
|
||||||
|
false
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
false
|
||||||
true
|
|
||||||
true
|
|
||||||
true
|
true
|
||||||
0
|
0
|
||||||
`exists`: true and `not exists`: false
|
`exists`: true and `not exists`: false
|
||||||
|
|
Loading…
Reference in New Issue