mirror of
https://github.com/vlang/v.git
synced 2025-09-09 07:15:50 -04:00
cgen: remove unused code generated for unwrapping temp var from callexpr (detect unused return value from CallExpr), fix parser bugs (#22769)
This commit is contained in:
parent
505a247706
commit
dab25cad49
@ -1559,6 +1559,7 @@ fn (t Tree) call_expr(node ast.CallExpr) &Node {
|
|||||||
obj.add('is_keep_alive', t.bool_node(node.is_keep_alive))
|
obj.add('is_keep_alive', t.bool_node(node.is_keep_alive))
|
||||||
obj.add_terse('is_noreturn', t.bool_node(node.is_noreturn))
|
obj.add_terse('is_noreturn', t.bool_node(node.is_noreturn))
|
||||||
obj.add_terse('is_ctor_new', t.bool_node(node.is_ctor_new))
|
obj.add_terse('is_ctor_new', t.bool_node(node.is_ctor_new))
|
||||||
|
obj.add_terse('is_return_used', t.bool_node(node.is_return_used))
|
||||||
obj.add('should_be_skipped', t.bool_node(node.should_be_skipped))
|
obj.add('should_be_skipped', t.bool_node(node.should_be_skipped))
|
||||||
obj.add_terse('free_receiver', t.bool_node(node.free_receiver))
|
obj.add_terse('free_receiver', t.bool_node(node.free_receiver))
|
||||||
obj.add('scope', t.number_node(int(node.scope)))
|
obj.add('scope', t.number_node(int(node.scope)))
|
||||||
|
@ -827,6 +827,7 @@ pub mut:
|
|||||||
scope &Scope = unsafe { nil }
|
scope &Scope = unsafe { nil }
|
||||||
from_embed_types []Type // holds the type of the embed that the method is called from
|
from_embed_types []Type // holds the type of the embed that the method is called from
|
||||||
comments []Comment
|
comments []Comment
|
||||||
|
is_return_used bool // return value is used for another expr
|
||||||
//
|
//
|
||||||
is_expand_simple_interpolation bool // true, when the function/method is marked as @[expand_simple_interpolation]
|
is_expand_simple_interpolation bool // true, when the function/method is marked as @[expand_simple_interpolation]
|
||||||
// Calls to it with an interpolation argument like `b.f('x ${y}')`, will be converted to `b.f('x ')` followed by `b.f(y)`.
|
// Calls to it with an interpolation argument like `b.f('x ${y}')`, will be converted to `b.f('x ')` followed by `b.f(y)`.
|
||||||
|
@ -580,13 +580,14 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
|
|||||||
right.pos())
|
right.pos())
|
||||||
c.note('an implicit clone of the slice was done here', right.pos())
|
c.note('an implicit clone of the slice was done here', right.pos())
|
||||||
right = ast.CallExpr{
|
right = ast.CallExpr{
|
||||||
name: 'clone'
|
name: 'clone'
|
||||||
left: right
|
left: right
|
||||||
left_type: left_type
|
left_type: left_type
|
||||||
is_method: true
|
is_method: true
|
||||||
receiver_type: left_type
|
receiver_type: left_type
|
||||||
return_type: left_type
|
return_type: left_type
|
||||||
scope: c.fn_scope
|
scope: c.fn_scope
|
||||||
|
is_return_used: true
|
||||||
}
|
}
|
||||||
right_type = c.expr(mut right)
|
right_type = c.expr(mut right)
|
||||||
node.right[i] = right
|
node.right[i] = right
|
||||||
|
@ -1371,7 +1371,6 @@ fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, expr
|
|||||||
c.expected_type = ret_type
|
c.expected_type = ret_type
|
||||||
c.expected_or_type = ret_type.clear_option_and_result()
|
c.expected_or_type = ret_type.clear_option_and_result()
|
||||||
last_stmt_typ := c.expr(mut stmt.expr)
|
last_stmt_typ := c.expr(mut stmt.expr)
|
||||||
|
|
||||||
if last_stmt_typ.has_flag(.option) || last_stmt_typ == ast.none_type {
|
if last_stmt_typ.has_flag(.option) || last_stmt_typ == ast.none_type {
|
||||||
if stmt.expr in [ast.Ident, ast.SelectorExpr, ast.CallExpr, ast.None, ast.CastExpr] {
|
if stmt.expr in [ast.Ident, ast.SelectorExpr, ast.CallExpr, ast.None, ast.CastExpr] {
|
||||||
expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result())
|
expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result())
|
||||||
|
@ -733,13 +733,14 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
|
|||||||
init_field.expr.pos())
|
init_field.expr.pos())
|
||||||
c.note('an implicit clone of the slice was done here', init_field.expr.pos())
|
c.note('an implicit clone of the slice was done here', init_field.expr.pos())
|
||||||
mut right := ast.CallExpr{
|
mut right := ast.CallExpr{
|
||||||
name: 'clone'
|
name: 'clone'
|
||||||
left: init_field.expr
|
left: init_field.expr
|
||||||
left_type: got_type
|
left_type: got_type
|
||||||
is_method: true
|
is_method: true
|
||||||
receiver_type: got_type.ref()
|
receiver_type: got_type.ref()
|
||||||
return_type: got_type
|
return_type: got_type
|
||||||
scope: c.fn_scope
|
scope: c.fn_scope
|
||||||
|
is_return_used: true
|
||||||
}
|
}
|
||||||
got_type = c.expr(mut right)
|
got_type = c.expr(mut right)
|
||||||
node.init_fields[i].expr = right
|
node.init_fields[i].expr = right
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
@[flag]
|
@[flag]
|
||||||
pub enum Enum {
|
pub enum Enum {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
@[flag]
|
@[flag]
|
||||||
pub enum Enum {
|
pub enum Enum {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1041,7 @@ fn (mut g Gen) gen_cross_var_assign(node &ast.AssignStmt) {
|
|||||||
g.write(' = *(voidptr*)array_get(')
|
g.write(' = *(voidptr*)array_get(')
|
||||||
} else {
|
} else {
|
||||||
styp := g.styp(info.elem_type)
|
styp := g.styp(info.elem_type)
|
||||||
string_clone := if needs_clone { '/*1*/string_clone(' } else { '' }
|
string_clone := if needs_clone { 'string_clone(' } else { '' }
|
||||||
|
|
||||||
g.write('${styp} _var_${left.pos.pos} = ${string_clone}*(${styp}*)array_get(')
|
g.write('${styp} _var_${left.pos.pos} = ${string_clone}*(${styp}*)array_get(')
|
||||||
}
|
}
|
||||||
|
@ -2158,7 +2158,11 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
|||||||
eprintln('cgen: ${g.file.path:-30} | pos: ${node.pos.line_str():-39} | node: ${ntype} | ${node}')
|
eprintln('cgen: ${g.file.path:-30} | pos: ${node.pos.line_str():-39} | node: ${ntype} | ${node}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
old_inside_call := g.inside_call
|
||||||
g.inside_call = false
|
g.inside_call = false
|
||||||
|
defer {
|
||||||
|
g.inside_call = old_inside_call
|
||||||
|
}
|
||||||
if !g.skip_stmt_pos {
|
if !g.skip_stmt_pos {
|
||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
}
|
}
|
||||||
@ -7140,6 +7144,10 @@ fn (mut g Gen) gen_or_block_stmts(cvar_name string, cast_typ string, stmts []ast
|
|||||||
&& expr_stmt.expr.or_block.kind == .absent {
|
&& expr_stmt.expr.or_block.kind == .absent {
|
||||||
g.write('${cvar_name} = ')
|
g.write('${cvar_name} = ')
|
||||||
return_wrapped = true
|
return_wrapped = true
|
||||||
|
} else if expr_stmt.expr is ast.CallExpr {
|
||||||
|
if expr_stmt.expr.is_return_used {
|
||||||
|
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
|
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
|
||||||
}
|
}
|
||||||
|
@ -1021,7 +1021,12 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
|||||||
&& unwrapped_styp.starts_with('_v_') {
|
&& unwrapped_styp.starts_with('_v_') {
|
||||||
unwrapped_styp = unwrapped_styp[3..]
|
unwrapped_styp = unwrapped_styp[3..]
|
||||||
}
|
}
|
||||||
g.write('\n ${cur_line} (*(${unwrapped_styp}*)${tmp_opt}.data)')
|
if node.is_return_used {
|
||||||
|
// return value is used, so we need to write the unwrapped temporary var
|
||||||
|
g.write('\n ${cur_line} (*(${unwrapped_styp}*)${tmp_opt}.data)')
|
||||||
|
} else {
|
||||||
|
g.write('\n ${cur_line}')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.write('\n ${cur_line} ${tmp_opt}')
|
g.write('\n ${cur_line} ${tmp_opt}')
|
||||||
}
|
}
|
||||||
|
@ -631,12 +631,13 @@ pub fn (mut g Gen) call_expr(node ast.CallExpr, expected ast.Type, existing_rvar
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr = ast.CallExpr{
|
expr = ast.CallExpr{
|
||||||
name: 'str'
|
name: 'str'
|
||||||
left: expr
|
left: expr
|
||||||
left_type: typ
|
left_type: typ
|
||||||
receiver_type: typ
|
receiver_type: typ
|
||||||
return_type: ast.string_type
|
return_type: ast.string_type
|
||||||
is_method: true
|
is_method: true
|
||||||
|
is_return_used: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ fn (mut p Parser) assign_stmt() ast.Stmt {
|
|||||||
mut defer_vars := p.defer_vars.clone()
|
mut defer_vars := p.defer_vars.clone()
|
||||||
p.defer_vars = []ast.Ident{}
|
p.defer_vars = []ast.Ident{}
|
||||||
|
|
||||||
exprs := p.expr_list()
|
exprs := p.expr_list(true)
|
||||||
|
|
||||||
if !(p.inside_defer && p.tok.kind == .decl_assign) {
|
if !(p.inside_defer && p.tok.kind == .decl_assign) {
|
||||||
defer_vars << p.defer_vars
|
defer_vars << p.defer_vars
|
||||||
@ -186,7 +186,10 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr) ast.Stmt {
|
|||||||
mut pos := p.tok.pos()
|
mut pos := p.tok.pos()
|
||||||
p.next()
|
p.next()
|
||||||
mut right := []ast.Expr{cap: left.len}
|
mut right := []ast.Expr{cap: left.len}
|
||||||
right = p.expr_list()
|
old_assign_rhs := p.inside_assign_rhs
|
||||||
|
p.inside_assign_rhs = true
|
||||||
|
right = p.expr_list(true)
|
||||||
|
p.inside_assign_rhs = old_assign_rhs
|
||||||
end_comments := p.eat_comments(same_line: true)
|
end_comments := p.eat_comments(same_line: true)
|
||||||
mut has_cross_var := false
|
mut has_cross_var := false
|
||||||
mut is_static := false
|
mut is_static := false
|
||||||
|
@ -15,7 +15,26 @@ fn (mut p Parser) check_expr_level() ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut p Parser) expr_no_value(precedence int) ast.Expr {
|
||||||
|
old_expecting_value := p.expecting_value
|
||||||
|
p.expecting_value = false
|
||||||
|
defer {
|
||||||
|
p.expecting_value = old_expecting_value
|
||||||
|
}
|
||||||
|
return p.check_expr(precedence) or {
|
||||||
|
if token.is_decl(p.tok.kind) && p.disallow_declarations_in_script_mode() {
|
||||||
|
return ast.empty_expr
|
||||||
|
}
|
||||||
|
p.unexpected(prepend_msg: 'invalid expression:')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut p Parser) expr(precedence int) ast.Expr {
|
fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
|
old_expecting_value := p.expecting_value
|
||||||
|
p.expecting_value = true
|
||||||
|
defer {
|
||||||
|
p.expecting_value = old_expecting_value
|
||||||
|
}
|
||||||
return p.check_expr(precedence) or {
|
return p.check_expr(precedence) or {
|
||||||
if token.is_decl(p.tok.kind) && p.disallow_declarations_in_script_mode() {
|
if token.is_decl(p.tok.kind) && p.disallow_declarations_in_script_mode() {
|
||||||
return ast.empty_expr
|
return ast.empty_expr
|
||||||
@ -466,12 +485,13 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
|||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
or_block := p.gen_or_block()
|
or_block := p.gen_or_block()
|
||||||
node = ast.CallExpr{
|
node = ast.CallExpr{
|
||||||
name: 'anon'
|
name: 'anon'
|
||||||
left: node
|
left: node
|
||||||
args: args
|
args: args
|
||||||
pos: pos
|
pos: pos
|
||||||
or_block: or_block
|
or_block: or_block
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
|
is_return_used: p.expecting_value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
@ -572,11 +592,12 @@ fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_ident bo
|
|||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
or_block := p.gen_or_block()
|
or_block := p.gen_or_block()
|
||||||
node = ast.CallExpr{
|
node = ast.CallExpr{
|
||||||
left: node
|
left: node
|
||||||
args: args
|
args: args
|
||||||
pos: pos
|
pos: pos
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
or_block: or_block
|
or_block: or_block
|
||||||
|
is_return_used: p.expecting_value
|
||||||
}
|
}
|
||||||
p.is_stmt_ident = is_stmt_ident
|
p.is_stmt_ident = is_stmt_ident
|
||||||
if p.tok.kind == .lpar && p.prev_tok.line_nr == p.tok.line_nr {
|
if p.tok.kind == .lpar && p.prev_tok.line_nr == p.tok.line_nr {
|
||||||
@ -613,7 +634,10 @@ fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_ident bo
|
|||||||
tok := p.tok
|
tok := p.tok
|
||||||
mut pos := tok.pos()
|
mut pos := tok.pos()
|
||||||
p.next()
|
p.next()
|
||||||
|
old_assign_rhs := p.inside_assign_rhs
|
||||||
|
p.inside_assign_rhs = true
|
||||||
right := p.expr(precedence - 1)
|
right := p.expr(precedence - 1)
|
||||||
|
p.inside_assign_rhs = old_assign_rhs
|
||||||
pos.update_last_line(p.prev_tok.line_nr)
|
pos.update_last_line(p.prev_tok.line_nr)
|
||||||
if mut node is ast.IndexExpr {
|
if mut node is ast.IndexExpr {
|
||||||
node.recursive_arraymap_set_is_setter()
|
node.recursive_arraymap_set_is_setter()
|
||||||
@ -757,7 +781,10 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
right_op_pos := p.tok.pos()
|
right_op_pos := p.tok.pos()
|
||||||
|
old_assign_rhs := p.inside_assign_rhs
|
||||||
|
p.inside_assign_rhs = true
|
||||||
right = p.expr(precedence)
|
right = p.expr(precedence)
|
||||||
|
p.inside_assign_rhs = old_assign_rhs
|
||||||
if op in [.plus, .minus, .mul, .div, .mod, .lt, .eq] && mut right is ast.PrefixExpr {
|
if op in [.plus, .minus, .mul, .div, .mod, .lt, .eq] && mut right is ast.PrefixExpr {
|
||||||
mut right_expr := right.right
|
mut right_expr := right.right
|
||||||
for mut right_expr is ast.ParExpr {
|
for mut right_expr is ast.ParExpr {
|
||||||
|
@ -111,11 +111,12 @@ fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr {
|
|||||||
}
|
}
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
comments: comments
|
comments: comments
|
||||||
|
is_return_used: p.expecting_value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) call_args() []ast.CallArg {
|
fn (mut p Parser) call_args() []ast.CallArg {
|
||||||
prev_inside_call_args := true
|
prev_inside_call_args := p.inside_call_args
|
||||||
p.inside_call_args = true
|
p.inside_call_args = true
|
||||||
defer {
|
defer {
|
||||||
p.inside_call_args = prev_inside_call_args
|
p.inside_call_args = prev_inside_call_args
|
||||||
@ -1168,7 +1169,8 @@ fn (mut p Parser) spawn_expr() ast.SpawnExpr {
|
|||||||
} else {
|
} else {
|
||||||
p.error_with_pos('expression in `spawn` must be a function call', expr.pos())
|
p.error_with_pos('expression in `spawn` must be a function call', expr.pos())
|
||||||
ast.CallExpr{
|
ast.CallExpr{
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
|
is_return_used: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos := spos.extend(p.prev_tok.pos())
|
pos := spos.extend(p.prev_tok.pos())
|
||||||
@ -1189,7 +1191,8 @@ fn (mut p Parser) go_expr() ast.GoExpr {
|
|||||||
} else {
|
} else {
|
||||||
p.error_with_pos('expression in `go` must be a function call', expr.pos())
|
p.error_with_pos('expression in `go` must be a function call', expr.pos())
|
||||||
ast.CallExpr{
|
ast.CallExpr{
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
|
is_return_used: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos := spos.extend(p.prev_tok.pos())
|
pos := spos.extend(p.prev_tok.pos())
|
||||||
|
@ -170,6 +170,13 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
}
|
}
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
stmts := p.parse_block_no_scope(false)
|
stmts := p.parse_block_no_scope(false)
|
||||||
|
// if the last expr is a callexpr mark its return as used
|
||||||
|
if p.inside_assign_rhs && stmts.len > 0 && stmts.last() is ast.ExprStmt {
|
||||||
|
mut last_expr := stmts.last() as ast.ExprStmt
|
||||||
|
if mut last_expr.expr is ast.CallExpr {
|
||||||
|
last_expr.expr.is_return_used = true
|
||||||
|
}
|
||||||
|
}
|
||||||
branches << ast.IfBranch{
|
branches << ast.IfBranch{
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
@ -245,11 +252,12 @@ fn (mut p Parser) is_match_sumtype_type() bool {
|
|||||||
|
|
||||||
fn (mut p Parser) match_expr() ast.MatchExpr {
|
fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
match_first_pos := p.tok.pos()
|
match_first_pos := p.tok.pos()
|
||||||
|
old_inside_match := p.inside_match
|
||||||
p.inside_match = true
|
p.inside_match = true
|
||||||
p.check(.key_match)
|
p.check(.key_match)
|
||||||
mut is_sum_type := false
|
mut is_sum_type := false
|
||||||
cond := p.expr(0)
|
cond := p.expr(0)
|
||||||
p.inside_match = false
|
p.inside_match = old_inside_match
|
||||||
no_lcbr := p.tok.kind != .lcbr
|
no_lcbr := p.tok.kind != .lcbr
|
||||||
if !no_lcbr {
|
if !no_lcbr {
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
@ -353,6 +361,12 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
|||||||
pos := branch_first_pos.extend_with_last_line(branch_last_pos, p.prev_tok.line_nr)
|
pos := branch_first_pos.extend_with_last_line(branch_last_pos, p.prev_tok.line_nr)
|
||||||
branch_pos := branch_first_pos.extend_with_last_line(p.tok.pos(), p.tok.line_nr)
|
branch_pos := branch_first_pos.extend_with_last_line(p.tok.pos(), p.tok.line_nr)
|
||||||
post_comments := p.eat_comments()
|
post_comments := p.eat_comments()
|
||||||
|
if p.inside_assign_rhs && stmts.len > 0 && stmts.last() is ast.ExprStmt {
|
||||||
|
mut last_expr := stmts.last() as ast.ExprStmt
|
||||||
|
if mut last_expr.expr is ast.CallExpr {
|
||||||
|
last_expr.expr.is_return_used = true
|
||||||
|
}
|
||||||
|
}
|
||||||
branches << ast.MatchBranch{
|
branches << ast.MatchBranch{
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
ecmnts: ecmnts
|
ecmnts: ecmnts
|
||||||
@ -430,7 +444,7 @@ fn (mut p Parser) select_expr() ast.SelectExpr {
|
|||||||
}
|
}
|
||||||
p.inside_match = true
|
p.inside_match = true
|
||||||
p.inside_select = true
|
p.inside_select = true
|
||||||
exprs := p.expr_list()
|
exprs := p.expr_list(true)
|
||||||
if exprs.len != 1 {
|
if exprs.len != 1 {
|
||||||
p.error('only one expression allowed as `select` key')
|
p.error('only one expression allowed as `select` key')
|
||||||
return ast.SelectExpr{}
|
return ast.SelectExpr{}
|
||||||
|
@ -54,6 +54,7 @@ mut:
|
|||||||
inside_array_lit bool
|
inside_array_lit bool
|
||||||
inside_in_array bool
|
inside_in_array bool
|
||||||
inside_infix bool
|
inside_infix bool
|
||||||
|
inside_assign_rhs bool // rhs assignment
|
||||||
inside_match bool // to separate `match A { }` from `Struct{}`
|
inside_match bool // to separate `match A { }` from `Struct{}`
|
||||||
inside_select bool // to allow `ch <- Struct{} {` inside `select`
|
inside_select bool // to allow `ch <- Struct{} {` inside `select`
|
||||||
inside_match_case bool // to separate `match_expr { }` from `Struct{}`
|
inside_match_case bool // to separate `match_expr { }` from `Struct{}`
|
||||||
@ -90,6 +91,7 @@ mut:
|
|||||||
returns bool
|
returns bool
|
||||||
is_stmt_ident bool // true while the beginning of a statement is an ident/selector
|
is_stmt_ident bool // true while the beginning of a statement is an ident/selector
|
||||||
expecting_type bool // `is Type`, expecting type
|
expecting_type bool // `is Type`, expecting type
|
||||||
|
expecting_value bool = true // true where a node value will be used
|
||||||
cur_fn_name string
|
cur_fn_name string
|
||||||
cur_fn_scope &ast.Scope = unsafe { nil }
|
cur_fn_scope &ast.Scope = unsafe { nil }
|
||||||
label_names []string
|
label_names []string
|
||||||
@ -1857,10 +1859,10 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) expr_list() []ast.Expr {
|
fn (mut p Parser) expr_list(expect_value bool) []ast.Expr {
|
||||||
mut exprs := []ast.Expr{}
|
mut exprs := []ast.Expr{}
|
||||||
for {
|
for {
|
||||||
expr := p.expr(0)
|
expr := if expect_value { p.expr(0) } else { p.expr_no_value(0) }
|
||||||
if expr !is ast.Comment {
|
if expr !is ast.Comment {
|
||||||
exprs << expr
|
exprs << expr
|
||||||
if p.tok.kind != .comma {
|
if p.tok.kind != .comma {
|
||||||
@ -2228,7 +2230,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
|||||||
mut defer_vars := p.defer_vars.clone()
|
mut defer_vars := p.defer_vars.clone()
|
||||||
p.defer_vars = []ast.Ident{}
|
p.defer_vars = []ast.Ident{}
|
||||||
|
|
||||||
left := p.expr_list()
|
left := p.expr_list(p.inside_assign_rhs)
|
||||||
|
|
||||||
if !(p.inside_defer && p.tok.kind == .decl_assign) {
|
if !(p.inside_defer && p.tok.kind == .decl_assign) {
|
||||||
defer_vars << p.defer_vars
|
defer_vars << p.defer_vars
|
||||||
@ -2881,11 +2883,12 @@ fn (mut p Parser) name_expr() ast.Expr {
|
|||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
or_block := p.gen_or_block()
|
or_block := p.gen_or_block()
|
||||||
node = ast.CallExpr{
|
node = ast.CallExpr{
|
||||||
left: node
|
left: node
|
||||||
args: args
|
args: args
|
||||||
pos: pos
|
pos: pos
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
or_block: or_block
|
or_block: or_block
|
||||||
|
is_return_used: p.expecting_value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3325,6 +3328,10 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||||||
end_pos := p.prev_tok.pos()
|
end_pos := p.prev_tok.pos()
|
||||||
pos := name_pos.extend(end_pos)
|
pos := name_pos.extend(end_pos)
|
||||||
comments := p.eat_comments(same_line: true)
|
comments := p.eat_comments(same_line: true)
|
||||||
|
mut left_node := unsafe { left }
|
||||||
|
if mut left_node is ast.CallExpr {
|
||||||
|
left_node.is_return_used = true
|
||||||
|
}
|
||||||
mcall_expr := ast.CallExpr{
|
mcall_expr := ast.CallExpr{
|
||||||
left: left
|
left: left
|
||||||
name: field_name
|
name: field_name
|
||||||
@ -3337,6 +3344,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||||||
or_block: or_block
|
or_block: or_block
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
comments: comments
|
comments: comments
|
||||||
|
is_return_used: p.expecting_value
|
||||||
}
|
}
|
||||||
return mcall_expr
|
return mcall_expr
|
||||||
}
|
}
|
||||||
@ -3382,7 +3390,10 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||||||
scope: p.scope
|
scope: p.scope
|
||||||
next_token: p.tok.kind
|
next_token: p.tok.kind
|
||||||
}
|
}
|
||||||
|
mut left_node := unsafe { left }
|
||||||
|
if mut left_node is ast.CallExpr {
|
||||||
|
left_node.is_return_used = true
|
||||||
|
}
|
||||||
return sel_expr
|
return sel_expr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3984,7 +3995,10 @@ fn (mut p Parser) return_stmt() ast.Return {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return exprs
|
// return exprs
|
||||||
exprs := p.expr_list()
|
old_assign_rhs := p.inside_assign_rhs
|
||||||
|
p.inside_assign_rhs = true
|
||||||
|
exprs := p.expr_list(true)
|
||||||
|
p.inside_assign_rhs = old_assign_rhs
|
||||||
end_pos := exprs.last().pos()
|
end_pos := exprs.last().pos()
|
||||||
return ast.Return{
|
return ast.Return{
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user