mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
js: array improvements (#11952)
This commit is contained in:
parent
f3757a7cd1
commit
863dd0b23e
@ -1,12 +1,69 @@
|
||||
module builtin
|
||||
|
||||
/// 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
|
||||
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 JS.Array
|
||||
arr array_buffer
|
||||
pub:
|
||||
len 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) {
|
||||
#"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')
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// last returns the last element of the array.
|
||||
pub fn (a array) last() voidptr {
|
||||
mut res := voidptr(0)
|
||||
#res = a.arr[a.len-1];
|
||||
#res = a.arr.get(new int(a.len-1));
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fn (a array) get(ix int) voidptr {
|
||||
mut result := voidptr(0)
|
||||
#result = a.arr[ix]
|
||||
#result = a.arr.get(ix)
|
||||
|
||||
return result
|
||||
}
|
||||
@ -72,28 +136,34 @@ pub fn (a array) repeat(count int) array {
|
||||
}
|
||||
}
|
||||
|
||||
fn empty_array() array {
|
||||
mut arr := array{}
|
||||
#arr = new array([])
|
||||
#function makeEmptyArray() { return new array(new array_buffer({})); }
|
||||
#function makeEmtpyJSArray() { return 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) {
|
||||
#a.arr.length=i
|
||||
#a.arr.arr.length=i
|
||||
}
|
||||
|
||||
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() {
|
||||
#a.val.arr.sort($sortComparator)
|
||||
#a.val.arr.arr.sort($sortComparator)
|
||||
}
|
||||
|
||||
pub fn (a array) index(v string) int {
|
||||
for i in 0 .. a.len {
|
||||
#if (a.arr[i].toString() == v.toString())
|
||||
#if (a.arr.get(i).toString() == v.toString())
|
||||
|
||||
{
|
||||
return i
|
||||
@ -104,39 +174,80 @@ pub fn (a array) index(v string) int {
|
||||
|
||||
pub fn (a array) slice(start int, end int) array {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
#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 {
|
||||
mut res := ''
|
||||
#res = new string(a.val.arr.join(separator +''));
|
||||
#res = new string(a.val.arr.arr.join(separator +''));
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
fn (a array) push(val voidptr) {
|
||||
#a.arr.push(val)
|
||||
fn (mut a array) push(val voidptr) {
|
||||
#a.val.arr.make_copy()
|
||||
#a.val.arr.arr.push(val)
|
||||
}
|
||||
|
||||
#array.prototype[Symbol.iterator] = function () { return this.arr[Symbol.iterator](); }
|
||||
#array.prototype.entries = function () { let result = []; for (const [key,val] of this.arr.entries()) { result.push([new int(key), val]); } return result[Symbol.iterator](); }
|
||||
#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; } )); }
|
||||
fn v_filter(arr array, callback fn (voidptr) bool) array {
|
||||
mut filtered := empty_array()
|
||||
|
||||
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; } })
|
||||
#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); } }
|
||||
#for (let i = 0;i < this.arr.length;i++)
|
||||
#if (val(this.arr[i]))
|
||||
#for (let i = 0;i < this.arr.arr.length;i++)
|
||||
#if (val(this.arr.get(i)))
|
||||
#return true;
|
||||
#
|
||||
#return false;
|
||||
@ -144,12 +255,17 @@ fn (a array) push(val voidptr) {
|
||||
|
||||
#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); } }
|
||||
#for (let i = 0;i < this.arr.length;i++)
|
||||
#if (!val(this.arr[i]))
|
||||
#for (let i = 0;i < this.arr.arr.length;i++)
|
||||
#if (!val(this.arr.get(i)))
|
||||
#return false;
|
||||
#
|
||||
#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`.
|
||||
pub fn (mut a array) delete(i int) {
|
||||
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`
|
||||
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.
|
||||
@ -172,48 +289,52 @@ pub fn (mut a array) prepend_many(val voidptr, size int) {
|
||||
}
|
||||
|
||||
pub fn (a array) reverse() array {
|
||||
mut res := array{}
|
||||
#res.arr = Array.from(a.arr).reverse()
|
||||
mut res := empty_array()
|
||||
#res.arr.arr = Array.from(a.arr).reverse()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
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,
|
||||
// resulting in a single output value.
|
||||
pub fn (a array) reduce(iter fn (int, int) int, accum_start int) int {
|
||||
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])
|
||||
#}
|
||||
#}*/
|
||||
for i in 0 .. a.len {
|
||||
accum_ = iter(accum_, a.get(i))
|
||||
}
|
||||
|
||||
return accum_
|
||||
}
|
||||
|
||||
pub fn (mut a array) pop() voidptr {
|
||||
mut res := voidptr(0)
|
||||
#res = a.val.arr.pop()
|
||||
#a.val.arr.make_copy()
|
||||
#res = a.val.arr.arr.pop()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (a array) first() voidptr {
|
||||
mut res := voidptr(0)
|
||||
#res = a.arr[0]
|
||||
#res = a.arr.get(new int(0))
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
#array.prototype.toString = function () {
|
||||
#let res = "["
|
||||
#for (let i = 0; i < this.arr.length;i++) {
|
||||
#res += this.arr[i].toString();
|
||||
#if (i != this.arr.length-1)
|
||||
#for (let i = 0; i < this.arr.arr.length;i++) {
|
||||
#res += this.arr.get(i).toString();
|
||||
#if (i != this.arr.arr.length-1)
|
||||
#res += ', '
|
||||
#}
|
||||
#res += ']'
|
||||
@ -221,16 +342,11 @@ pub fn (a array) first() voidptr {
|
||||
#
|
||||
#}
|
||||
|
||||
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
|
||||
}
|
||||
pub fn (a array) contains(key voidptr) bool
|
||||
|
||||
// delete_last effectively removes last element of an array.
|
||||
pub fn (mut a array) delete_last() {
|
||||
#a.val.arr.pop();
|
||||
#a.val.arr.arr.pop();
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
@ -240,7 +356,7 @@ pub fn (a &array) free() {
|
||||
// todo: once (a []byte) will work rewrite this
|
||||
pub fn (a array) bytestr() string {
|
||||
res := ''
|
||||
#a.arr.forEach((item) => res.str += String.fromCharCode(+item))
|
||||
#a.arr.arr.forEach((item) => res.str += String.fromCharCode(+item))
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ pub fn (s string) bool() bool {
|
||||
|
||||
pub fn (s string) split(dot string) []string {
|
||||
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
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ pub fn (mut b Builder) writeln(s string) {
|
||||
pub fn (mut b Builder) str() string {
|
||||
s := ''
|
||||
|
||||
#for (const c of b.val.buf.arr)
|
||||
#for (const c of b.val.buf.arr.arr)
|
||||
#s.str += String.fromCharCode(+c)
|
||||
|
||||
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)
|
||||
fn_builder.writeln('function ${fn_name}(a, v) {')
|
||||
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 {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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 {
|
||||
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}')
|
||||
@ -131,49 +134,7 @@ fn (mut g JsGen) gen_array_method_call(it ast.CallExpr) {
|
||||
return
|
||||
}
|
||||
'sort' {
|
||||
g.write('array')
|
||||
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('})')
|
||||
}
|
||||
g.gen_array_sort(node)
|
||||
}
|
||||
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('\tfor (let i = 0; i < a.len; ++i) {')
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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}')
|
||||
@ -248,3 +212,80 @@ fn (mut g JsGen) gen_array_contains_method(left_type ast.Type) string {
|
||||
}
|
||||
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) {')
|
||||
// compare every pair of elements of the two arrays
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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 {
|
||||
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 {
|
||||
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}')
|
||||
@ -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) {')
|
||||
// compare every pair of elements of the two fixed arrays
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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() {
|
||||
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 {
|
||||
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 {
|
||||
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}')
|
||||
@ -281,7 +281,7 @@ fn (mut g JsGen) gen_map_equality_fn(left_type ast.Type) string {
|
||||
g.definitions.writeln(fn_builder.str())
|
||||
}
|
||||
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}')
|
||||
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 {
|
||||
g.definitions.writeln('\t\tlet it = ${elem_str_fn_name}();')
|
||||
} 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 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 is_elem_ptr {
|
||||
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}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}')
|
||||
} 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] {
|
||||
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 {
|
||||
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 {
|
||||
// tmp_str := str_intp_rune('${elem_str_fn_name}( a[i] $deref)')
|
||||
// g.definitions.writeln('\t\tstrings__Builder_write_string(sb, $tmp_str);')
|
||||
} 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}) {')
|
||||
|
@ -405,8 +405,8 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
||||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
val_name: 'arr'
|
||||
default_value: 'new Array()'
|
||||
constructor: 'this.arr = arr'
|
||||
default_value: 'new array_buffer({})'
|
||||
constructor: 'this.arr = arr\nif (arr.index_start.val != 0) { v_makeSlice(this); } '
|
||||
value_of: 'this'
|
||||
to_string: 'JSON.stringify(this.arr.map(it => it.valueOf()))'
|
||||
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
|
||||
arg_name := g.js_name(arg.name)
|
||||
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 {
|
||||
if arg.typ.is_ptr() || arg.is_mut {
|
||||
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 {
|
||||
g.expr(node.left)
|
||||
g.gen_deref_ptr(left.typ)
|
||||
g.write('.arr,...')
|
||||
g.write('.arr.arr,...')
|
||||
g.expr(node.right)
|
||||
g.gen_deref_ptr(right.typ)
|
||||
g.write('.arr')
|
||||
g.write('.arr.arr')
|
||||
g.write(')')
|
||||
} else {
|
||||
g.expr(node.left)
|
||||
g.gen_deref_ptr(left.typ)
|
||||
g.write('.arr,')
|
||||
g.write('.arr.arr,')
|
||||
g.expr(node.right)
|
||||
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) {
|
||||
l_sym := g.table.get_final_type_symbol(node.left_type)
|
||||
r_sym := g.table.get_final_type_symbol(node.right_type)
|
||||
l_sym := g.unwrap(node.left_type)
|
||||
r_sym := g.unwrap(node.right_type)
|
||||
if node.op == .not_in {
|
||||
g.write('!')
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.gen_deref_ptr(node.right_type)
|
||||
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.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 {
|
||||
g.write('.map.has(')
|
||||
} 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 {
|
||||
g.write('.str')
|
||||
}
|
||||
g.write(')')
|
||||
g.write(')')*/
|
||||
}
|
||||
|
||||
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
|
||||
defer_ifdef string
|
||||
out strings.Builder = strings.new_builder(128)
|
||||
array_sort_fn map[string]bool
|
||||
}
|
||||
|
||||
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
|
||||
if g.file.mod.name == 'builtin' && !g.generated_builtin {
|
||||
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(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
|
||||
}
|
||||
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.expr(left)
|
||||
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)
|
||||
}
|
||||
}
|
||||
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
|
||||
g.write('.val')
|
||||
}
|
||||
@ -1135,13 +1159,58 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||
}
|
||||
g.write(')')
|
||||
} else {
|
||||
if is_assign {
|
||||
if is_assign && array_set {
|
||||
g.expr(left)
|
||||
if l_sym.kind == .string {
|
||||
g.write('.str')
|
||||
} else {
|
||||
g.write('.val')
|
||||
}
|
||||
g.write(' = ')
|
||||
|
||||
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.expr(left)
|
||||
|
||||
match op {
|
||||
@ -1180,7 +1249,10 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.write(' $op ')
|
||||
if op == .assign && array_set {
|
||||
} else {
|
||||
g.write(' $op ')
|
||||
}
|
||||
}
|
||||
// TODO: Multiple types??
|
||||
should_cast :=
|
||||
@ -1201,6 +1273,9 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) {
|
||||
g.cast_stack.delete_last()
|
||||
}
|
||||
}
|
||||
if array_set {
|
||||
g.write(')')
|
||||
}
|
||||
if semicolon {
|
||||
if g.inside_loop {
|
||||
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
|
||||
// 4) Modern engines can optimize regular arrays into typed arrays anyways,
|
||||
// offering similar performance
|
||||
g.write('new array(')
|
||||
g.write('new array(new array_buffer({arr: ')
|
||||
g.inc_indent()
|
||||
|
||||
if it.has_len {
|
||||
t1 := g.new_tmp_var()
|
||||
t2 := g.new_tmp_var()
|
||||
g.writeln('(function() {')
|
||||
g.writeln('(function(length) {')
|
||||
g.inc_indent()
|
||||
g.writeln('const $t1 = [];')
|
||||
g.write('for (let $t2 = 0; $t2 < ')
|
||||
g.expr(it.len_expr)
|
||||
g.write('for (let $t2 = 0; $t2 < length')
|
||||
|
||||
g.writeln('; $t2++) {')
|
||||
g.inc_indent()
|
||||
g.write('${t1}.push(')
|
||||
@ -1628,7 +1703,14 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
|
||||
g.writeln('};')
|
||||
g.writeln('return $t1;')
|
||||
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 {
|
||||
// [100]byte codegen
|
||||
t1 := g.new_tmp_var()
|
||||
@ -1653,23 +1735,31 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
|
||||
g.writeln('};')
|
||||
g.writeln('return $t1;')
|
||||
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 {
|
||||
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.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('[')
|
||||
mut c := 0
|
||||
for i, expr in exprs {
|
||||
g.expr(expr)
|
||||
if i < exprs.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
c++
|
||||
}
|
||||
g.write(']')
|
||||
return c
|
||||
}
|
||||
|
||||
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() {
|
||||
g.write('.valueOf()')
|
||||
}
|
||||
g.write('.arr')
|
||||
g.write('[Number(')
|
||||
g.write('.arr.get(')
|
||||
g.write('new int(')
|
||||
g.cast_stack << ast.int_type_idx
|
||||
g.expr(expr.index)
|
||||
g.write('.valueOf()')
|
||||
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) {
|
||||
l_sym := g.table.get_final_type_symbol(it.left_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')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write('.arr,')
|
||||
g.write('.arr.arr,')
|
||||
array_info := l_sym.info as ast.Array
|
||||
// arr << [1, 2]
|
||||
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
|
||||
}
|
||||
expr := it.exprs[i]
|
||||
fmt := it.fmts[i]
|
||||
fwidth := it.fwidths[i]
|
||||
precision := it.precisions[i]
|
||||
// fmt := it.fmts[i]
|
||||
// fwidth := it.fwidths[i]
|
||||
// precision := it.precisions[i]
|
||||
g.write('\${')
|
||||
if fmt != `_` || fwidth != 0 || precision != 987698 {
|
||||
// TODO: Handle formatting
|
||||
g.expr(expr)
|
||||
} else {
|
||||
sym := g.table.get_type_symbol(it.expr_types[i])
|
||||
g.expr(expr)
|
||||
typ := g.unwrap_generic(it.expr_types[i])
|
||||
/*
|
||||
g.expr(expr)
|
||||
if sym.kind == .struct_ && sym.has_method('str') {
|
||||
g.write('.str()')
|
||||
}
|
||||
}
|
||||
}*/
|
||||
g.gen_expr_to_string(expr, typ)
|
||||
g.write('}')
|
||||
}
|
||||
g.write('`')
|
||||
|
30
vlib/v/gen/js/tests/testdata/array.out
vendored
30
vlib/v/gen/js/tests/testdata/array.out
vendored
@ -29,7 +29,7 @@
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
true
|
||||
true
|
||||
@ -109,14 +109,7 @@ abc
|
||||
1
|
||||
4
|
||||
6
|
||||
[4, 3, 2, 1]
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
[]
|
||||
0
|
||||
[0, 0, 0, 0]
|
||||
[0, 7, 0, 0]
|
||||
@ -146,10 +139,10 @@ true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
true
|
||||
true
|
||||
15
|
||||
@ -231,7 +224,7 @@ false
|
||||
79
|
||||
[0, 1, 15, 27, 38, 50, 79]
|
||||
[0, 1, 15, 27, 38, 50, 79]
|
||||
3
|
||||
2
|
||||
[14, 2, 3]
|
||||
test b
|
||||
[true, false, true]
|
||||
@ -243,6 +236,7 @@ test b
|
||||
2,2
|
||||
3,3
|
||||
4,4
|
||||
{ val: 0 }
|
||||
6
|
||||
[2, 0, 2, 2]
|
||||
[[1, 0, 0], [0, 0, 0]]
|
||||
@ -285,11 +279,11 @@ true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
0
|
||||
`exists`: true and `not exists`: false
|
||||
@ -305,4 +299,4 @@ Numbers{
|
||||
odds: [3, 5, 7]
|
||||
evens: [2, 6, 10]
|
||||
}
|
||||
[[10, 10, 10], [10, 10, 10], [10, 10, 10]]
|
||||
[[10, 10, 10], [10, 10, 10], [10, 10, 10]]
|
||||
|
Loading…
Reference in New Issue
Block a user