diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 05a0222ae3..12c8a0ac86 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -1196,15 +1196,35 @@ fn (mut g JsGen) gen_index_expr(it ast.IndexExpr) { } fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) { - g.expr(it.left) + l_sym := g.table.get_type_symbol(it.left_type) + r_sym := g.table.get_type_symbol(it.right_type) - mut op := it.op.str() - // in js == is non-strict & === is strict, always do strict - if op == '==' { op = '===' } - else if op == '!=' { op = '!==' } + if l_sym.kind == .array && it.op == .left_shift { // arr << 1 + g.expr(it.left) + g.write('.push(') + if r_sym.kind == .array { g.write('...') } // arr << [1, 2] + g.expr(it.right) + g.write(')') + } else if it.op == .key_is { // foo is Foo + g.write('/*') + g.expr(it.left) + g.write(' is $r_sym.name') + g.write('*/0') + // TODO + } else { + g.expr(it.left) - g.write(' $op ') - g.expr(it.right) + // in js == is non-strict & === is strict, always do strict + if it.op == .eq { + g.write(' === ') + } else if it.op == .ne { + g.write(' !== ') + } else { + g.write(' $it.op ') + } + + g.expr(it.right) + } } diff --git a/vlib/v/gen/js/tests/array.js b/vlib/v/gen/js/tests/array.js index 84c836cd17..ce43b3aa7c 100644 --- a/vlib/v/gen/js/tests/array.js +++ b/vlib/v/gen/js/tests/array.js @@ -1,5 +1,5 @@ // V_COMMIT_HASH 0de70e8 -// V_CURRENT_COMMIT_HASH 4271eb4 +// V_CURRENT_COMMIT_HASH 2eac2a5 // Generated by the V compiler "use strict"; @@ -70,6 +70,9 @@ const main = (function () { arr2[0] = 1; arr2[0 + 1] = 2; builtin.println(arr2); + arr2.push(6); + arr2.push(...[7, 8, 9]); + builtin.println(arr2); /** @type {string} - slice4 */ const slice4 = idx1.slice(0, 4); builtin.println(slice4); diff --git a/vlib/v/gen/js/tests/array.v b/vlib/v/gen/js/tests/array.v index 56938f292c..32e68109b7 100644 --- a/vlib/v/gen/js/tests/array.v +++ b/vlib/v/gen/js/tests/array.v @@ -24,6 +24,15 @@ arr2[0] = 1 arr2[0 + 1] = 2 println(arr2) +// TODO: This does not work for now +// arr2[0..1] = arr2[3..4] +// println(arr2) + +// Array push operator +arr2 << 6 +arr2 << [7, 8, 9] +println(arr2) + // String slices slice4 := idx1[..4] println(slice4) // 'Back' @@ -31,11 +40,6 @@ println(slice4) // 'Back' // String indexes idx2 := slice4[0] -// TODO: This does not work for now -// arr2[0..1] = arr2[3..4] -// println(arr2) - - // Maps mut m := map[string]string key := 'key' diff --git a/vlib/v/gen/js/tests/life.js b/vlib/v/gen/js/tests/life.js new file mode 100644 index 0000000000..cf06263c67 --- /dev/null +++ b/vlib/v/gen/js/tests/life.js @@ -0,0 +1,206 @@ +// V_COMMIT_HASH 0de70e8 +// V_CURRENT_COMMIT_HASH 1c2dbea +// Generated by the V compiler + +"use strict"; + +const _CONSTS = Object.freeze({ + /** @type {number} - w */ + w: 30, + /** @type {number} - h */ + h: 30 +}); + +/** @namespace builtin */ +const builtin = (function () { + /** + * @param {any} s + * @returns {void} + * @function + */ + function println(s) { + console.log(s); + } + + /** + * @param {any} s + * @returns {void} + * @function + */ + function print(s) { + process.stdout.write(s); + } + + /* module exports */ + return { + println, + print, + }; +})(); + +/** @namespace main */ +const main = (function () { + /** + * @returns {void} + * @function + */ + function clear() { + console.clear(); + } + +/** + * @param {boolean[]} game + * @param {number} x + * @param {number} y + * @returns {boolean} + * @function + */ + function get(game, x, y) { + if (y < 0 || x < 0) { + return false; + } + + if (y >= _CONSTS.h || x >= _CONSTS.w) { + return false; + } + + return game[y][x]; + } + + /** + * @param {boolean[]} game + * @param {number} x + * @param {number} y + * @returns {number} + * @function + */ + function neighbours(game, x, y) { + /** @type {number} - count */ + let count = 0; + if (get(game, x - 1, y - 1)) { + count++; + } + + if (get(game, x, y - 1)) { + count++; + } + + if (get(game, x + 1, y - 1)) { + count++; + } + + if (get(game, x - 1, y)) { + count++; + } + + if (get(game, x + 1, y)) { + count++; + } + + if (get(game, x - 1, y + 1)) { + count++; + } + + if (get(game, x, y + 1)) { + count++; + } + + if (get(game, x + 1, y + 1)) { + count++; + } + + return count; + } + + /** + * @param {boolean[]} game + * @returns {boolean[]} + * @function + */ + function step(game) { + /** @type {boolean[]} - new_game */ + let new_game = [[]]; + for (let y = 0; y < game.length; ++y) { + let row = game[y]; + /** @type {boolean[]} - new_row */ + let new_row = []; + new_game[y] = new_row; + for (let x = 0; x < row.length; ++x) { + let cell = row[x]; + /** @type {number} - count */ + const count = neighbours(game, x, y); + new_row[x] = cell && count === 2 || count === 3; + } + + } + + return new_game; + } + + /** + * @param {boolean[]} row + * @returns {string} + * @function + */ + function row_str(row) { + /** @type {string} - str */ + let str = ""; + for (let _tmp1 = 0; _tmp1 < row.length; ++_tmp1) { + let cell = row[_tmp1]; + if (cell) { + str += "◼ "; + } else { + str += "◻ "; + } + + } + + return str; + } + + /** + * @param {boolean[]} game + * @returns {void} + * @function + */ + function show(game) { + clear(); + for (let _tmp2 = 0; _tmp2 < game.length; ++_tmp2) { + let row = game[_tmp2]; + builtin.println(row_str(row)); + } + + } + + /* program entry point */ + (function() { + /** @type {boolean[]} - game */ + let game = [[]]; + for (let y = 0; y < _CONSTS.h; ++y) { + /** @type {boolean[]} - row */ + let row = []; + for (let x = 0; x < _CONSTS.w; ++x) { + row[x] = false; + } + + game[y] = row; + } + + game[11][15] = true; + game[11][16] = true; + game[12][16] = true; + game[10][21] = true; + game[12][20] = true; + game[12][21] = true; + game[12][22] = true; + setInterval(function () { + show(game); + game = step(game); + }, 500); + })(); + + /* module exports */ + return {}; +})(); + + diff --git a/vlib/v/gen/js/tests/life.v b/vlib/v/gen/js/tests/life.v new file mode 100644 index 0000000000..029d3f489b --- /dev/null +++ b/vlib/v/gen/js/tests/life.v @@ -0,0 +1,74 @@ +fn JS.setInterval(f fn (), ms int) +fn JS.console.clear() +fn clear() { JS.console.clear() } + +const (w = 30 h = 30) + +fn get(game [][]bool, x int, y int) bool { + if y < 0 || x < 0 { return false } + if y >= h || x >= w { return false } + + return game[y][x] +} + +fn neighbours(game [][]bool, x int, y int) int { + mut count := 0 + if get(game, x-1, y-1) { count++ } + if get(game, x, y-1) { count++ } + if get(game, x+1, y-1) { count++ } + if get(game, x-1, y) { count++ } + if get(game, x+1, y) { count++ } + if get(game, x-1, y+1) { count++ } + if get(game, x, y+1) { count++ } + if get(game, x+1, y+1) { count++ } + return count +} + +fn step(game [][]bool) [][]bool { + mut new_game := [[]bool{}] + for y, row in game { + mut new_row := []bool{} + new_game[y] = new_row + for x, cell in row { + count := neighbours(game, x, y) + new_row[x] = cell && count == 2 || count == 3 // TODO: count in [2, 3] + } + } + return new_game +} + +fn row_str(row []bool) string { + mut str := '' + for cell in row { + if cell { str += '◼ ' } + else { str += '◻ ' } + } + return str +} + +fn show(game [][]bool) { + clear() + for row in game { + println(row_str(row)) + } +} + +mut game := [[]bool{}] + +for y in 0..h { + mut row := []bool{} + for x in 0..w { + row[x] = false + } + game[y] = row +} + +game[11][15] = true +game[11][16] = true +game[12][16] = true +game[10][21] = true +game[12][20] = true +game[12][21] = true +game[12][22] = true + +JS.setInterval(fn () { show(game) game = step(game) }, 500)