v.gen.js: implement most of array and map methods in builtin/js (#10806)
parent
027be2ecd4
commit
06edbc8a38
|
@ -0,0 +1,114 @@
|
|||
module builtin
|
||||
|
||||
struct array {
|
||||
arr JS.Array
|
||||
pub:
|
||||
len int
|
||||
}
|
||||
|
||||
#function flatIntoArray(target, source, sourceLength, targetIndex, depth) {
|
||||
#"use strict";
|
||||
#
|
||||
#for (var sourceIndex = 0; sourceIndex < sourceLength; ++sourceIndex) {
|
||||
#if (sourceIndex in source) {
|
||||
#var element = source[sourceIndex];
|
||||
#if (depth > 0 && Array.isArray(element))
|
||||
#targetIndex = flatIntoArray(target, element, element.length, targetIndex, depth - 1);
|
||||
#else {
|
||||
#target[targetIndex] = element;
|
||||
#++targetIndex;
|
||||
#}
|
||||
#}
|
||||
#}
|
||||
#return targetIndex;
|
||||
#}
|
||||
#function flatArray(target,depth) {
|
||||
#var array = target
|
||||
#var length = array.length;
|
||||
#var depthNum = 1;
|
||||
#
|
||||
#if (depth !== undefined)
|
||||
#depthNum = +depth
|
||||
#
|
||||
#var result = []
|
||||
#
|
||||
#flatIntoArray(result, array, length, 0, depthNum);
|
||||
#return result;
|
||||
#}
|
||||
|
||||
[unsafe]
|
||||
pub fn (a array) repeat_to_depth(count int, depth int) array {
|
||||
if count < 0 {
|
||||
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);
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
fn (a array) get(ix int) voidptr {
|
||||
mut result := voidptr(0)
|
||||
#result = a.arr[ix]
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
pub fn (a array) repeat(count int) array {
|
||||
unsafe {
|
||||
return a.repeat_to_depth(count, 0)
|
||||
}
|
||||
}
|
||||
|
||||
fn empty_array() array {
|
||||
mut arr := array{}
|
||||
#arr = new array([])
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
fn (a &array) set_len(i int) {
|
||||
#a.arr.length=i
|
||||
}
|
||||
|
||||
pub fn (mut a array) sort_with_comparator(compare voidptr) {
|
||||
#a.arr.sort(compare)
|
||||
}
|
||||
|
||||
pub fn (mut a array) sort() {
|
||||
#a.arr.sort()
|
||||
}
|
||||
|
||||
pub fn (a array) index(v string) int {
|
||||
for i in 0 .. a.len {
|
||||
#if (a.arr[i].toString() == v.toString())
|
||||
|
||||
{
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
pub fn (a array) slice(start int, end int) array {
|
||||
mut result := a
|
||||
#result = new array(a.arr.slice(start,end))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
pub fn (mut a array) insert(i int, val voidptr) {
|
||||
#a.arr.splice(i,0,val)
|
||||
}
|
||||
|
||||
fn (a array) push(val voidptr) {
|
||||
#a.arr.push(val)
|
||||
}
|
||||
|
||||
#array.prototype[Symbol.iterator] = function () { return this.arr[Symbol.iterator](); }
|
||||
#array.prototype.entries = function () { return this.arr.entries(); }
|
||||
#array.prototype.map = function(callback) { return this.arr.map(callback); }
|
||||
#array.prototype.filter = function(callback) { return this.arr.filter(callback); }
|
|
@ -0,0 +1,14 @@
|
|||
module builtin
|
||||
|
||||
struct map {
|
||||
m JS.Map
|
||||
len int
|
||||
}
|
||||
|
||||
// Removes the mapping of a particular key from the map.
|
||||
[unsafe]
|
||||
pub fn (mut m map) delete(key voidptr) {
|
||||
#m.m.delete(key)
|
||||
}
|
||||
|
||||
pub fn (m &map) free() {}
|
|
@ -41,12 +41,18 @@ pub fn (s string) bool() bool {
|
|||
}
|
||||
|
||||
pub fn (s string) split(dot string) []string {
|
||||
return s.str.split(dot.str).map(string(it))
|
||||
mut arr := s.str.split(dot.str).map(string(it))
|
||||
#arr = new array(arr)
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
pub fn (s string) bytes() []byte {
|
||||
sep := ''
|
||||
return s.str.split(sep.str).map(it.charCodeAt(0))
|
||||
mut arr := s.str.split(sep.str).map(it.charCodeAt(0))
|
||||
#arr = new array(arr)
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
pub fn (s string) capitalize() string {
|
|
@ -124,6 +124,9 @@ 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 this.arr.length;}, set: function(l) { this.arr.length = l; } }); ')
|
||||
g.writeln('Object.defineProperty(map.prototype,"len", { get: function() {return this.map.length;}, set: function(l) { this.map.length = l; } }); ')
|
||||
g.writeln('Object.defineProperty(array.prototype,"length", { get: function() {return this.arr.length;}, set: function(l) { this.arr.length = l; } }); ')
|
||||
g.generated_builtin = true
|
||||
}
|
||||
|
||||
|
@ -1005,6 +1008,13 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
|
|||
g.write('${it.params[0].name} = this')
|
||||
}
|
||||
g.writeln(') {')
|
||||
for i, arg in args {
|
||||
is_varg := i == args.len - 1 && it.is_variadic
|
||||
if is_varg {
|
||||
name := g.js_name(arg.name)
|
||||
g.writeln('$name = new array($name);')
|
||||
}
|
||||
}
|
||||
g.stmts(it.stmts)
|
||||
g.write('}')
|
||||
if is_main {
|
||||
|
@ -1273,6 +1283,8 @@ 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.inc_indent()
|
||||
if it.has_len {
|
||||
t1 := g.new_tmp_var()
|
||||
t2 := g.new_tmp_var()
|
||||
|
@ -1300,6 +1312,8 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
|
|||
} else {
|
||||
g.gen_array_init_values(it.exprs)
|
||||
}
|
||||
g.dec_indent()
|
||||
g.write(')')
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_array_init_values(exprs []ast.Expr) {
|
||||
|
@ -1512,9 +1526,9 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
|
|||
g.expr(expr.left)
|
||||
if expr.is_setter {
|
||||
g.inside_map_set = true
|
||||
g.write('.set(')
|
||||
g.write('.map.set(')
|
||||
} else {
|
||||
g.write('.get(')
|
||||
g.write('.map.get(')
|
||||
}
|
||||
g.expr(expr.index)
|
||||
g.write('.toString()')
|
||||
|
@ -1534,6 +1548,7 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
|
|||
} else {
|
||||
// TODO Does this cover all cases?
|
||||
g.expr(expr.left)
|
||||
g.write('.arr')
|
||||
g.write('[')
|
||||
g.cast_stack << ast.int_type_idx
|
||||
g.expr(expr.index)
|
||||
|
@ -1568,8 +1583,9 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
g.write(')')
|
||||
}
|
||||
} else if l_sym.kind == .array && it.op == .left_shift { // arr << 1
|
||||
g.write('Array.prototype.push.call(')
|
||||
g.expr(it.left)
|
||||
g.write('.push(')
|
||||
g.write('.arr,')
|
||||
// arr << [1, 2]
|
||||
if r_sym.kind == .array {
|
||||
g.write('...')
|
||||
|
@ -1579,11 +1595,11 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
} else if r_sym.kind in [.array, .map, .string] && it.op in [.key_in, .not_in] {
|
||||
g.expr(it.right)
|
||||
if r_sym.kind == .map {
|
||||
g.write('.has(')
|
||||
g.write('.map.has(')
|
||||
} else if r_sym.kind == .string {
|
||||
g.write('.str.includes(')
|
||||
} else {
|
||||
g.write('.includes(')
|
||||
g.write('.arr.includes(')
|
||||
}
|
||||
g.expr(it.left)
|
||||
if l_sym.kind == .string {
|
||||
|
@ -1680,6 +1696,8 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
|
|||
// value_typ_sym := g.table.get_type_symbol(it.value_type)
|
||||
// key_typ_str := util.no_dots(key_typ_sym.name)
|
||||
// value_typ_str := util.no_dots(value_typ_sym.name)
|
||||
g.writeln('new map(')
|
||||
g.inc_indent()
|
||||
if it.vals.len > 0 {
|
||||
g.writeln('new Map([')
|
||||
g.inc_indent()
|
||||
|
@ -1700,6 +1718,8 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
|
|||
} else {
|
||||
g.write('new Map()')
|
||||
}
|
||||
g.dec_indent()
|
||||
g.write(')')
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) {
|
||||
|
@ -1843,16 +1863,16 @@ fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) {
|
|||
// TODO: call.language always seems to be "v", parser bug?
|
||||
if g.call_stack.len > 0 {
|
||||
call := g.call_stack[g.call_stack.len - 1]
|
||||
// if call.language == .js {
|
||||
for t in call.args {
|
||||
if t.expr is ast.IntegerLiteral {
|
||||
if t.expr == it {
|
||||
g.write(it.val)
|
||||
return
|
||||
if call.language == .js {
|
||||
for t in call.args {
|
||||
if t.expr is ast.IntegerLiteral {
|
||||
if t.expr == it {
|
||||
g.write(it.val)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
// Skip cast if type is the same as the parrent caster
|
||||
|
|
Loading…
Reference in New Issue