diff --git a/examples/game_of_life/life.v b/examples/game_of_life/life.v index 0f3b7c7ef0..037a5303c4 100644 --- a/examples/game_of_life/life.v +++ b/examples/game_of_life/life.v @@ -1,25 +1,85 @@ -module main - +import term +import rand import time -import automaton -fn print_automaton(a &automaton.Automaton) { - for y := 1; y < a.field.maxy; y++ { - mut s := ' ' - for x := 1; x < a.field.maxx; x++ { - cell := a.field.get(x, y) - s += if cell == 1 { '@' } else { '.' } - } - println(s) +const ( + cell = '█' + nothing = ' ' + switches = { + cell: nothing + nothing: cell } - println('') + transformers = [nothing, cell] +) + +struct Game { +mut: + grid [][]string +} + +fn (g Game) get_surrounding_alive_count(x int, y int) int { + mut count := 0 + for i := x - 1; i <= x + 1; i++ { + for j := y - 1; j <= y + 1; j++ { + if (i != x || j != y) && i >= 0 && j >= 0 && i < g.grid.len && j < g.grid[x].len { + if g.grid[i][j] == cell { + count++ + } + } + } + } + return count +} + +fn (mut g Game) evolve() { + mut temp_grid := [][]string{} + for x in 0 .. g.grid.len { + temp_grid << []string{} + for y in 0 .. g.grid[x].len { + count := g.get_surrounding_alive_count(x, y) + if count == 3 || ((g.grid[x][y] == cell) && count == 2) { + temp_grid[x] << cell + } else { + temp_grid[x] << nothing + } + } + } + + g.grid = temp_grid +} + +fn (mut g Game) display() { + for y in 0 .. g.grid[0].len { + mut line := '' + for x in 0 .. g.grid.len { + line += g.grid[x][y] + } + println(line) + } +} + +fn new_game() Game { + w, h := term.get_terminal_size() + mut grid := [][]string{} + for x in 0 .. w { + grid << []string{} + for _ in 0 .. h { + is_live := rand.f64() > 0.82 + icon := transformers[int(is_live)] + grid[x] << icon + } + } + return Game{grid} } fn main() { - mut a := automaton.gun() + mut g := new_game() + + g.display() for { - a.update() - print_automaton(a) + g.evolve() + term.erase_clear() + g.display() time.sleep(100 * time.millisecond) } } diff --git a/vlib/os/os.js.v b/vlib/os/os.js.v index bdcfa556dc..c9e130d254 100644 --- a/vlib/os/os.js.v +++ b/vlib/os/os.js.v @@ -10,8 +10,10 @@ pub const ( args = []string{} ) -$if js_node { - #$process.argv.forEach(function(val,index) { os__args.arr[index] = new string(val); }) +fn init() { + $if js_node { + #$process.argv.forEach(function(val,index) { os__args.arr[index] = new string(val); }) + } } // real_path returns the full absolute path for fpath, with all relative ../../, symlinks and so on resolved. diff --git a/vlib/rand/constants/constants.v b/vlib/rand/constants/constants.v index 76fe211dab..c70d3e4895 100644 --- a/vlib/rand/constants/constants.v +++ b/vlib/rand/constants/constants.v @@ -4,7 +4,7 @@ module constants pub const ( lower_mask = u64(0x00000000FFFFFFFF) max_u32 = 0xFFFFFFFF - max_u64 = 0xFFFFFFFFFFFFFFFF + max_u64 = u64(0xFFFFFFFFFFFFFFFF) max_u32_as_f32 = f32(max_u32) + 1 max_u64_as_f64 = f64(max_u64) + 1 u31_mask = u32(0x7FFFFFFF) diff --git a/vlib/time/time.js.v b/vlib/time/time.js.v index 9d08e08aa5..f6c552d9ef 100644 --- a/vlib/time/time.js.v +++ b/vlib/time/time.js.v @@ -36,3 +36,9 @@ pub fn (t Time) local() Time { // if it is not we should try to use Intl for getting local time. return t } + +pub fn sleep(dur Duration) { + #let now = new Date().getTime() + #let toWait = BigInt(dur.val) / BigInt(time__millisecond) + #while (new Date().getTime() < now + Number(toWait)) {} +} diff --git a/vlib/v/gen/js/builtin_types.v b/vlib/v/gen/js/builtin_types.v index c3085be652..d24cdfff48 100644 --- a/vlib/v/gen/js/builtin_types.v +++ b/vlib/v/gen/js/builtin_types.v @@ -325,7 +325,7 @@ fn (mut g JsGen) gen_builtin_type_defs() { typ_name: typ_name default_value: 'new Number(0)' // mask <=32 bit numbers with 0xffffffff - constructor: 'this.val = Number(val) & 0xffffffff' + constructor: 'this.val = Math.round(Number(val)) & 0xffffffff' value_of: 'Number(this.val)' to_string: 'this.valueOf().toString()' eq: 'new bool(self.valueOf() === other.valueOf())' @@ -359,7 +359,7 @@ fn (mut g JsGen) gen_builtin_type_defs() { g.gen_builtin_prototype( typ_name: typ_name default_value: 'new Number(0)' - constructor: 'if (typeof(val) == "string") { this.val = val.charCodeAt() } else if (val instanceof string) { this.val = val.str.charCodeAt(); } else { this.val = val | 0 }' + constructor: 'if (typeof(val) == "string") { this.val = val.charCodeAt() } else if (val instanceof string) { this.val = val.str.charCodeAt(); } else { this.val = Math.round(val) }' value_of: 'this.val | 0' to_string: 'new string(this.val + "")' eq: 'new bool(self.valueOf() === other.valueOf())' diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 732d1dab04..de87665960 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -86,6 +86,7 @@ mut: array_sort_fn map[string]bool wasm_export map[string][]string wasm_import map[string][]string + init_global map[string]map[string]ast.Expr // initializers for constants or globals, should be invoked before module init. } fn (mut g JsGen) write_tests_definitions() { @@ -204,6 +205,11 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { for mod_name in g.table.modules { g.writeln('// Initializations for module $mod_name') + for global, expr in g.init_global[mod_name] { + g.write('$global = ') + g.expr(expr) + g.writeln(';') + } init_fn_name := '${mod_name}.init' if initfn := g.table.find_fn(init_fn_name) { if initfn.return_type == ast.void_type && initfn.params.len == 0 { @@ -213,6 +219,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { } } } + if !g.pref.is_shared { g.write('loadRoutine().then(_ => js_main());') } @@ -1214,7 +1221,7 @@ fn (mut g JsGen) gen_assert_stmt(orig_node ast.AssertStmt) { fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt, semicolon bool) { if stmt.left.len > stmt.right.len { // multi return - g.write('const [') + g.write('let [') for i, left in stmt.left { if !left.is_blank_ident() { g.expr(left) @@ -1469,8 +1476,17 @@ fn (mut g JsGen) gen_const_decl(it ast.ConstDecl) { if field.is_pub { g.push_pub_var(field.name) } - g.write('const ${g.js_name(field.name)} = ') - g.expr(field.expr) + + if field.expr is ast.StringInterLiteral || field.expr is ast.StringLiteral + || field.expr is ast.IntegerLiteral || field.expr is ast.FloatLiteral + || field.expr is ast.BoolLiteral { + g.write('const ${g.js_name(field.name)} = ') + g.expr(field.expr) + } else { + g.write('let ${g.js_name(field.name)} = ') + g.write('undefined') + g.init_global[g.ns.name][g.js_name(field.name)] = field.expr + } g.writeln(';') } g.writeln('')