v.gen.js: refactor code, fix alias codegen, `-stats` now again works with tests on the JS backend (#11512)
							parent
							
								
									ead5e66afd
								
							
						
					
					
						commit
						c175b4fd48
					
				|  | @ -2,6 +2,7 @@ module os | |||
| 
 | ||||
| #const $fs = require('fs'); | ||||
| #const $path = require('path'); | ||||
| #const tty = require('tty') | ||||
| 
 | ||||
| pub const ( | ||||
| 	path_delimiter = '/' | ||||
|  | @ -95,3 +96,10 @@ pub fn execute(cmd string) Result { | |||
| 		output: stdout | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn is_atty(fd int) int { | ||||
| 	res := 0 | ||||
| 	#res.val = +tty.isatty(fd.val) | ||||
| 
 | ||||
| 	return res | ||||
| } | ||||
|  |  | |||
|  | @ -258,6 +258,9 @@ pub fn (v &Builder) get_user_files() []string { | |||
| 	if v.pref.is_test && v.pref.is_stats { | ||||
| 		user_files << os.join_path(preludes_path, 'tests_with_stats.v') | ||||
| 	} | ||||
| 	if v.pref.backend.is_js() && v.pref.is_stats && v.pref.is_test { | ||||
| 		user_files << os.join_path(preludes_path, 'stats_import.js.v') | ||||
| 	} | ||||
| 	if v.pref.is_prof { | ||||
| 		user_files << os.join_path(preludes_path, 'profiled_program.v') | ||||
| 	} | ||||
|  |  | |||
|  | @ -12,6 +12,9 @@ fn (mut g JsGen) gen_sumtype_equality_fn(left_type ast.Type) string { | |||
| 	g.sumtype_fn_definitions << ptr_styp | ||||
| 	info := left.sym.sumtype_info() | ||||
| 	mut fn_builder := strings.new_builder(512) | ||||
| 	defer { | ||||
| 		g.definitions.writeln(fn_builder.str()) | ||||
| 	} | ||||
| 	fn_builder.writeln('function ${ptr_styp}_sumtype_eq(a,b) {') | ||||
| 	fn_builder.writeln('\tlet aProto = Object.getPrototypeOf(a);') | ||||
| 	fn_builder.writeln('\tlet bProto = Object.getPrototypeOf(b);') | ||||
|  | @ -48,7 +51,7 @@ fn (mut g JsGen) gen_sumtype_equality_fn(left_type ast.Type) string { | |||
| 	} | ||||
| 	fn_builder.writeln('\treturn new bool(false);') | ||||
| 	fn_builder.writeln('}') | ||||
| 	g.definitions.writeln(fn_builder.str()) | ||||
| 
 | ||||
| 	return ptr_styp | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -120,10 +120,11 @@ pub fn (mut g JsGen) base_type(t ast.Type) string { | |||
| } | ||||
| 
 | ||||
| pub fn (mut g JsGen) typ(t ast.Type) string { | ||||
| 	sym := g.table.get_type_symbol(t) | ||||
| 	sym := g.table.get_final_type_symbol(t) | ||||
| 	if sym.kind == .voidptr { | ||||
| 		return 'any' | ||||
| 	} | ||||
| 
 | ||||
| 	styp := g.base_type(t) | ||||
| 	return styp | ||||
| } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ module js | |||
| import v.ast | ||||
| import v.util | ||||
| import v.parser | ||||
| import strings | ||||
| 
 | ||||
| fn (mut g JsGen) js_mname(name_ string) string { | ||||
| 	mut is_js := false | ||||
|  | @ -348,3 +349,178 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { | |||
| 	} | ||||
| 	g.call_stack.delete_last() | ||||
| } | ||||
| 
 | ||||
| enum FnGenType { | ||||
| 	function | ||||
| 	struct_method | ||||
| 	alias_method | ||||
| 	iface_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 && g.table.get_type_symbol(it.params[0].typ).kind == .interface_ { | ||||
| 		return .iface_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) { | ||||
| 	res := g.fn_gen_type(it) | ||||
| 	if it.language == .js { | ||||
| 		return | ||||
| 	} | ||||
| 	if g.inside_builtin { | ||||
| 		g.builtin_fns << it.name | ||||
| 	} | ||||
| 	cur_fn_decl := g.fn_decl | ||||
| 	g.gen_method_decl(it, res) | ||||
| 	g.fn_decl = cur_fn_decl | ||||
| } | ||||
| 
 | ||||
| fn fn_has_go(node ast.FnDecl) bool { | ||||
| 	mut has_go := false | ||||
| 	for stmt in node.stmts { | ||||
| 		if stmt is ast.ExprStmt { | ||||
| 			if stmt.expr is ast.GoExpr { | ||||
| 				has_go = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return has_go | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) generic_fn_name(types []ast.Type, before string, is_decl bool) string { | ||||
| 	if types.len == 0 { | ||||
| 		return before | ||||
| 	} | ||||
| 
 | ||||
| 	mut name := before + '_T' | ||||
| 	for typ in types { | ||||
| 		name += '_' + strings.repeat_string('__ptr__', typ.nr_muls()) + g.typ(typ.set_nr_muls(0)) | ||||
| 	} | ||||
| 	return name | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) { | ||||
| 	unsafe { | ||||
| 		g.fn_decl = &it | ||||
| 	} | ||||
| 	cur_fn_save := g.table.cur_fn | ||||
| 	defer { | ||||
| 		g.table.cur_fn = cur_fn_save | ||||
| 	} | ||||
| 	unsafe { | ||||
| 		g.table.cur_fn = &it | ||||
| 	} | ||||
| 	node := it | ||||
| 	mut name := it.name | ||||
| 	if name in ['+', '-', '*', '/', '%', '<', '=='] { | ||||
| 		name = util.replace_op(name) | ||||
| 	} | ||||
| 
 | ||||
| 	if node.is_method { | ||||
| 		unwrapped_rec_sym := g.table.get_type_symbol(g.unwrap_generic(node.receiver.typ)) | ||||
| 		if unwrapped_rec_sym.kind == .placeholder { | ||||
| 			return | ||||
| 		} | ||||
| 		name = g.cc_type(node.receiver.typ, false) + '_' + name | ||||
| 	} | ||||
| 
 | ||||
| 	name = g.js_name(name) | ||||
| 
 | ||||
| 	name = g.generic_fn_name(g.table.cur_concrete_types, name, true) | ||||
| 	if name in parser.builtin_functions { | ||||
| 		name = 'builtin__$name' | ||||
| 	} | ||||
| 	has_go := fn_has_go(it) | ||||
| 	if it.is_pub && !it.is_method { | ||||
| 		g.push_pub_var(name) | ||||
| 	} | ||||
| 	is_main := it.name == 'main.main' | ||||
| 	g.gen_attrs(it.attrs) | ||||
| 	if is_main { | ||||
| 		// there is no concept of main in JS but we do have iife
 | ||||
| 		g.writeln('/* program entry point */') | ||||
| 
 | ||||
| 		// g.write('(')
 | ||||
| 		if has_go { | ||||
| 			g.write('async ') | ||||
| 		} | ||||
| 		g.write('function js_main(') | ||||
| 	} else if it.is_anon { | ||||
| 		g.write('function (') | ||||
| 	} else { | ||||
| 		c := name[0] | ||||
| 		if c in [`+`, `-`, `*`, `/`] { | ||||
| 			name = util.replace_op(name) | ||||
| 		} | ||||
| 		// type_name := g.typ(it.return_type)
 | ||||
| 		// generate jsdoc for the function
 | ||||
| 		g.doc.gen_fn(it) | ||||
| 		if has_go { | ||||
| 			g.write('async ') | ||||
| 		} | ||||
| 
 | ||||
| 		g.write('function ') | ||||
| 
 | ||||
| 		g.write('${name}(') | ||||
| 		if it.is_pub && !it.is_method { | ||||
| 			g.push_pub_var(name) | ||||
| 		} | ||||
| 	} | ||||
| 	mut args := it.params | ||||
| 
 | ||||
| 	g.fn_args(args, it.is_variadic) | ||||
| 	g.write(') {') | ||||
| 	for i, arg in args { | ||||
| 		is_varg := i == args.len - 1 && it.is_variadic | ||||
| 		arg_name := g.js_name(arg.name) | ||||
| 		if is_varg { | ||||
| 			g.writeln('$arg_name = new array($arg_name);') | ||||
| 		} else { | ||||
| 			if arg.typ.is_ptr() || arg.is_mut { | ||||
| 				g.writeln('$arg_name = new \$ref($arg_name)') | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	g.stmts(it.stmts) | ||||
| 	g.writeln('}') | ||||
| 
 | ||||
| 	if is_main { | ||||
| 		// g.write(')')
 | ||||
| 	} | ||||
| 	g.writeln('') | ||||
| 
 | ||||
| 	for attr in it.attrs { | ||||
| 		match attr.name { | ||||
| 			'export' { | ||||
| 				g.writeln('globalThis.$attr.arg = ${g.js_name(it.name)};') | ||||
| 			} | ||||
| 			else {} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	g.fn_decl = voidptr(0) | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) fn_args(args []ast.Param, is_variadic bool) { | ||||
| 	for i, arg in args { | ||||
| 		name := g.js_name(arg.name) | ||||
| 		is_varg := i == args.len - 1 && is_variadic | ||||
| 		if is_varg { | ||||
| 			g.write('...$name') | ||||
| 		} else { | ||||
| 			g.write(name) | ||||
| 		} | ||||
| 		// if its not the last argument
 | ||||
| 		if i < args.len - 1 { | ||||
| 			g.write(', ') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -9,12 +9,6 @@ import v.util.version | |||
| import v.depgraph | ||||
| import encoding.base64 | ||||
| import v.gen.js.sourcemap | ||||
| import v.parser | ||||
| 
 | ||||
| struct MutArg { | ||||
| 	tmp_var string | ||||
| 	expr    ast.Expr = ast.empty_expr() | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
| 	// https://ecma-international.org/ecma-262/#sec-reserved-words
 | ||||
|  | @ -285,24 +279,24 @@ pub fn (mut g JsGen) gen_js_main_for_tests() { | |||
| 	g.writeln('') | ||||
| 	g.writeln('globalThis.VTEST=1') | ||||
| 	if g.pref.is_stats { | ||||
| 		g.writeln('let bt = start_testing($all_tfuncs.len, "$g.pref.path")') | ||||
| 		g.writeln('let bt = main__start_testing(new int($all_tfuncs.len), new string("$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('main__BenchedTests_testing_step_start(bt,new string("$tcname"))') | ||||
| 		} | ||||
| 
 | ||||
| 		g.writeln('try { ${tcname}(); } catch (_e) {} ') | ||||
| 		if g.pref.is_stats { | ||||
| 			g.writeln('bt.testing_step_end();') | ||||
| 			g.writeln('main__BenchedTests_testing_step_end(bt);') | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	g.writeln('') | ||||
| 	if g.pref.is_stats { | ||||
| 		g.writeln('bt.end_testing();') | ||||
| 		g.writeln('main__BenchedTests_end_testing(bt);') | ||||
| 	} | ||||
| 	g.dec_indent() | ||||
| 	g.writeln('}') | ||||
|  | @ -489,62 +483,6 @@ fn (mut g JsGen) get_alias(name string) string { | |||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) js_name(name_ string) string { | ||||
| 	/* | ||||
| 	mut is_js := false | ||||
| 	is_overload := ['+', '-', '*', '/', '==', '<', '>'] | ||||
| 	mut name := name_ | ||||
| 	if name.starts_with('JS.') { | ||||
| 		name = name[3..] | ||||
| 		is_js = true | ||||
| 	} | ||||
| 	ns := get_ns(name) | ||||
| 	name = if name in is_overload { | ||||
| 		match name { | ||||
| 			'+' { | ||||
| 				'\$add' | ||||
| 			} | ||||
| 			'-' { | ||||
| 				'\$sub' | ||||
| 			} | ||||
| 			'/' { | ||||
| 				'\$div' | ||||
| 			} | ||||
| 			'*' { | ||||
| 				'\$mul' | ||||
| 			} | ||||
| 			'%' { | ||||
| 				'\$mod' | ||||
| 			} | ||||
| 			'==' { | ||||
| 				'eq' | ||||
| 			} | ||||
| 			'>' { | ||||
| 				'\$gt' | ||||
| 			} | ||||
| 			'<' { | ||||
| 				'\$lt' | ||||
| 			} | ||||
| 			else { | ||||
| 				'' | ||||
| 			} | ||||
| 		} | ||||
| 	} else if g.ns == 0 { | ||||
| 		name | ||||
| 	} else if ns == g.ns.name { | ||||
| 		name.split('.').last() | ||||
| 	} else { | ||||
| 		g.get_alias(name) | ||||
| 	} | ||||
| 	mut parts := name.split('.') | ||||
| 	if !is_js { | ||||
| 		for i, p in parts { | ||||
| 			if p in js.js_reserved { | ||||
| 				parts[i] = 'v_$p' | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return parts.join('.')*/ | ||||
| 
 | ||||
| 	mut name := name_ | ||||
| 	if name.starts_with('JS.') { | ||||
| 		name = name[3..] | ||||
|  | @ -558,11 +496,9 @@ fn (mut g JsGen) js_name(name_ string) string { | |||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) stmts(stmts []ast.Stmt) { | ||||
| 	g.inc_indent() | ||||
| 	for stmt in stmts { | ||||
| 		g.stmt(stmt) | ||||
| 	} | ||||
| 	g.dec_indent() | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
|  | @ -619,6 +555,11 @@ fn (mut g JsGen) gen_global_decl(node ast.GlobalDecl) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) gen_alias_type_decl(node ast.AliasTypeDecl) { | ||||
| 	name := if g.ns.name == 'builtin' { node.name } else { '${g.js_name(g.ns.name)}__$node.name' } | ||||
| 	g.writeln('function ${name}(val) { return val;  }') | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) stmt_no_semi(node ast.Stmt) { | ||||
| 	g.stmt_start_pos = g.out.len | ||||
| 	match node { | ||||
|  | @ -822,7 +763,12 @@ fn (mut g JsGen) stmt(node ast.Stmt) { | |||
| 			g.gen_struct_decl(node) | ||||
| 		} | ||||
| 		ast.TypeDecl { | ||||
| 			// skip JS has no typedecl
 | ||||
| 			match node { | ||||
| 				ast.AliasTypeDecl { | ||||
| 					g.gen_alias_type_decl(node) | ||||
| 				} | ||||
| 				else {} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1275,7 +1221,9 @@ fn (mut g JsGen) gen_attrs(attrs []ast.Attr) { | |||
| 
 | ||||
| fn (mut g JsGen) gen_block(it ast.Block) { | ||||
| 	g.writeln('{') | ||||
| 	g.inc_indent() | ||||
| 	g.stmts(it.stmts) | ||||
| 	g.dec_indent() | ||||
| 	g.writeln('}') | ||||
| } | ||||
| 
 | ||||
|  | @ -1338,59 +1286,9 @@ fn (mut g JsGen) gen_expr_stmt_no_semi(it ast.ExprStmt) { | |||
| 	g.expr(it.expr) | ||||
| } | ||||
| 
 | ||||
| enum FnGenType { | ||||
| 	function | ||||
| 	struct_method | ||||
| 	alias_method | ||||
| 	iface_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 && g.table.get_type_symbol(it.params[0].typ).kind == .interface_ { | ||||
| 		return .iface_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) { | ||||
| 	res := g.fn_gen_type(it) | ||||
| 	if it.language == .js { | ||||
| 		return | ||||
| 	} | ||||
| 	/* | ||||
| 	if res == .struct_method { | ||||
| 		// Struct methods are handled by class generation code.
 | ||||
| 		return | ||||
| 	}*/ | ||||
| 	if g.inside_builtin { | ||||
| 		g.builtin_fns << it.name | ||||
| 	} | ||||
| 	cur_fn_decl := g.fn_decl | ||||
| 	g.gen_method_decl(it, res) | ||||
| 	g.fn_decl = cur_fn_decl | ||||
| } | ||||
| 
 | ||||
| fn fn_has_go(node ast.FnDecl) bool { | ||||
| 	mut has_go := false | ||||
| 	for stmt in node.stmts { | ||||
| 		if stmt is ast.ExprStmt { | ||||
| 			if stmt.expr is ast.GoExpr { | ||||
| 				has_go = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return has_go | ||||
| } | ||||
| 
 | ||||
| // cc_type whether to prefix 'struct' or not (C__Foo -> struct Foo)
 | ||||
| fn (mut g JsGen) cc_type(typ ast.Type, is_prefix_struct bool) string { | ||||
| 	sym := g.table.get_type_symbol(g.unwrap_generic(typ)) | ||||
| 	sym := g.table.get_final_type_symbol(g.unwrap_generic(typ)) | ||||
| 	mut styp := sym.cname | ||||
| 	match mut sym.info { | ||||
| 		ast.Struct, ast.Interface, ast.SumType { | ||||
|  | @ -1408,231 +1306,6 @@ fn (mut g JsGen) cc_type(typ ast.Type, is_prefix_struct bool) string { | |||
| 	return styp | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) generic_fn_name(types []ast.Type, before string, is_decl bool) string { | ||||
| 	if types.len == 0 { | ||||
| 		return before | ||||
| 	} | ||||
| 
 | ||||
| 	mut name := before + '_T' | ||||
| 	for typ in types { | ||||
| 		name += '_' + strings.repeat_string('__ptr__', typ.nr_muls()) + g.typ(typ.set_nr_muls(0)) | ||||
| 	} | ||||
| 	return name | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) { | ||||
| 	unsafe { | ||||
| 		g.fn_decl = &it | ||||
| 	} | ||||
| 	cur_fn_save := g.table.cur_fn | ||||
| 	defer { | ||||
| 		g.table.cur_fn = cur_fn_save | ||||
| 	} | ||||
| 	unsafe { | ||||
| 		g.table.cur_fn = &it | ||||
| 	} | ||||
| 	node := it | ||||
| 	mut name := it.name | ||||
| 	if name in ['+', '-', '*', '/', '%', '<', '=='] { | ||||
| 		name = util.replace_op(name) | ||||
| 	} | ||||
| 
 | ||||
| 	if node.is_method { | ||||
| 		unwrapped_rec_sym := g.table.get_type_symbol(g.unwrap_generic(node.receiver.typ)) | ||||
| 		if unwrapped_rec_sym.kind == .placeholder { | ||||
| 			return | ||||
| 		} | ||||
| 		name = g.cc_type(node.receiver.typ, false) + '_' + name | ||||
| 	} | ||||
| 
 | ||||
| 	name = g.js_name(name) | ||||
| 
 | ||||
| 	name = g.generic_fn_name(g.table.cur_concrete_types, name, true) | ||||
| 	if name in parser.builtin_functions { | ||||
| 		name = 'builtin__$name' | ||||
| 	} | ||||
| 	has_go := fn_has_go(it) | ||||
| 	if it.is_pub && !it.is_method { | ||||
| 		g.push_pub_var(name) | ||||
| 	} | ||||
| 	is_main := it.name == 'main.main' | ||||
| 	g.gen_attrs(it.attrs) | ||||
| 	if is_main { | ||||
| 		// there is no concept of main in JS but we do have iife
 | ||||
| 		g.writeln('/* program entry point */') | ||||
| 
 | ||||
| 		// g.write('(')
 | ||||
| 		if has_go { | ||||
| 			g.write('async ') | ||||
| 		} | ||||
| 		g.write('function js_main(') | ||||
| 	} else if it.is_anon { | ||||
| 		g.write('function (') | ||||
| 	} else { | ||||
| 		c := name[0] | ||||
| 		if c in [`+`, `-`, `*`, `/`] { | ||||
| 			name = util.replace_op(name) | ||||
| 		} | ||||
| 		// type_name := g.typ(it.return_type)
 | ||||
| 		// generate jsdoc for the function
 | ||||
| 		g.doc.gen_fn(it) | ||||
| 		if has_go { | ||||
| 			g.write('async ') | ||||
| 		} | ||||
| 
 | ||||
| 		g.write('function ') | ||||
| 
 | ||||
| 		g.write('${name}(') | ||||
| 		if it.is_pub && !it.is_method { | ||||
| 			g.push_pub_var(name) | ||||
| 		} | ||||
| 	} | ||||
| 	mut args := it.params | ||||
| 
 | ||||
| 	g.fn_args(args, it.is_variadic) | ||||
| 	g.write(') {') | ||||
| 	for i, arg in args { | ||||
| 		is_varg := i == args.len - 1 && it.is_variadic | ||||
| 		arg_name := g.js_name(arg.name) | ||||
| 		if is_varg { | ||||
| 			g.writeln('$arg_name = new array($arg_name);') | ||||
| 		} else { | ||||
| 			if arg.typ.is_ptr() || arg.is_mut { | ||||
| 				g.writeln('$arg_name = new \$ref($arg_name)') | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	g.stmts(it.stmts) | ||||
| 	g.writeln('}') | ||||
| 
 | ||||
| 	if is_main { | ||||
| 		// g.write(')')
 | ||||
| 	} | ||||
| 	g.writeln('') | ||||
| 
 | ||||
| 	for attr in it.attrs { | ||||
| 		match attr.name { | ||||
| 			'export' { | ||||
| 				g.writeln('globalThis.$attr.arg = ${g.js_name(it.name)};') | ||||
| 			} | ||||
| 			else {} | ||||
| 		} | ||||
| 	} | ||||
| 	/* | ||||
| 	if typ == .alias_method || typ == .iface_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('') | ||||
| 		} | ||||
| 		g.writeln('${name}.prototype.$it.name = function ') | ||||
| 	} | ||||
| 	has_go := fn_has_go(it) | ||||
| 	is_main := it.name == 'main.main' | ||||
| 	g.gen_attrs(it.attrs) | ||||
| 	if is_main { | ||||
| 		// there is no concept of main in JS but we do have iife
 | ||||
| 		g.writeln('/* program entry point */') | ||||
| 
 | ||||
| 		g.write('(') | ||||
| 		if has_go { | ||||
| 			g.write('async ') | ||||
| 		} | ||||
| 		g.write('function(') | ||||
| 	} else if it.is_anon { | ||||
| 		g.write('function (') | ||||
| 	} else { | ||||
| 		mut name := g.js_name(it.name) | ||||
| 		c := name[0] | ||||
| 		if c in [`+`, `-`, `*`, `/`] { | ||||
| 			name = util.replace_op(name) | ||||
| 		} | ||||
| 		// type_name := g.typ(it.return_type)
 | ||||
| 		// generate jsdoc for the function
 | ||||
| 		g.doc.gen_fn(it) | ||||
| 		if has_go { | ||||
| 			g.write('async ') | ||||
| 		} | ||||
| 		if !it.is_method { | ||||
| 			g.write('function ') | ||||
| 		} else { | ||||
| 			if it.attrs.contains('js_getter') { | ||||
| 				g.write('get ') | ||||
| 			} else if it.attrs.contains('js_setter') { | ||||
| 				g.write('set ') | ||||
| 			} | ||||
| 		} | ||||
| 		g.write('${name}(') | ||||
| 		if it.is_pub && !it.is_method { | ||||
| 			g.push_pub_var(name) | ||||
| 		} | ||||
| 	} | ||||
| 	mut args := it.params | ||||
| 	if it.is_method { | ||||
| 		args = args[1..] | ||||
| 	} | ||||
| 	g.fn_args(args, it.is_variadic) | ||||
| 	if it.is_method { | ||||
| 		if args.len > 0 { | ||||
| 			g.write(', ') | ||||
| 		} | ||||
| 		if it.params[0].is_mut || it.params[0].typ.is_ptr() { | ||||
| 			g.write('${it.params[0].name} = new \$ref(this)') | ||||
| 		} else { | ||||
| 			g.write('${it.params[0].name} = this') | ||||
| 		} | ||||
| 	} | ||||
| 	g.writeln(') {') | ||||
| 	for i, arg in args { | ||||
| 		is_varg := i == args.len - 1 && it.is_variadic | ||||
| 		name := g.js_name(arg.name) | ||||
| 		if is_varg { | ||||
| 			g.writeln('$name = new array($name);') | ||||
| 		} else { | ||||
| 			if arg.typ.is_ptr() || arg.is_mut { | ||||
| 				g.writeln('$name = new \$ref($name)') | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	g.stmts(it.stmts) | ||||
| 	g.writeln('}') | ||||
| 	for attr in it.attrs { | ||||
| 		match attr.name { | ||||
| 			'export' { | ||||
| 				g.writeln('globalThis.$attr.arg = ${g.js_name(it.name)};') | ||||
| 			} | ||||
| 			else {} | ||||
| 		} | ||||
| 	} | ||||
| 	if is_main { | ||||
| 		g.write(')();') | ||||
| 	} else if typ != .struct_method { | ||||
| 		// g.write(';')
 | ||||
| 	} | ||||
| 	if typ == .struct_method || typ == .alias_method || typ == .iface_method { | ||||
| 		g.writeln('\n') | ||||
| 	} | ||||
| 	*/ | ||||
| 	g.fn_decl = voidptr(0) | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) fn_args(args []ast.Param, is_variadic bool) { | ||||
| 	for i, arg in args { | ||||
| 		name := g.js_name(arg.name) | ||||
| 		is_varg := i == args.len - 1 && is_variadic | ||||
| 		if is_varg { | ||||
| 			g.write('...$name') | ||||
| 		} else { | ||||
| 			g.write(name) | ||||
| 		} | ||||
| 		// if its not the last argument
 | ||||
| 		if i < args.len - 1 { | ||||
| 			g.write(', ') | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (mut g JsGen) gen_for_c_stmt(it ast.ForCStmt) { | ||||
| 	g.inside_loop = true | ||||
| 	g.write('for (') | ||||
|  | @ -1918,11 +1591,6 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) { | |||
| 	g.writeln('};\n') | ||||
| 	g.dec_indent() | ||||
| 
 | ||||
| 	/* | ||||
| 	for cfn in fns { | ||||
| 		g.gen_method_decl(cfn, .struct_method) | ||||
| 	}*/ | ||||
| 
 | ||||
| 	if node.is_pub { | ||||
| 		g.push_pub_var(name) | ||||
| 	} | ||||
|  | @ -2553,11 +2221,12 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) { | |||
| 			g.write('.valueOf()') | ||||
| 		} | ||||
| 		g.write('.arr') | ||||
| 		g.write('[+') | ||||
| 		g.write('[Number(') | ||||
| 		g.cast_stack << ast.int_type_idx | ||||
| 		g.expr(expr.index) | ||||
| 		g.write('.valueOf()') | ||||
| 		g.cast_stack.delete_last() | ||||
| 		g.write(']') | ||||
| 		g.write(')]') | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -2617,37 +2286,6 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) { | |||
| 		g.write('.valueOf()') | ||||
| 		g.write(')') | ||||
| 	} else if it.op == .eq || it.op == .ne { | ||||
| 		/* | ||||
| 		has_operator_overloading := g.table.type_has_method(l_sym, '==') | ||||
| 		if has_operator_overloading { | ||||
| 			g.expr(it.left) | ||||
| 			g.gen_deref_ptr(it.left_type) | ||||
| 			g.write('.eq(') | ||||
| 			g.expr(it.right) | ||||
| 			g.gen_deref_ptr(it.right_type) | ||||
| 			g.write(')') | ||||
| 			// Shallow equatables
 | ||||
| 		} else if l_sym.kind in js.shallow_equatables && r_sym.kind in js.shallow_equatables { | ||||
| 			// wrap left expr in parens so binary operations will work correctly.
 | ||||
| 			g.write('(') | ||||
| 			g.expr(it.left) | ||||
| 			g.gen_deref_ptr(it.left_type) | ||||
| 			g.write(')') | ||||
| 			g.write('.eq(') | ||||
| 			g.cast_stack << int(l_sym.kind) | ||||
| 			g.expr(it.right) | ||||
| 			g.gen_deref_ptr(it.right_type) | ||||
| 			g.cast_stack.delete_last() | ||||
| 			g.write(')') | ||||
| 		} else { | ||||
| 			g.write('vEq(') | ||||
| 			g.expr(it.left) | ||||
| 			g.gen_deref_ptr(it.left_type) | ||||
| 			g.write(', ') | ||||
| 			g.expr(it.right) | ||||
| 			g.gen_deref_ptr(it.right_type) | ||||
| 			g.write(')') | ||||
| 		}*/ | ||||
| 		node := it | ||||
| 		left := g.unwrap(node.left_type) | ||||
| 		right := g.unwrap(node.right_type) | ||||
|  |  | |||
|  | @ -1 +0,0 @@ | |||
| module stats_import | ||||
		Loading…
	
		Reference in New Issue