js: fix -stats compilation of tests, proper alias codegen (#11327)

pull/11329/head
playX 2021-08-28 16:57:33 +03:00 committed by GitHub
parent 25bf68e2f1
commit 118c5fdcd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 28 deletions

View File

@ -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
}

View File

@ -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(',')
}

View File

@ -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' {

View File

@ -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
}

View File

@ -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
}