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 $fs = require('fs');
|
||||||
#const $path = require('path');
|
#const $path = require('path');
|
||||||
|
#const tty = require('tty')
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
path_delimiter = '/'
|
path_delimiter = '/'
|
||||||
|
@ -95,3 +96,10 @@ pub fn execute(cmd string) Result {
|
||||||
output: stdout
|
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 {
|
if v.pref.is_test && v.pref.is_stats {
|
||||||
user_files << os.join_path(preludes_path, 'tests_with_stats.v')
|
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 {
|
if v.pref.is_prof {
|
||||||
user_files << os.join_path(preludes_path, 'profiled_program.v')
|
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
|
g.sumtype_fn_definitions << ptr_styp
|
||||||
info := left.sym.sumtype_info()
|
info := left.sym.sumtype_info()
|
||||||
mut fn_builder := strings.new_builder(512)
|
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('function ${ptr_styp}_sumtype_eq(a,b) {')
|
||||||
fn_builder.writeln('\tlet aProto = Object.getPrototypeOf(a);')
|
fn_builder.writeln('\tlet aProto = Object.getPrototypeOf(a);')
|
||||||
fn_builder.writeln('\tlet bProto = Object.getPrototypeOf(b);')
|
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('\treturn new bool(false);')
|
||||||
fn_builder.writeln('}')
|
fn_builder.writeln('}')
|
||||||
g.definitions.writeln(fn_builder.str())
|
|
||||||
return ptr_styp
|
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 {
|
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 {
|
if sym.kind == .voidptr {
|
||||||
return 'any'
|
return 'any'
|
||||||
}
|
}
|
||||||
|
|
||||||
styp := g.base_type(t)
|
styp := g.base_type(t)
|
||||||
return styp
|
return styp
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ module js
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.util
|
import v.util
|
||||||
import v.parser
|
import v.parser
|
||||||
|
import strings
|
||||||
|
|
||||||
fn (mut g JsGen) js_mname(name_ string) string {
|
fn (mut g JsGen) js_mname(name_ string) string {
|
||||||
mut is_js := false
|
mut is_js := false
|
||||||
|
@ -348,3 +349,178 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
||||||
}
|
}
|
||||||
g.call_stack.delete_last()
|
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 v.depgraph
|
||||||
import encoding.base64
|
import encoding.base64
|
||||||
import v.gen.js.sourcemap
|
import v.gen.js.sourcemap
|
||||||
import v.parser
|
|
||||||
|
|
||||||
struct MutArg {
|
|
||||||
tmp_var string
|
|
||||||
expr ast.Expr = ast.empty_expr()
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// https://ecma-international.org/ecma-262/#sec-reserved-words
|
// 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('')
|
||||||
g.writeln('globalThis.VTEST=1')
|
g.writeln('globalThis.VTEST=1')
|
||||||
if g.pref.is_stats {
|
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 {
|
for tname in all_tfuncs {
|
||||||
tcname := g.js_name(tname)
|
tcname := g.js_name(tname)
|
||||||
|
|
||||||
if g.pref.is_stats {
|
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) {} ')
|
g.writeln('try { ${tcname}(); } catch (_e) {} ')
|
||||||
if g.pref.is_stats {
|
if g.pref.is_stats {
|
||||||
g.writeln('bt.testing_step_end();')
|
g.writeln('main__BenchedTests_testing_step_end(bt);')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
if g.pref.is_stats {
|
if g.pref.is_stats {
|
||||||
g.writeln('bt.end_testing();')
|
g.writeln('main__BenchedTests_end_testing(bt);')
|
||||||
}
|
}
|
||||||
g.dec_indent()
|
g.dec_indent()
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
@ -489,62 +483,6 @@ fn (mut g JsGen) get_alias(name string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) js_name(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_
|
mut name := name_
|
||||||
if name.starts_with('JS.') {
|
if name.starts_with('JS.') {
|
||||||
name = name[3..]
|
name = name[3..]
|
||||||
|
@ -558,11 +496,9 @@ fn (mut g JsGen) js_name(name_ string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) stmts(stmts []ast.Stmt) {
|
fn (mut g JsGen) stmts(stmts []ast.Stmt) {
|
||||||
g.inc_indent()
|
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
}
|
}
|
||||||
g.dec_indent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[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) {
|
fn (mut g JsGen) stmt_no_semi(node ast.Stmt) {
|
||||||
g.stmt_start_pos = g.out.len
|
g.stmt_start_pos = g.out.len
|
||||||
match node {
|
match node {
|
||||||
|
@ -822,7 +763,12 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
||||||
g.gen_struct_decl(node)
|
g.gen_struct_decl(node)
|
||||||
}
|
}
|
||||||
ast.TypeDecl {
|
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) {
|
fn (mut g JsGen) gen_block(it ast.Block) {
|
||||||
g.writeln('{')
|
g.writeln('{')
|
||||||
|
g.inc_indent()
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
|
g.dec_indent()
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1338,59 +1286,9 @@ fn (mut g JsGen) gen_expr_stmt_no_semi(it ast.ExprStmt) {
|
||||||
g.expr(it.expr)
|
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)
|
// 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 {
|
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
|
mut styp := sym.cname
|
||||||
match mut sym.info {
|
match mut sym.info {
|
||||||
ast.Struct, ast.Interface, ast.SumType {
|
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
|
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) {
|
fn (mut g JsGen) gen_for_c_stmt(it ast.ForCStmt) {
|
||||||
g.inside_loop = true
|
g.inside_loop = true
|
||||||
g.write('for (')
|
g.write('for (')
|
||||||
|
@ -1918,11 +1591,6 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
|
||||||
g.writeln('};\n')
|
g.writeln('};\n')
|
||||||
g.dec_indent()
|
g.dec_indent()
|
||||||
|
|
||||||
/*
|
|
||||||
for cfn in fns {
|
|
||||||
g.gen_method_decl(cfn, .struct_method)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if node.is_pub {
|
if node.is_pub {
|
||||||
g.push_pub_var(name)
|
g.push_pub_var(name)
|
||||||
}
|
}
|
||||||
|
@ -2553,11 +2221,12 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
|
||||||
g.write('.valueOf()')
|
g.write('.valueOf()')
|
||||||
}
|
}
|
||||||
g.write('.arr')
|
g.write('.arr')
|
||||||
g.write('[+')
|
g.write('[Number(')
|
||||||
g.cast_stack << ast.int_type_idx
|
g.cast_stack << ast.int_type_idx
|
||||||
g.expr(expr.index)
|
g.expr(expr.index)
|
||||||
|
g.write('.valueOf()')
|
||||||
g.cast_stack.delete_last()
|
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('.valueOf()')
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if it.op == .eq || it.op == .ne {
|
} 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
|
node := it
|
||||||
left := g.unwrap(node.left_type)
|
left := g.unwrap(node.left_type)
|
||||||
right := g.unwrap(node.right_type)
|
right := g.unwrap(node.right_type)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
module stats_import
|
|
Loading…
Reference in New Issue