jsgen: start implementing remaining `expr`s and `stmt`s
							parent
							
								
									fd4d28b7b6
								
							
						
					
					
						commit
						4189190bb8
					
				| 
						 | 
				
			
			@ -4,7 +4,6 @@ import strings
 | 
			
		|||
import v.ast
 | 
			
		||||
import v.table
 | 
			
		||||
import v.pref
 | 
			
		||||
import term
 | 
			
		||||
import v.util
 | 
			
		||||
import v.depgraph
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +192,6 @@ pub fn (g JsGen) hashes() string {
 | 
			
		|||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// V type to JS type
 | 
			
		||||
pub fn (mut g JsGen) typ(t table.Type) string {
 | 
			
		||||
	sym := g.table.get_type_symbol(t)
 | 
			
		||||
| 
						 | 
				
			
			@ -382,9 +380,6 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
 | 
			
		|||
	g.stmt_start_pos = g.out.len
 | 
			
		||||
 | 
			
		||||
	match node {
 | 
			
		||||
		ast.Module {
 | 
			
		||||
			// TODO: Implement namespaces
 | 
			
		||||
		}
 | 
			
		||||
		ast.AssertStmt {
 | 
			
		||||
			g.gen_assert_stmt(it)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -401,12 +396,15 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
 | 
			
		|||
		ast.BranchStmt {
 | 
			
		||||
			g.gen_branch_stmt(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.ConstDecl {
 | 
			
		||||
			g.gen_const_decl(it)
 | 
			
		||||
		ast.Comment {
 | 
			
		||||
			// Skip: don't generate comments
 | 
			
		||||
		}
 | 
			
		||||
		ast.CompIf {
 | 
			
		||||
			// skip: JS has no compile time if
 | 
			
		||||
		}
 | 
			
		||||
		ast.ConstDecl {
 | 
			
		||||
			g.gen_const_decl(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.DeferStmt {
 | 
			
		||||
			g.defer_stmts << *it
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -434,6 +432,9 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
 | 
			
		|||
			g.gen_for_stmt(it)
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
		}
 | 
			
		||||
		ast.GlobalDecl {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.GoStmt {
 | 
			
		||||
			g.gen_go_stmt(it)
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
| 
						 | 
				
			
			@ -453,6 +454,9 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
 | 
			
		|||
		ast.InterfaceDecl {
 | 
			
		||||
			// TODO skip: interfaces not implemented yet
 | 
			
		||||
		}
 | 
			
		||||
		ast.Module {
 | 
			
		||||
			// skip: namespacing implemented externally
 | 
			
		||||
		}
 | 
			
		||||
		ast.Return {
 | 
			
		||||
			if g.defer_stmts.len > 0 {
 | 
			
		||||
				g.gen_defer_stmts()
 | 
			
		||||
| 
						 | 
				
			
			@ -468,20 +472,32 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
 | 
			
		|||
		ast.UnsafeStmt {
 | 
			
		||||
			g.stmts(it.stmts)
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		else {
 | 
			
		||||
			verror('jsgen.stmt(): bad node ${typeof(node)}')
 | 
			
		||||
		}
 | 
			
		||||
		*/
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) expr(node ast.Expr) {
 | 
			
		||||
	match node {
 | 
			
		||||
		ast.AnonFn {
 | 
			
		||||
			g.gen_fn_decl(it.decl)
 | 
			
		||||
		}
 | 
			
		||||
		ast.ArrayInit {
 | 
			
		||||
			g.gen_array_init_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.AsCast {
 | 
			
		||||
			// skip: JS has no types, so no need to cast
 | 
			
		||||
			// TODO: Is jsdoc needed here for TS support?
 | 
			
		||||
		}
 | 
			
		||||
		ast.AssignExpr {
 | 
			
		||||
			g.gen_assign_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.Assoc {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.BoolLiteral {
 | 
			
		||||
			if it.val == true {
 | 
			
		||||
				g.write('true')
 | 
			
		||||
| 
						 | 
				
			
			@ -489,11 +505,18 @@ fn (mut g JsGen) expr(node ast.Expr) {
 | 
			
		|||
				g.write('false')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ast.CallExpr {
 | 
			
		||||
			g.gen_call_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.CastExpr {
 | 
			
		||||
			// skip: JS has no types, so no need to cast
 | 
			
		||||
			// TODO: Check if jsdoc is needed for TS support
 | 
			
		||||
		}
 | 
			
		||||
		ast.CharLiteral {
 | 
			
		||||
			g.write("'$it.val'")
 | 
			
		||||
		}
 | 
			
		||||
		ast.CallExpr {
 | 
			
		||||
			g.gen_call_expr(it)
 | 
			
		||||
		ast.ConcatExpr {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.EnumVal {
 | 
			
		||||
			styp := g.typ(it.typ)
 | 
			
		||||
| 
						 | 
				
			
			@ -511,123 +534,74 @@ fn (mut g JsGen) expr(node ast.Expr) {
 | 
			
		|||
		ast.IfGuardExpr {
 | 
			
		||||
			// TODO no optionals yet
 | 
			
		||||
		}
 | 
			
		||||
		ast.IntegerLiteral {
 | 
			
		||||
			g.write(it.val)
 | 
			
		||||
		ast.IndexExpr {
 | 
			
		||||
			g.gen_index_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.InfixExpr {
 | 
			
		||||
			g.expr(it.left)
 | 
			
		||||
 | 
			
		||||
			mut op := it.op.str()
 | 
			
		||||
			// in js == is non-strict & === is strict, always do strict
 | 
			
		||||
			if op == '==' { op = '===' }
 | 
			
		||||
			else if op == '!=' { op = '!==' }
 | 
			
		||||
 | 
			
		||||
			g.write(' $op ')
 | 
			
		||||
			g.expr(it.right)
 | 
			
		||||
			g.gen_infix_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.IntegerLiteral {
 | 
			
		||||
			g.write(it.val)
 | 
			
		||||
		}
 | 
			
		||||
		ast.MapInit {
 | 
			
		||||
			g.gen_map_init_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		ast.UnaryExpr {
 | 
			
		||||
			g.expr(it.left)
 | 
			
		||||
			g.write(' $it.op ')
 | 
			
		||||
		ast.MatchExpr {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
		ast.StringLiteral {
 | 
			
		||||
			g.write('"$it.val"')
 | 
			
		||||
		ast.None {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.StringInterLiteral {
 | 
			
		||||
			g.gen_string_inter_literal(it)
 | 
			
		||||
		ast.OrExpr {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.ParExpr {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.PostfixExpr {
 | 
			
		||||
			g.expr(it.expr)
 | 
			
		||||
			g.write(it.op.str())
 | 
			
		||||
		}
 | 
			
		||||
		ast.StructInit {
 | 
			
		||||
			// `user := User{name: 'Bob'}`
 | 
			
		||||
			g.gen_struct_init(it)
 | 
			
		||||
		ast.PrefixExpr {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.RangeExpr {
 | 
			
		||||
			// Only used in IndexExpr, requires index type info
 | 
			
		||||
		}
 | 
			
		||||
		ast.SelectorExpr {
 | 
			
		||||
			g.gen_selector_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.AnonFn {
 | 
			
		||||
			g.gen_anon_fn_decl(it)
 | 
			
		||||
		ast.SizeOf {
 | 
			
		||||
			// TODO
 | 
			
		||||
		}
 | 
			
		||||
		ast.StringInterLiteral {
 | 
			
		||||
			g.gen_string_inter_literal(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.StringLiteral {
 | 
			
		||||
			g.write('"$it.val"')
 | 
			
		||||
		}
 | 
			
		||||
		ast.StructInit {
 | 
			
		||||
			// `user := User{name: 'Bob'}`
 | 
			
		||||
			g.gen_struct_init(it)
 | 
			
		||||
		}
 | 
			
		||||
		ast.Type {
 | 
			
		||||
			// skip: JS has no types
 | 
			
		||||
			// TODO maybe?
 | 
			
		||||
		}
 | 
			
		||||
		ast.TypeOf {
 | 
			
		||||
			g.gen_typeof_expr(it)
 | 
			
		||||
			// TODO: Should this print the V type or the JS type?
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		else {
 | 
			
		||||
			println(term.red('jsgen.expr(): bad node "${typeof(node)}"'))
 | 
			
		||||
			println(term.red('jsgen.expr(): unhandled node "${typeof(node)}"'))
 | 
			
		||||
		}
 | 
			
		||||
		*/
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
 | 
			
		||||
	g.write('tos3(`')
 | 
			
		||||
	for i, val in it.vals {
 | 
			
		||||
		escaped_val := val.replace_each(['`', '\`', '\r\n', '\n'])
 | 
			
		||||
		g.write(escaped_val)
 | 
			
		||||
		if i >= it.exprs.len {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		expr := it.exprs[i]
 | 
			
		||||
		sfmt := it.expr_fmts[i]
 | 
			
		||||
		g.write('\${')
 | 
			
		||||
		if sfmt.len > 0 {
 | 
			
		||||
			fspec := sfmt[sfmt.len - 1]
 | 
			
		||||
			if fspec == `s` && it.expr_types[i] == table.string_type {
 | 
			
		||||
				g.expr(expr)
 | 
			
		||||
				g.write('.str')
 | 
			
		||||
			} else {
 | 
			
		||||
				g.expr(expr)
 | 
			
		||||
			}
 | 
			
		||||
		} else if it.expr_types[i] == table.string_type {
 | 
			
		||||
			// `name.str`
 | 
			
		||||
			g.expr(expr)
 | 
			
		||||
			g.write('.str')
 | 
			
		||||
		} else if it.expr_types[i] == table.bool_type {
 | 
			
		||||
			// `expr ? "true" : "false"`
 | 
			
		||||
			g.expr(expr)
 | 
			
		||||
			g.write(' ? "true" : "false"')
 | 
			
		||||
		} else {
 | 
			
		||||
			sym := g.table.get_type_symbol(it.expr_types[i])
 | 
			
		||||
 | 
			
		||||
			match sym.kind {
 | 
			
		||||
				.struct_ {
 | 
			
		||||
					g.expr(expr)
 | 
			
		||||
					if sym.has_method('str') {
 | 
			
		||||
						g.write('.str()')
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					g.expr(expr)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		g.write('}')
 | 
			
		||||
	}
 | 
			
		||||
	g.write('`)')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_import_stmt(it ast.Import) {
 | 
			
		||||
	mut imports := g.namespace_imports[g.namespace]
 | 
			
		||||
	imports[it.mod] = it.alias
 | 
			
		||||
	g.namespace_imports[g.namespace] = imports
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
 | 
			
		||||
	type_sym := g.table.get_type_symbol(it.typ)
 | 
			
		||||
	if type_sym.kind != .array_fixed {
 | 
			
		||||
		g.write('[')
 | 
			
		||||
		for i, expr in it.exprs {
 | 
			
		||||
			g.expr(expr)
 | 
			
		||||
			if i < it.exprs.len - 1 {
 | 
			
		||||
				g.write(', ')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		g.write(']')
 | 
			
		||||
	} else {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO
 | 
			
		||||
fn (mut g JsGen) gen_assert_stmt(a ast.AssertStmt) {
 | 
			
		||||
	g.writeln('// assert')
 | 
			
		||||
	g.write('if( ')
 | 
			
		||||
| 
						 | 
				
			
			@ -713,12 +687,6 @@ fn (mut g JsGen) gen_assign_stmt(it ast.AssignStmt) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_assign_expr(it ast.AssignExpr) {
 | 
			
		||||
	g.expr(it.left)
 | 
			
		||||
	g.write(' $it.op ')
 | 
			
		||||
	g.expr(it.val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_attr(it ast.Attr) {
 | 
			
		||||
	g.writeln('/* [$it.name] */')
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -807,8 +775,12 @@ fn (mut g JsGen) gen_fn_decl(it ast.FnDecl) {
 | 
			
		|||
	g.gen_method_decl(it)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_anon_fn_decl(it ast.AnonFn) {
 | 
			
		||||
	g.gen_method_decl(it.decl)
 | 
			
		||||
fn fn_has_go(it ast.FnDecl) bool {
 | 
			
		||||
	mut has_go := false
 | 
			
		||||
	for stmt in it.stmts {
 | 
			
		||||
		if stmt is ast.GoStmt { has_go = true }
 | 
			
		||||
	}
 | 
			
		||||
	return has_go
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
 | 
			
		||||
| 
						 | 
				
			
			@ -875,6 +847,23 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
 | 
			
		|||
	g.fn_decl = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) fn_args(args []table.Arg, is_variadic bool) {
 | 
			
		||||
	// no_names := args.len > 0 && args[0].name == 'arg_1'
 | 
			
		||||
	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 (')
 | 
			
		||||
| 
						 | 
				
			
			@ -961,23 +950,6 @@ fn (mut g JsGen) gen_for_stmt(it ast.ForStmt) {
 | 
			
		|||
	g.writeln('}')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) fn_args(args []table.Arg, is_variadic bool) {
 | 
			
		||||
	// no_names := args.len > 0 && args[0].name == 'arg_1'
 | 
			
		||||
	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_go_stmt(node ast.GoStmt) {
 | 
			
		||||
	// x := node.call_expr as ast.CallEpxr // TODO
 | 
			
		||||
	match node.call_expr {
 | 
			
		||||
| 
						 | 
				
			
			@ -1005,39 +977,21 @@ fn (mut g JsGen) gen_go_stmt(node ast.GoStmt) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
 | 
			
		||||
	// key_typ_sym := g.table.get_type_symbol(it.key_type)
 | 
			
		||||
	// value_typ_sym := g.table.get_type_symbol(it.value_type)
 | 
			
		||||
	// key_typ_str := key_typ_sym.name.replace('.', '__')
 | 
			
		||||
	// value_typ_str := value_typ_sym.name.replace('.', '__')
 | 
			
		||||
	if it.vals.len > 0 {
 | 
			
		||||
		g.writeln('new Map([')
 | 
			
		||||
		g.inc_indent()
 | 
			
		||||
		for i, key in it.keys {
 | 
			
		||||
			val := it.vals[i]
 | 
			
		||||
			g.write('[')
 | 
			
		||||
			g.expr(key)
 | 
			
		||||
			g.write(', ')
 | 
			
		||||
			g.expr(val)
 | 
			
		||||
			g.write(']')
 | 
			
		||||
			if i < it.keys.len - 1 {
 | 
			
		||||
				g.write(',')
 | 
			
		||||
			}
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
		}
 | 
			
		||||
		g.dec_indent()
 | 
			
		||||
		g.write('])')
 | 
			
		||||
	} else {
 | 
			
		||||
		g.write('new Map()')
 | 
			
		||||
	}
 | 
			
		||||
fn (mut g JsGen) gen_import_stmt(it ast.Import) {
 | 
			
		||||
	mut imports := g.namespace_imports[g.namespace]
 | 
			
		||||
	imports[it.mod] = it.alias
 | 
			
		||||
	g.namespace_imports[g.namespace] = imports
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_return_stmt(it ast.Return) {
 | 
			
		||||
	g.write('return ')
 | 
			
		||||
 | 
			
		||||
	if it.exprs.len == 0 {
 | 
			
		||||
		// Returns nothing
 | 
			
		||||
	} else if it.exprs.len == 1 {
 | 
			
		||||
		g.write('return;')
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g.write('return ')
 | 
			
		||||
	if it.exprs.len == 1 {
 | 
			
		||||
		g.expr(it.exprs[0])
 | 
			
		||||
	} else {
 | 
			
		||||
		// Multi return
 | 
			
		||||
| 
						 | 
				
			
			@ -1053,13 +1007,6 @@ fn (mut g JsGen) gen_return_stmt(it ast.Return) {
 | 
			
		|||
	g.writeln(';')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) enum_expr(node ast.Expr) {
 | 
			
		||||
	match node {
 | 
			
		||||
		ast.EnumVal { g.write(it.val) }
 | 
			
		||||
		else { g.expr(node) }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
 | 
			
		||||
	g.writeln(g.doc.gen_fac_fn(node.fields))
 | 
			
		||||
	g.write('function ${g.js_name(node.name)}({ ')
 | 
			
		||||
| 
						 | 
				
			
			@ -1104,37 +1051,24 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_struct_init(it ast.StructInit) {
 | 
			
		||||
fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) {
 | 
			
		||||
	type_sym := g.table.get_type_symbol(it.typ)
 | 
			
		||||
	name := type_sym.name
 | 
			
		||||
	if it.fields.len == 0 {
 | 
			
		||||
		g.write('new ${g.js_name(name)}({})')
 | 
			
		||||
	} else {
 | 
			
		||||
		g.writeln('new ${g.js_name(name)}({')
 | 
			
		||||
		g.inc_indent()
 | 
			
		||||
		for i, field in it.fields {
 | 
			
		||||
			g.write('$field.name: ')
 | 
			
		||||
			g.expr(field.expr)
 | 
			
		||||
			if i < it.fields.len - 1 {
 | 
			
		||||
	if type_sym.kind != .array_fixed {
 | 
			
		||||
		g.write('[')
 | 
			
		||||
		for i, expr in it.exprs {
 | 
			
		||||
			g.expr(expr)
 | 
			
		||||
			if i < it.exprs.len - 1 {
 | 
			
		||||
				g.write(', ')
 | 
			
		||||
			}
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
		}
 | 
			
		||||
		g.dec_indent()
 | 
			
		||||
		g.write('})')
 | 
			
		||||
	}
 | 
			
		||||
		g.write(']')
 | 
			
		||||
	} else {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_ident(node ast.Ident) {
 | 
			
		||||
	if node.kind == .constant {
 | 
			
		||||
		// TODO: Handle const namespacing: only consts in the main module are handled rn
 | 
			
		||||
		g.write('_CONSTS.')
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := g.js_name(node.name)
 | 
			
		||||
	// TODO `is`
 | 
			
		||||
	// TODO handle optionals
 | 
			
		||||
	g.write(name)
 | 
			
		||||
fn (mut g JsGen) gen_assign_expr(it ast.AssignExpr) {
 | 
			
		||||
	g.expr(it.left)
 | 
			
		||||
	g.write(' $it.op ')
 | 
			
		||||
	g.expr(it.val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1163,9 +1097,16 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
 | 
			
		|||
	g.write(')')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) {
 | 
			
		||||
	g.expr(it.expr)
 | 
			
		||||
	g.write('.$it.field_name')
 | 
			
		||||
fn (mut g JsGen) gen_ident(node ast.Ident) {
 | 
			
		||||
	if node.kind == .constant {
 | 
			
		||||
		// TODO: Handle const namespacing: only consts in the main module are handled rn
 | 
			
		||||
		g.write('_CONSTS.')
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name := g.js_name(node.name)
 | 
			
		||||
	// TODO `is`
 | 
			
		||||
	// TODO handle optionals
 | 
			
		||||
	g.write(name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_if_expr(node ast.IfExpr) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1223,14 +1164,172 @@ fn (mut g JsGen) gen_if_expr(node ast.IfExpr) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn verror(s string) {
 | 
			
		||||
	util.verror('jsgen error', s)
 | 
			
		||||
fn (mut g JsGen) gen_index_expr(it ast.IndexExpr) {
 | 
			
		||||
	// TODO: Handle splice setting if it's implemented
 | 
			
		||||
	if it.index is ast.RangeExpr {
 | 
			
		||||
		range := it.index as ast.RangeExpr
 | 
			
		||||
		g.expr(it.left)
 | 
			
		||||
		g.write('.slice(')
 | 
			
		||||
		if range.has_low {
 | 
			
		||||
			g.expr(range.low)
 | 
			
		||||
		} else {
 | 
			
		||||
			g.write('0')
 | 
			
		||||
		}
 | 
			
		||||
		g.write(', ')
 | 
			
		||||
		if range.has_high {
 | 
			
		||||
			g.expr(range.high)
 | 
			
		||||
		} else {
 | 
			
		||||
			g.expr(it.left)
 | 
			
		||||
			g.write('.length')
 | 
			
		||||
		}
 | 
			
		||||
		g.write(')')
 | 
			
		||||
	} else {
 | 
			
		||||
		// TODO Does this work in all cases?
 | 
			
		||||
		g.expr(it.left)
 | 
			
		||||
		g.write('[')
 | 
			
		||||
		g.expr(it.index)
 | 
			
		||||
		g.write(']')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fn_has_go(it ast.FnDecl) bool {
 | 
			
		||||
	mut has_go := false
 | 
			
		||||
	for stmt in it.stmts {
 | 
			
		||||
		if stmt is ast.GoStmt { has_go = true }
 | 
			
		||||
	}
 | 
			
		||||
	return has_go
 | 
			
		||||
fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
 | 
			
		||||
	g.expr(it.left)
 | 
			
		||||
 | 
			
		||||
	mut op := it.op.str()
 | 
			
		||||
	// in js == is non-strict & === is strict, always do strict
 | 
			
		||||
	if op == '==' { op = '===' }
 | 
			
		||||
	else if op == '!=' { op = '!==' }
 | 
			
		||||
 | 
			
		||||
	g.write(' $op ')
 | 
			
		||||
	g.expr(it.right)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
 | 
			
		||||
	// key_typ_sym := g.table.get_type_symbol(it.key_type)
 | 
			
		||||
	// value_typ_sym := g.table.get_type_symbol(it.value_type)
 | 
			
		||||
	// key_typ_str := key_typ_sym.name.replace('.', '__')
 | 
			
		||||
	// value_typ_str := value_typ_sym.name.replace('.', '__')
 | 
			
		||||
	if it.vals.len > 0 {
 | 
			
		||||
		g.writeln('new Map([')
 | 
			
		||||
		g.inc_indent()
 | 
			
		||||
		for i, key in it.keys {
 | 
			
		||||
			val := it.vals[i]
 | 
			
		||||
			g.write('[')
 | 
			
		||||
			g.expr(key)
 | 
			
		||||
			g.write(', ')
 | 
			
		||||
			g.expr(val)
 | 
			
		||||
			g.write(']')
 | 
			
		||||
			if i < it.keys.len - 1 {
 | 
			
		||||
				g.write(',')
 | 
			
		||||
			}
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
		}
 | 
			
		||||
		g.dec_indent()
 | 
			
		||||
		g.write('])')
 | 
			
		||||
	} else {
 | 
			
		||||
		g.write('new Map()')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) {
 | 
			
		||||
	g.expr(it.expr)
 | 
			
		||||
	g.write('.$it.field_name')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
 | 
			
		||||
	// TODO Implement `tos3`
 | 
			
		||||
	g.write('tos3(`')
 | 
			
		||||
	for i, val in it.vals {
 | 
			
		||||
		escaped_val := val.replace_each(['`', '\`', '\r\n', '\n'])
 | 
			
		||||
		g.write(escaped_val)
 | 
			
		||||
		if i >= it.exprs.len {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		expr := it.exprs[i]
 | 
			
		||||
		sfmt := it.expr_fmts[i]
 | 
			
		||||
		g.write('\${')
 | 
			
		||||
		if sfmt.len > 0 {
 | 
			
		||||
			fspec := sfmt[sfmt.len - 1]
 | 
			
		||||
			if fspec == `s` && it.expr_types[i] == table.string_type {
 | 
			
		||||
				g.expr(expr)
 | 
			
		||||
				g.write('.str')
 | 
			
		||||
			} else {
 | 
			
		||||
				g.expr(expr)
 | 
			
		||||
			}
 | 
			
		||||
		} else if it.expr_types[i] == table.string_type {
 | 
			
		||||
			// `name.str`
 | 
			
		||||
			g.expr(expr)
 | 
			
		||||
			g.write('.str')
 | 
			
		||||
		} else if it.expr_types[i] == table.bool_type {
 | 
			
		||||
			// `expr ? "true" : "false"`
 | 
			
		||||
			g.expr(expr)
 | 
			
		||||
			g.write(' ? "true" : "false"')
 | 
			
		||||
		} else {
 | 
			
		||||
			sym := g.table.get_type_symbol(it.expr_types[i])
 | 
			
		||||
 | 
			
		||||
			match sym.kind {
 | 
			
		||||
				.struct_ {
 | 
			
		||||
					g.expr(expr)
 | 
			
		||||
					if sym.has_method('str') {
 | 
			
		||||
						g.write('.str()')
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					g.expr(expr)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		g.write('}')
 | 
			
		||||
	}
 | 
			
		||||
	g.write('`)')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_struct_init(it ast.StructInit) {
 | 
			
		||||
	type_sym := g.table.get_type_symbol(it.typ)
 | 
			
		||||
	name := type_sym.name
 | 
			
		||||
	if it.fields.len == 0 {
 | 
			
		||||
		g.write('new ${g.js_name(name)}({})')
 | 
			
		||||
	} else {
 | 
			
		||||
		g.writeln('new ${g.js_name(name)}({')
 | 
			
		||||
		g.inc_indent()
 | 
			
		||||
		for i, field in it.fields {
 | 
			
		||||
			g.write('$field.name: ')
 | 
			
		||||
			g.expr(field.expr)
 | 
			
		||||
			if i < it.fields.len - 1 {
 | 
			
		||||
				g.write(',')
 | 
			
		||||
			}
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
		}
 | 
			
		||||
		g.dec_indent()
 | 
			
		||||
		g.write('})')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
 | 
			
		||||
	sym := g.table.get_type_symbol(it.expr_type)
 | 
			
		||||
	if sym.kind == .sum_type {
 | 
			
		||||
		// TODO: JS sumtypes not implemented yet
 | 
			
		||||
	} else if sym.kind == .array_fixed {
 | 
			
		||||
		fixed_info := sym.info as table.ArrayFixed
 | 
			
		||||
		typ_name := g.table.get_type_name(fixed_info.elem_type)
 | 
			
		||||
		g.write('"[$fixed_info.size]${typ_name}"')
 | 
			
		||||
	} else if sym.kind == .function {
 | 
			
		||||
		info := sym.info as table.FnType
 | 
			
		||||
		fn_info := info.func
 | 
			
		||||
		mut repr := 'fn ('
 | 
			
		||||
		for i, arg in fn_info.args {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				repr += ', '
 | 
			
		||||
			}
 | 
			
		||||
			repr += g.table.get_type_name(arg.typ)
 | 
			
		||||
		}
 | 
			
		||||
		repr += ')'
 | 
			
		||||
		if fn_info.return_type != table.void_type {
 | 
			
		||||
			repr += ' ${g.table.get_type_name(fn_info.return_type)}'
 | 
			
		||||
		}
 | 
			
		||||
		g.write('"$repr"')
 | 
			
		||||
	} else {
 | 
			
		||||
		g.write('"${sym.name}"')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
// V_COMMIT_HASH 0de70e8
 | 
			
		||||
// V_CURRENT_COMMIT_HASH 4271eb4
 | 
			
		||||
// Generated by the V compiler
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
/** @namespace builtin */
 | 
			
		||||
const builtin = (function () {
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {any} s
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function println(s) {
 | 
			
		||||
		console.log(s);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {any} s
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function print(s) {
 | 
			
		||||
		process.stdout.write(s);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* module exports */
 | 
			
		||||
	return {
 | 
			
		||||
		println,
 | 
			
		||||
		print,
 | 
			
		||||
	};
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
/** @namespace main */
 | 
			
		||||
const main = (function () {
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {...number} args
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function variadic(...args) {
 | 
			
		||||
		builtin.println(args);
 | 
			
		||||
		builtin.println(args[0]);
 | 
			
		||||
		builtin.println(args[1]);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function vararg_test() {
 | 
			
		||||
		variadic(1, 2, 3);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* program entry point */
 | 
			
		||||
	(function() {
 | 
			
		||||
		vararg_test();
 | 
			
		||||
		/** @type {string[]} - arr1 */
 | 
			
		||||
		const arr1 = ["Hello", "JS", "Backend"];
 | 
			
		||||
		/** @type {number[]} - arr2 */
 | 
			
		||||
		let arr2 = [1, 2, 3, 4, 5];
 | 
			
		||||
		/** @type {string[]} - slice1 */
 | 
			
		||||
		const slice1 = arr1.slice(1, 3);
 | 
			
		||||
		/** @type {number[]} - slice2 */
 | 
			
		||||
		const slice2 = arr2.slice(0, 3);
 | 
			
		||||
		/** @type {number[]} - slice3 */
 | 
			
		||||
		const slice3 = arr2.slice(3, arr2.length);
 | 
			
		||||
		/** @type {string} - idx1 */
 | 
			
		||||
		const idx1 = slice1[1];
 | 
			
		||||
		arr2[0] = 1;
 | 
			
		||||
		arr2[0 + 1] = 2;
 | 
			
		||||
		builtin.println(arr2);
 | 
			
		||||
		/** @type {string} - slice4 */
 | 
			
		||||
		const slice4 = idx1.slice(0, 4);
 | 
			
		||||
		builtin.println(slice4);
 | 
			
		||||
		/** @type {byte} - idx2 */
 | 
			
		||||
		const idx2 = slice4[0];
 | 
			
		||||
		/** @type {Map<string, string>} - m */
 | 
			
		||||
		let m = new Map();
 | 
			
		||||
		/** @type {string} - key */
 | 
			
		||||
		const key = "key";
 | 
			
		||||
		m[key] = "value";
 | 
			
		||||
		/** @type {string} - val */
 | 
			
		||||
		const val = m["key"];
 | 
			
		||||
		builtin.println(val);
 | 
			
		||||
	})();
 | 
			
		||||
 | 
			
		||||
	/* module exports */
 | 
			
		||||
	return {};
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
fn variadic(args ...int) {
 | 
			
		||||
	println(args)
 | 
			
		||||
	println(args[0])
 | 
			
		||||
	println(args[1])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn vararg_test() {
 | 
			
		||||
	variadic(1, 2, 3)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vararg_test()
 | 
			
		||||
 | 
			
		||||
arr1 := ['Hello', 'JS', 'Backend']
 | 
			
		||||
mut arr2 := [1, 2, 3, 4, 5]
 | 
			
		||||
 | 
			
		||||
// Array slices
 | 
			
		||||
slice1 := arr1[1..3]
 | 
			
		||||
slice2 := arr2[..3]
 | 
			
		||||
slice3 := arr2[3..]
 | 
			
		||||
 | 
			
		||||
// Array indexes
 | 
			
		||||
idx1 := slice1[1]
 | 
			
		||||
arr2[0] = 1
 | 
			
		||||
arr2[0 + 1] = 2
 | 
			
		||||
println(arr2)
 | 
			
		||||
 | 
			
		||||
// String slices
 | 
			
		||||
slice4 := idx1[..4]
 | 
			
		||||
println(slice4) // 'Back'
 | 
			
		||||
 | 
			
		||||
// String indexes
 | 
			
		||||
idx2 := slice4[0]
 | 
			
		||||
 | 
			
		||||
// TODO: This does not work for now
 | 
			
		||||
// arr2[0..1] = arr2[3..4]
 | 
			
		||||
// println(arr2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Maps
 | 
			
		||||
mut m := map[string]string
 | 
			
		||||
key := 'key'
 | 
			
		||||
m[key] = 'value'
 | 
			
		||||
val := m['key']
 | 
			
		||||
println(val)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
// V_COMMIT_HASH 74686d0
 | 
			
		||||
// V_CURRENT_COMMIT_HASH 0d3f133
 | 
			
		||||
// V_COMMIT_HASH 0de70e8
 | 
			
		||||
// V_CURRENT_COMMIT_HASH 4271eb4
 | 
			
		||||
// Generated by the V compiler
 | 
			
		||||
 | 
			
		||||
"use strict";
 | 
			
		||||
| 
						 | 
				
			
			@ -11,51 +11,81 @@ const _CONSTS = Object.freeze({
 | 
			
		|||
	v_super: "amazing keyword"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/* namespace: hello */
 | 
			
		||||
const hello = (function () {
 | 
			
		||||
	class A {
 | 
			
		||||
		/**
 | 
			
		||||
		 * @param {{foo?: string}} values - values for this class fields
 | 
			
		||||
		 * @constructor
 | 
			
		||||
		*/
 | 
			
		||||
		constructor(values) {
 | 
			
		||||
			this.foo = values.foo
 | 
			
		||||
		}
 | 
			
		||||
/** @namespace builtin */
 | 
			
		||||
const builtin = (function () {
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {any} s
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function println(s) {
 | 
			
		||||
		console.log(s);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {any} s
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function print(s) {
 | 
			
		||||
		process.stdout.write(s);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* module exports */
 | 
			
		||||
	return {
 | 
			
		||||
		println,
 | 
			
		||||
		print,
 | 
			
		||||
	};
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
/** @namespace hello */
 | 
			
		||||
const hello = (function () {
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {{foo?: string}} values - values for this class fields
 | 
			
		||||
	 * @constructor
 | 
			
		||||
	*/
 | 
			
		||||
	function A({ foo = "" }) {
 | 
			
		||||
		this.foo = foo
 | 
			
		||||
	};
 | 
			
		||||
	A.prototype = {
 | 
			
		||||
		/** @type {string} - foo */
 | 
			
		||||
		foo: "",
 | 
			
		||||
		/**
 | 
			
		||||
		 * @param {string} s
 | 
			
		||||
		 * @returns {void}
 | 
			
		||||
		 * @function
 | 
			
		||||
		*/
 | 
			
		||||
		update(s) {
 | 
			
		||||
			const a = this;
 | 
			
		||||
			a.foo = s;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	class B {
 | 
			
		||||
		/**
 | 
			
		||||
		 * @param {{}} values - values for this class fields
 | 
			
		||||
		 * @constructor
 | 
			
		||||
		*/
 | 
			
		||||
		constructor(values) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {{}} values - values for this class fields
 | 
			
		||||
	 * @constructor
 | 
			
		||||
	*/
 | 
			
		||||
	function B({  }) {
 | 
			
		||||
	};
 | 
			
		||||
	B.prototype = {
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const C = Object.freeze({
 | 
			
		||||
	});
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * @returns {string}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function v_debugger() {
 | 
			
		||||
		const v = new B({
 | 
			
		||||
		});
 | 
			
		||||
		const v = new B({});
 | 
			
		||||
		return "Hello";
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * @returns {string}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function excited() {
 | 
			
		||||
		return v_debugger() + "!";
 | 
			
		||||
| 
						 | 
				
			
			@ -70,31 +100,39 @@ const hello = (function () {
 | 
			
		|||
	};
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
/* namespace: main */
 | 
			
		||||
/** @namespace main */
 | 
			
		||||
const main = (function (hl) {
 | 
			
		||||
	class Foo {
 | 
			
		||||
		/**
 | 
			
		||||
		 * @param {{a?: hl["A"]["prototype"]}} values - values for this class fields
 | 
			
		||||
		 * @constructor
 | 
			
		||||
		*/
 | 
			
		||||
		constructor(values) {
 | 
			
		||||
			this.a = values.a
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	class Companies {
 | 
			
		||||
		/**
 | 
			
		||||
		 * @param {{google?: number, amazon?: boolean, yahoo?: string}} values - values for this class fields
 | 
			
		||||
		 * @constructor
 | 
			
		||||
		*/
 | 
			
		||||
		constructor(values) {
 | 
			
		||||
			this.google = values.google
 | 
			
		||||
			this.amazon = values.amazon
 | 
			
		||||
			this.yahoo = values.yahoo
 | 
			
		||||
		}
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {{a?: hl["A"]["prototype"]}} values - values for this class fields
 | 
			
		||||
	 * @constructor
 | 
			
		||||
	*/
 | 
			
		||||
	function Foo({ a = {} }) {
 | 
			
		||||
		this.a = a
 | 
			
		||||
	};
 | 
			
		||||
	Foo.prototype = {
 | 
			
		||||
		/** @type {hl["A"]["prototype"]} - a */
 | 
			
		||||
		a: {}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {{google?: number, amazon?: boolean, yahoo?: string}} values - values for this class fields
 | 
			
		||||
	 * @constructor
 | 
			
		||||
	*/
 | 
			
		||||
	function Companies({ google = 0, amazon = false, yahoo = "" }) {
 | 
			
		||||
		this.google = google
 | 
			
		||||
		this.amazon = amazon
 | 
			
		||||
		this.yahoo = yahoo
 | 
			
		||||
	};
 | 
			
		||||
	Companies.prototype = {
 | 
			
		||||
		/** @type {number} - google */
 | 
			
		||||
		google: 0,
 | 
			
		||||
		/** @type {boolean} - amazon */
 | 
			
		||||
		amazon: false,
 | 
			
		||||
		/** @type {string} - yahoo */
 | 
			
		||||
		yahoo: "",
 | 
			
		||||
		/**
 | 
			
		||||
		 * @returns {number}
 | 
			
		||||
		 * @function
 | 
			
		||||
		*/
 | 
			
		||||
		method() {
 | 
			
		||||
			const it = this;
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +150,7 @@ const main = (function (hl) {
 | 
			
		|||
			
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	const POSITION = Object.freeze({
 | 
			
		||||
		go_back: 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +161,7 @@ const main = (function (hl) {
 | 
			
		|||
	 * @param {string} v_extends
 | 
			
		||||
	 * @param {number} v_instanceof
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function v_class(v_extends, v_instanceof) {
 | 
			
		||||
		/** @type {number} - v_delete */
 | 
			
		||||
| 
						 | 
				
			
			@ -131,22 +170,20 @@ const main = (function (hl) {
 | 
			
		|||
	
 | 
			
		||||
	/* program entry point */
 | 
			
		||||
	(async function() {
 | 
			
		||||
		console.log("Hello from V.js!");
 | 
			
		||||
		builtin.println("Hello from V.js!");
 | 
			
		||||
		/** @type {number} - a */
 | 
			
		||||
		let a = 1;
 | 
			
		||||
		a *= 2;
 | 
			
		||||
		a += 3;
 | 
			
		||||
		console.log(a, " ==  5");
 | 
			
		||||
		const b = new hl.A({
 | 
			
		||||
		});
 | 
			
		||||
		builtin.println(a);
 | 
			
		||||
		const b = new hl.A({});
 | 
			
		||||
		b.update("an update");
 | 
			
		||||
		console.log(b);
 | 
			
		||||
		builtin.println(b);
 | 
			
		||||
		const c = new Foo({
 | 
			
		||||
			a: new hl.A({
 | 
			
		||||
			})
 | 
			
		||||
			a: new hl.A({})
 | 
			
		||||
		});
 | 
			
		||||
		c.a.update("another update");
 | 
			
		||||
		console.log(c);
 | 
			
		||||
		builtin.println(c);
 | 
			
		||||
		/** @type {string} - v */
 | 
			
		||||
		const v = "done";
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -198,11 +235,11 @@ const main = (function (hl) {
 | 
			
		|||
		
 | 
			
		||||
		/** @type {(number: number) => void} - fn_in_var */
 | 
			
		||||
		const fn_in_var = function (number) {
 | 
			
		||||
			console.log(tos3(`number: ${number}`));
 | 
			
		||||
			builtin.println(tos3(`number: ${number}`));
 | 
			
		||||
		};
 | 
			
		||||
		hl.v_debugger();
 | 
			
		||||
		anon_consumer(hl.excited(), function (message) {
 | 
			
		||||
			console.log(message);
 | 
			
		||||
			builtin.println(message);
 | 
			
		||||
		});
 | 
			
		||||
	})();
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -210,6 +247,7 @@ const main = (function (hl) {
 | 
			
		|||
	 * @param {string} greeting
 | 
			
		||||
	 * @param {(message: string) => void} anon
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function anon_consumer(greeting, anon) {
 | 
			
		||||
		anon(greeting);
 | 
			
		||||
| 
						 | 
				
			
			@ -219,6 +257,7 @@ const main = (function (hl) {
 | 
			
		|||
	 * @param {number} num
 | 
			
		||||
	 * @param {string} def
 | 
			
		||||
	 * @returns {void}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function async(num, def) {
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +269,7 @@ const main = (function (hl) {
 | 
			
		|||
	 * @param {number} game_on
 | 
			
		||||
	 * @param {...string} dummy
 | 
			
		||||
	 * @returns {[number, number]}
 | 
			
		||||
	 * @function
 | 
			
		||||
	*/
 | 
			
		||||
	function hello(game_on, ...dummy) {
 | 
			
		||||
		for (let _tmp2 = 0; _tmp2 < dummy.length; ++_tmp2) {
 | 
			
		||||
| 
						 | 
				
			
			@ -246,8 +286,7 @@ const main = (function (hl) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* module exports */
 | 
			
		||||
	return {
 | 
			
		||||
	};
 | 
			
		||||
	return {};
 | 
			
		||||
})(hello);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
import hello as hl
 | 
			
		||||
 | 
			
		||||
fn JS.alert(arg string)
 | 
			
		||||
fn JS.console.log(arg string)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
    i_am_a_const = 21214
 | 
			
		||||
| 
						 | 
				
			
			@ -29,20 +28,20 @@ fn class(extends string, instanceof int) {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    JS.console.log('Hello from V.js!')
 | 
			
		||||
    println('Hello from V.js!')
 | 
			
		||||
 | 
			
		||||
    mut a := 1
 | 
			
		||||
    a *= 2
 | 
			
		||||
    a += 3
 | 
			
		||||
    JS.console.log(a, ' ==  5') // TODO: Handle string interpolation
 | 
			
		||||
    println(a) // TODO: Handle string interpolation
 | 
			
		||||
 | 
			
		||||
    b := hl.A{}
 | 
			
		||||
    b.update('an update')
 | 
			
		||||
    JS.console.log(b)
 | 
			
		||||
    println(b)
 | 
			
		||||
 | 
			
		||||
    c := Foo{ hl.A{} }
 | 
			
		||||
    c.a.update('another update')
 | 
			
		||||
    JS.console.log(c)
 | 
			
		||||
    println(c)
 | 
			
		||||
 | 
			
		||||
    v := "done"
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -81,12 +80,12 @@ fn main() {
 | 
			
		|||
    go async(0, "hello")
 | 
			
		||||
 | 
			
		||||
    fn_in_var := fn (number int) {
 | 
			
		||||
        JS.console.log("number: $number")
 | 
			
		||||
        println("number: $number")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hl.debugger()
 | 
			
		||||
    anon_consumer(hl.excited(), fn (message string) {
 | 
			
		||||
        JS.console.log(message)
 | 
			
		||||
        println(message)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue