v.gen.js: improve reference support (#10793)

pull/10801/head
playX 2021-07-14 11:43:48 +03:00 committed by GitHub
parent 19642a1182
commit 9c710b2a34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 33 additions and 98 deletions

View File

@ -655,13 +655,18 @@ fn (mut g JsGen) expr(node ast.Expr) {
if node.op in [.amp, .mul] {
// C pointers/references: ignore them
if node.op == .amp {
g.write('{ value: ')
g.expr(node.right)
g.write(' } ')
type_sym := g.table.get_type_symbol(node.right_type)
if !type_sym.is_primitive() && !node.right_type.is_pointer() {
g.write('{ val: ')
g.expr(node.right)
g.write(' } ')
} else {
g.expr(node.right)
}
} else {
g.write('(')
g.expr(node.right)
g.write(').value')
g.write(').val')
}
} else {
g.write(node.op.str())
@ -808,13 +813,18 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt) {
}
}
g.expr(left)
mut is_ptr := false
if stmt.op == .assign && stmt.left_types[i].is_ptr() {
g.write('.value')
is_ptr = true
g.write('.val')
}
if g.inside_map_set && op == .assign {
g.inside_map_set = false
g.write(', ')
g.expr(val)
if is_ptr {
g.write('.val')
}
g.write(')')
} else {
g.write(' $op ')
@ -831,6 +841,9 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt) {
g.write('${g.typ(stmt.left_types.first())}(')
}
g.expr(val)
if is_ptr {
g.write('.val')
}
if should_cast {
g.write(')')
g.cast_stack.delete_last()
@ -1302,14 +1315,20 @@ fn (mut g JsGen) gen_array_init_values(exprs []ast.Expr) {
fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
g.call_stack << it
expected_types := it.expected_arg_types
mut name := g.js_name(it.name)
call_return_is_optional := it.return_type.has_flag(.optional)
if it.is_method {
if call_return_is_optional {
g.writeln('(function(){')
g.inc_indent()
g.writeln('try {')
g.inc_indent()
g.write('return builtin.unwrap(')
}
g.expr(it.left)
if it.is_method { // foo.bar.baz()
sym := g.table.get_type_symbol(it.receiver_type)
g.write('.')
if sym.kind == .array && it.name in ['map', 'filter'] {
g.expr(it.left)
g.write('.')
// Prevent 'it' from getting shadowed inside the match
node := it
g.write(it.name)
@ -1342,52 +1361,6 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
g.write(')')
return
}
}
g.writeln('(function() { ')
g.inc_indent()
mut mut_args := map[int]MutArg{}
// store all the mutable arguments in temporary variable + allocate an object which boxes these arguments
for i, arg in it.args {
if arg.is_mut {
tmp_var := g.new_tmp_var()
g.writeln('const $tmp_var = ')
expr := arg.expr
match expr {
ast.Ident {
if expr.var_info().typ.is_ptr() {
g.write(expr.name)
g.writeln(';')
} else {
g.write('{ value: ')
g.expr(expr)
g.writeln(' }; ')
}
}
else {
g.write('{ value: ')
g.expr(expr)
g.writeln(' }; ')
}
}
mut_args[i] = MutArg{tmp_var, arg.expr}
}
}
g.write('let result;')
if call_return_is_optional {
g.writeln('(function(){')
g.inc_indent()
g.writeln('try {')
g.inc_indent()
// g.write('return builtin.unwrap(')
}
g.writeln('result = ')
g.expr(it.left)
if it.is_method { // foo.bar.baz()
g.write('.')
} else {
if name in g.builtin_fns {
g.write('builtin.')
@ -1395,51 +1368,16 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
}
g.write('${name}(')
for i, arg in it.args {
if arg.is_mut {
mut_arg := mut_args[i]
g.write(mut_arg.tmp_var)
} else {
g.expr(arg.expr)
}
// TODO: Is this correct way of passing argument?
if i < expected_types.len && arg.typ.is_ptr() && !arg.is_mut && !expected_types[i].is_ptr() {
g.write('.value')
}
g.expr(arg.expr)
if i != it.args.len - 1 {
g.write(', ')
}
}
// end method call
g.writeln(');')
// now unbox all the mutable arguments
for i, arg in it.args {
if arg.is_mut {
mut_arg := mut_args[i]
expr := mut_arg.expr
match expr {
ast.Ident {
if !expr.var_info().typ.is_ptr() {
g.writeln('$expr.name = ($mut_arg.tmp_var).value;')
}
}
ast.IndexExpr {
g.expr(mut_arg.expr)
g.writeln(' = ($mut_arg.tmp_var).value;')
}
ast.SelectorExpr {
g.expr(mut_arg.expr)
g.writeln(' = ($mut_arg.tmp_var).value;')
}
else {
// TODO
}
}
}
}
g.write(')')
if call_return_is_optional {
// end unwrap
g.writeln('result = builtin.unwrap(result)')
g.writeln(')')
g.dec_indent()
// begin catch block
g.writeln('} catch(err) {')
@ -1450,7 +1388,7 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
if it.or_block.stmts.len > 1 {
g.stmts(it.or_block.stmts[..it.or_block.stmts.len - 1])
}
// g.write('result = ')
g.write('return ')
g.stmt(it.or_block.stmts.last())
}
.propagate {
@ -1468,11 +1406,8 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
g.writeln('}')
// end anon fn
g.dec_indent()
g.writeln('})()')
g.write('})()')
}
g.dec_indent()
g.writeln('return result;')
g.writeln('})()')
g.call_stack.delete_last()
}