diff --git a/vlib/builtin/js/array.js.v b/vlib/builtin/js/array.js.v index 51d762ad06..ac0f2321a1 100644 --- a/vlib/builtin/js/array.js.v +++ b/vlib/builtin/js/array.js.v @@ -243,3 +243,11 @@ pub fn (mut a array) delete_last() { [unsafe] 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)) + + return res +} diff --git a/vlib/v/gen/js/builtin_types.v b/vlib/v/gen/js/builtin_types.v index d5b915e8f2..916490aa92 100644 --- a/vlib/v/gen/js/builtin_types.v +++ b/vlib/v/gen/js/builtin_types.v @@ -184,8 +184,9 @@ pub fn (mut g JsGen) typ(t ast.Type) string { styp = 'union_sym_type' } .alias { - // TODO: Implement aliases - styp = 'alias' + fsym := g.table.get_final_type_symbol(t) + name := g.js_name(fsym.name) + styp += '$name' } .enum_ { // NB: We could declare them as TypeScript enums but TS doesn't like @@ -278,7 +279,7 @@ fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeConfig) { } for method in g.method_fn_decls[c.typ_name] { g.inside_def_typ_decl = true - g.gen_method_decl(method) + g.gen_method_decl(method, .struct_method) g.inside_def_typ_decl = false g.writeln(',') } diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index d86064659d..8333e7f293 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -284,24 +284,25 @@ pub fn (mut g JsGen) gen_js_main_for_tests() { g.writeln('') g.writeln('globalThis.VTEST=1') - // g.writeln('let bt = start_testing($all_tfuncs.len, "$g.pref.path")') - + if g.pref.is_stats { + g.writeln('let bt = start_testing($all_tfuncs.len, "$g.pref.path")') + } for tname in all_tfuncs { tcname := g.js_name(tname) if g.pref.is_stats { - // g.writeln('bt.testing_step_start("$tcname")') + g.writeln('bt.testing_step_start("$tcname")') } g.writeln('try { ${tcname}(); } catch (_e) {} ') if g.pref.is_stats { - // g.writeln('bt.testing_step_end();') + g.writeln('bt.testing_step_end();') } } g.writeln('') if g.pref.is_stats { - // g.writeln('bt.end_testing();') + g.writeln('bt.end_testing();') } g.dec_indent() g.writeln('})();') @@ -380,7 +381,7 @@ pub fn (mut g JsGen) find_class_methods(stmts []ast.Stmt) { pub fn (mut g JsGen) init() { g.definitions.writeln('// Generated by the V compiler\n') - g.definitions.writeln('"use strict";') + // g.definitions.writeln('"use strict";') g.definitions.writeln('') g.definitions.writeln('var \$global = (new Function("return this"))();') g.definitions.writeln('function \$ref(value) { if (value instanceof \$ref) { return value; } this.val = value; } ') @@ -699,9 +700,7 @@ fn (mut g JsGen) stmt_no_semi(node ast.Stmt) { g.write_v_source_line_info(node.pos) g.gen_struct_decl(node) } - ast.TypeDecl { - // skip JS has no typedecl - } + ast.TypeDecl {} } } @@ -1319,8 +1318,25 @@ fn (mut g JsGen) gen_expr_stmt_no_semi(it ast.ExprStmt) { g.expr(it.expr) } +enum FnGenType { + function + struct_method + alias_method +} + +fn (g &JsGen) fn_gen_type(it &ast.FnDecl) FnGenType { + if it.is_method && g.table.get_type_symbol(it.params[0].typ).kind == .alias { + return .alias_method + } else if it.is_method || it.no_body { + return .struct_method + } else { + return .function + } +} + fn (mut g JsGen) gen_fn_decl(it ast.FnDecl) { - if it.no_body || it.is_method { + res := g.fn_gen_type(it) + if res == .struct_method { // Struct methods are handled by class generation code. return } @@ -1328,7 +1344,7 @@ fn (mut g JsGen) gen_fn_decl(it ast.FnDecl) { g.builtin_fns << it.name } cur_fn_decl := g.fn_decl - g.gen_method_decl(it) + g.gen_method_decl(it, res) g.fn_decl = cur_fn_decl } @@ -1345,10 +1361,18 @@ fn fn_has_go(node ast.FnDecl) bool { return has_go } -fn (mut g JsGen) gen_method_decl(it ast.FnDecl) { +fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) { unsafe { g.fn_decl = &it } + if typ == .alias_method { + sym := g.table.get_final_type_symbol(it.params[0].typ.set_nr_muls(0)) + name := g.js_name(sym.name) + if name in js.v_types { + g.writeln('builtin.') + } + g.writeln('${name}.prototype.$it.name = function ') + } has_go := fn_has_go(it) is_main := it.name == 'main.main' g.gen_attrs(it.attrs) @@ -1422,7 +1446,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) { if is_main { g.write(')();') } - if !it.is_anon && !it.is_method { + if typ == .struct_method || typ == .alias_method { g.writeln('\n') } g.fn_decl = voidptr(0) @@ -1661,8 +1685,9 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) { g.write('$field.name: ${g.to_js_typ_val(field.typ)}') g.writeln(',') } + for cfn in fns { - g.gen_method_decl(cfn) + g.gen_method_decl(cfn, .struct_method) g.writeln(',') } // gen toString method @@ -2435,8 +2460,8 @@ fn (mut g JsGen) gen_deref_ptr(ty ast.Type) { } fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) { - l_sym := g.table.get_type_symbol(it.left_type) - r_sym := g.table.get_type_symbol(it.right_type) + l_sym := g.table.get_final_type_symbol(it.left_type) + r_sym := g.table.get_final_type_symbol(it.right_type) is_not := it.op in [.not_in, .not_is, .ne] if is_not { @@ -2444,10 +2469,15 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) { } is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod, .right_shift, .left_shift, .amp, .pipe, .xor] + if is_arithmetic && ((l_sym.kind == .i64 || l_sym.kind == .u64) || (r_sym.kind == .i64 || r_sym.kind == .u64)) { // if left or right is i64 or u64 we convert them to bigint to perform operation. - greater_typ := g.greater_typ(it.left_type, it.right_type) + greater_typ := if l_sym.kind == .i64 || l_sym.kind == .u64 { + it.left_type + } else { + it.right_type + } // g.greater_typ(it.left_type, it.right_type) g.write('new ') if g.ns.name != 'builtin' { g.write('builtin.') @@ -2894,7 +2924,7 @@ fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) { is_literal := ((it.expr is ast.IntegerLiteral && it.typ in ast.integer_type_idxs) || (it.expr is ast.FloatLiteral && it.typ in ast.float_type_idxs)) // Skip cast if type is the same as the parrent caster - tsym := g.table.get_type_symbol(it.typ) + tsym := g.table.get_final_type_symbol(it.typ) if it.expr is ast.IntegerLiteral && (tsym.kind == .i64 || tsym.kind == .u64) { g.write('new ') if g.ns.name != 'builtin' { diff --git a/vlib/v/preludes_js/stats_import.js.v b/vlib/v/preludes_js/stats_import.js.v new file mode 100644 index 0000000000..25cb22dddb --- /dev/null +++ b/vlib/v/preludes_js/stats_import.js.v @@ -0,0 +1,15 @@ +module stats_import + +pub fn get_stats_ok() int { + res := 0 + #res.val = +g_test_oks + + return res +} + +pub fn get_stats_fail() int { + res := 0 + #res.val = +g_test_fails + + return res +} diff --git a/vlib/v/preludes_js/tests_with_stats.v b/vlib/v/preludes_js/tests_with_stats.v index cc6992ec01..67c81be525 100644 --- a/vlib/v/preludes_js/tests_with_stats.v +++ b/vlib/v/preludes_js/tests_with_stats.v @@ -1,5 +1,7 @@ module main +import stats_import +import benchmark // ///////////////////////////////////////////////////////////////////// // / This file will get compiled as a part of the same module, // / in which a given _test.v file is, when v is given -stats argument @@ -7,10 +9,12 @@ module main // / main function, so that customizing the look & feel of the results // / is easy, since it is done in normal V code, instead of in embedded C ... // ///////////////////////////////////////////////////////////////////// + const inner_indent = ' ' struct BenchedTests { mut: + bench benchmark.Benchmark oks int fails int test_suit_file string @@ -21,7 +25,10 @@ mut: // /////////////////////////////////////////////////////////////////// // Called at the start of the test program produced by `v -stats file_test.v` pub fn start_testing(total_number_of_tests int, vfilename string) BenchedTests { - mut benched_tests_res := BenchedTests{} + mut benched_tests_res := BenchedTests{ + bench: benchmark.new_benchmark() + } + benched_tests_res.bench.set_total_expected_steps(total_number_of_tests) benched_tests_res.total_number_of_tests = total_number_of_tests benched_tests_res.test_suit_file = vfilename println('running tests in: $benched_tests_res.test_suit_file') @@ -31,14 +38,15 @@ pub fn start_testing(total_number_of_tests int, vfilename string) BenchedTests { // Called before each test_ function, defined in file_test.v fn (mut b BenchedTests) testing_step_start(stepfunc string) { b.step_func_name = stepfunc.replace('main.', '').replace('__', '.') - b.oks = C.g_test_oks - b.fails = C.g_test_fails + b.oks = stats_import.get_stats_ok() + b.fails = stats_import.get_stats_fail() + b.bench.step() } // Called after each test_ function, defined in file_test.v fn (mut b BenchedTests) testing_step_end() { - ok_diff := C.g_test_oks - b.oks - fail_diff := C.g_test_fails - b.fails + ok_diff := stats_import.get_stats_ok() - b.oks + fail_diff := stats_import.get_stats_fail() - b.fails // //////////////////////////////////////////////////////////////// if ok_diff == 0 && fail_diff == 0 { println(inner_indent + ' NO asserts | ' + b.fn_name()) @@ -46,17 +54,19 @@ fn (mut b BenchedTests) testing_step_end() { } // //////////////////////////////////////////////////////////////// if ok_diff > 0 { - // b.bench.ok_many(ok_diff) + b.bench.ok_many(ok_diff) } if fail_diff > 0 { - // b.bench.fail_many(fail_diff) + b.bench.fail_many(fail_diff) } // //////////////////////////////////////////////////////////////// if ok_diff > 0 && fail_diff == 0 { + println(inner_indent + b.bench.step_message_ok(nasserts(ok_diff)) + b.fn_name()) println(inner_indent + nasserts(ok_diff) + b.fn_name()) return } if fail_diff > 0 { + println(inner_indent + b.bench.step_message_fail(nasserts(fail_diff)) + b.fn_name()) println(inner_indent + nasserts(fail_diff) + b.fn_name()) return }