From 7a67a08d2f08ed6ca7ccda7ab8e0d5a58862a292 Mon Sep 17 00:00:00 2001 From: playX Date: Mon, 9 Aug 2021 01:46:40 +0300 Subject: [PATCH] js: implement codegen for array.sort and implement .any,.all (#11100) --- vlib/builtin/js/array.js.v | 30 ++++++---- vlib/v/gen/js/array.v | 89 ++++++++++++++++++++++++++++ vlib/v/gen/js/js.v | 47 +-------------- vlib/v/gen/js/temp_fast_deep_equal.v | 11 ++++ 4 files changed, 120 insertions(+), 57 deletions(-) create mode 100644 vlib/v/gen/js/array.v diff --git a/vlib/builtin/js/array.js.v b/vlib/builtin/js/array.js.v index 1fc644b71b..e25e627bd0 100644 --- a/vlib/builtin/js/array.js.v +++ b/vlib/builtin/js/array.js.v @@ -87,19 +87,6 @@ pub fn (mut a array) sort_with_compare(compare voidptr) { #a.arr.sort(compare) } -#function $sortComparator(a, b) -#{ -#"use strict"; -#a = a.$toJS(); -#b = b.$toJS(); -# -#if (a > b) return 1; -#if (a < b) return -1; -#return 0; -# -# -#} - pub fn (mut a array) sort() { #a.arr.sort($sortComparator) } @@ -153,6 +140,23 @@ pub fn (a array) str() string { #array.prototype.map = function(callback) { return new builtin.array(this.arr.map(callback)); } #array.prototype.filter = function(callback) { return new array(this.arr.filter( function (it) { return (+callback(it)) != 0; } )); } #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])) +#return true; +# +#return false; +#} + +#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])) +#return false; +# +#return true; +#} // delete deletes array element at index `i`. pub fn (mut a array) delete(i int) { a.delete_many(i, 1) diff --git a/vlib/v/gen/js/array.v b/vlib/v/gen/js/array.v new file mode 100644 index 0000000000..c9d5ef664b --- /dev/null +++ b/vlib/v/gen/js/array.v @@ -0,0 +1,89 @@ +module js + +import v.ast + +const ( + special_array_methods = [ + 'sort', + 'insert', + 'prepend', + ] +) + +fn (mut g JsGen) gen_array_method_call(it ast.CallExpr) { + node := it + match node.name { + 'insert' { + arg2_sym := g.table.get_type_symbol(node.args[1].typ) + is_arg2_array := arg2_sym.kind == .array && node.args[1].typ == node.left_type + if is_arg2_array { + g.write('insert_many(') + } else { + g.write('insert(') + } + + g.expr(node.args[0].expr) + g.write(',') + if is_arg2_array { + g.expr(node.args[1].expr) + g.write('.arr,') + g.expr(node.args[1].expr) + g.write('.len') + } else { + g.expr(node.args[1].expr) + } + g.write(')') + return + } + 'prepend' { + arg_sym := g.table.get_type_symbol(node.args[0].typ) + is_arg_array := arg_sym.kind == .array && node.args[0].typ == node.left_type + if is_arg_array { + g.write('prepend_many(') + } else { + g.write('prepend(') + } + + if is_arg_array { + g.expr(node.args[0].expr) + g.write('.arr, ') + g.expr(node.args[0].expr) + g.write('.len') + } else { + g.expr(node.args[0].expr) + } + g.write(')') + return + } + 'sort' { + 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()') + return + } else { + 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 {} + } +} diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 9778b44944..a5af503e5a 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -1516,50 +1516,9 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { left_sym := g.table.get_type_symbol(it.left_type) if left_sym.kind == .array { node := it - match node.name { - 'insert' { - arg2_sym := g.table.get_type_symbol(node.args[1].typ) - is_arg2_array := arg2_sym.kind == .array && node.args[1].typ == node.left_type - if is_arg2_array { - g.write('insert_many(') - } else { - g.write('insert(') - } - - g.expr(node.args[0].expr) - g.write(',') - if is_arg2_array { - g.expr(node.args[1].expr) - g.write('.arr,') - g.expr(node.args[1].expr) - g.write('.len') - } else { - g.expr(node.args[1].expr) - } - g.write(')') - return - } - 'prepend' { - arg_sym := g.table.get_type_symbol(node.args[0].typ) - is_arg_array := arg_sym.kind == .array && node.args[0].typ == node.left_type - if is_arg_array { - g.write('prepend_many(') - } else { - g.write('prepend(') - } - - if is_arg_array { - g.expr(node.args[0].expr) - g.write('.arr, ') - g.expr(node.args[0].expr) - g.write('.len') - } else { - g.expr(node.args[0].expr) - } - g.write(')') - return - } - else {} + if node.name in special_array_methods { + g.gen_array_method_call(it) + return } } } else { diff --git a/vlib/v/gen/js/temp_fast_deep_equal.v b/vlib/v/gen/js/temp_fast_deep_equal.v index bca6e6175d..a22d2d882a 100644 --- a/vlib/v/gen/js/temp_fast_deep_equal.v +++ b/vlib/v/gen/js/temp_fast_deep_equal.v @@ -74,5 +74,16 @@ function vEq(a, b) { // true if both NaN, false otherwise return a!==a && b!==b; }; + +function \$sortComparator(a, b) +{ +a = a.\$toJS(); +b = b.\$toJS(); +if (a > b) return 1; +if (a < b) return -1; +return 0; + + +} " )