parser,checker,cgen: remove unused err declaration or or { } blocks (#25034)
Some checks failed
Graphics CI / gg-regressions (push) Waiting to run
vlib modules CI / build-module-docs (push) Waiting to run
native backend CI / native-backend-ubuntu (push) Waiting to run
native backend CI / native-backend-windows (push) Waiting to run
Shy and PV CI / v-compiles-puzzle-vibes (push) Waiting to run
Sanitized CI / sanitize-undefined-clang (push) Waiting to run
Sanitized CI / sanitize-undefined-gcc (push) Waiting to run
Sanitized CI / tests-sanitize-address-clang (push) Waiting to run
Sanitized CI / sanitize-address-msvc (push) Waiting to run
Sanitized CI / sanitize-address-gcc (push) Waiting to run
Sanitized CI / sanitize-memory-clang (push) Waiting to run
sdl CI / v-compiles-sdl-examples (push) Waiting to run
Time CI / time-linux (push) Waiting to run
Time CI / time-macos (push) Waiting to run
Time CI / time-windows (push) Waiting to run
toml CI / toml-module-pass-external-test-suites (push) Waiting to run
Tools CI / tools-linux (clang) (push) Waiting to run
Tools CI / tools-linux (gcc) (push) Waiting to run
Tools CI / tools-linux (tcc) (push) Waiting to run
Tools CI / tools-macos (clang) (push) Waiting to run
Tools CI / tools-windows (gcc) (push) Waiting to run
Tools CI / tools-windows (msvc) (push) Waiting to run
Tools CI / tools-windows (tcc) (push) Waiting to run
Tools CI / tools-docker-ubuntu-musl (push) Waiting to run
vab CI / v-compiles-os-android (push) Waiting to run
vab CI / vab-compiles-v-examples (push) Waiting to run
wasm backend CI / wasm-backend (ubuntu-22.04) (push) Waiting to run
wasm backend CI / wasm-backend (windows-2022) (push) Waiting to run
json decoder benchmark CI / json-encode-benchmark (push) Has been cancelled
json encoder benchmark CI / json-encode-benchmark (push) Has been cancelled

This commit is contained in:
Felipe Pena 2025-08-05 04:48:17 -03:00 committed by GitHub
parent c5b6d2a1c6
commit 21d9a5ded5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 108 additions and 37 deletions

View file

@ -1646,6 +1646,7 @@ fn (t Tree) or_expr(node ast.OrExpr) &Node {
obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add_terse('stmts', t.array_node_stmt(node.stmts))
obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('kind', t.enum_node(node.kind))
obj.add('pos', t.pos(node.pos)) obj.add('pos', t.pos(node.pos))
obj.add('scope', t.number_node(int(node.scope)))
return obj return obj
} }

View file

@ -14,6 +14,10 @@ module builtin
// The number for `degree` has been picked through vigor- // The number for `degree` has been picked through vigor-
// ous benchmarking but can be changed to any number > 1. // ous benchmarking but can be changed to any number > 1.
// `degree` determines the maximum length of each node. // `degree` determines the maximum length of each node.
// TODO: the @[markused] tag here is needed as a workaround for
// compilation with `-cc clang -usecache`; added in https://github.com/vlang/v/pull/25034
@[markused]
const degree = 6 const degree = 6
const mid_index = degree - 1 const mid_index = degree - 1
const max_len = 2 * degree - 1 const max_len = 2 * degree - 1

View file

@ -935,6 +935,7 @@ pub mut:
is_tmp bool // for tmp for loop vars, so that autofree can skip them is_tmp bool // for tmp for loop vars, so that autofree can skip them
is_auto_heap bool // value whose address goes out of scope is_auto_heap bool // value whose address goes out of scope
is_stack_obj bool // may be pointer to stack value (`mut` or `&` arg and not @[heap] struct) is_stack_obj bool // may be pointer to stack value (`mut` or `&` arg and not @[heap] struct)
is_special bool // err, it, a, b vars (ignore not useds)
} }
// used for smartcasting only // used for smartcasting only
@ -1912,10 +1913,12 @@ pub enum OrKind {
// `or { ... }` // `or { ... }`
pub struct OrExpr { pub struct OrExpr {
pub: pub:
kind OrKind kind OrKind
pos token.Pos pos token.Pos
scope &Scope = unsafe { nil }
pub mut: pub mut:
stmts []Stmt err_used bool
stmts []Stmt
} }
/* /*

View file

@ -113,6 +113,7 @@ mut:
type_level int // to avoid infinite recursion segfaults due to compiler bugs in ensure_type_exists type_level int // to avoid infinite recursion segfaults due to compiler bugs in ensure_type_exists
ensure_generic_type_level int // to avoid infinite recursion segfaults in ensure_generic_type_specify_type_names ensure_generic_type_level int // to avoid infinite recursion segfaults in ensure_generic_type_specify_type_names
cur_orm_ts ast.TypeSymbol cur_orm_ts ast.TypeSymbol
cur_or_expr &ast.OrExpr = unsafe { nil }
cur_anon_fn &ast.AnonFn = unsafe { nil } cur_anon_fn &ast.AnonFn = unsafe { nil }
vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path** vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path**
loop_labels []string // filled, when inside labelled for loops: `a_label: for x in 0..10 {` loop_labels []string // filled, when inside labelled for loops: `a_label: for x in 0..10 {`
@ -299,7 +300,7 @@ pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) {
for _, obj in sc.objects { for _, obj in sc.objects {
match obj { match obj {
ast.Var { ast.Var {
if !obj.is_used && obj.name[0] != `_` { if !obj.is_special && !obj.is_used && obj.name[0] != `_` {
if !c.pref.translated && !c.file.is_translated { if !c.pref.translated && !c.file.is_translated {
if obj.is_arg { if obj.is_arg {
if c.pref.show_unused_params { if c.pref.show_unused_params {
@ -310,11 +311,11 @@ pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) {
} }
} }
} }
if obj.is_mut && !obj.is_changed && !c.is_builtin_mod && obj.name != 'it' { // if obj.is_mut && !obj.is_changed && !c.is_builtin_mod && obj.name != 'it' {
// if obj.is_mut && !obj.is_changed && !c.is_builtin { //TODO C error bad field not checked // if obj.is_mut && !obj.is_changed && !c.is_builtin { //TODO C error bad field not checked
// c.warn('`$obj.name` is declared as mutable, but it was never changed', // c.warn('`$obj.name` is declared as mutable, but it was never changed',
// obj.pos) // obj.pos)
} // }
} }
else {} else {}
} }
@ -1338,7 +1339,10 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast.
} }
} }
} else { } else {
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &expr.or_block
c.check_or_expr(expr.or_block, ret_type, expr_ret_type, expr) c.check_or_expr(expr.or_block, ret_type, expr_ret_type, expr)
c.cur_or_expr = last_cur_or_expr
} }
return ret_type.clear_flag(.result) return ret_type.clear_flag(.result)
} else { } else {
@ -1365,7 +1369,10 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast.
} }
} else { } else {
if expr.or_block.kind != .absent { if expr.or_block.kind != .absent {
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &expr.or_block
c.check_or_expr(expr.or_block, ret_type, expr.typ, expr) c.check_or_expr(expr.or_block, ret_type, expr.typ, expr)
c.cur_or_expr = last_cur_or_expr
} }
} }
return ret_type.clear_flag(.result) return ret_type.clear_flag(.result)
@ -1389,8 +1396,11 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast.
if return_none_or_error { if return_none_or_error {
c.check_expr_option_or_result_call(expr.or_expr, c.table.cur_fn.return_type) c.check_expr_option_or_result_call(expr.or_expr, c.table.cur_fn.return_type)
} else { } else {
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &expr.or_expr
c.check_or_expr(expr.or_expr, ret_type, ret_type.set_flag(.result), c.check_or_expr(expr.or_expr, ret_type, ret_type.set_flag(.result),
expr) expr)
c.cur_or_expr = last_cur_or_expr
} }
} else if expr.left is ast.SelectorExpr && expr.left_type.has_option_or_result() { } else if expr.left is ast.SelectorExpr && expr.left_type.has_option_or_result() {
with_modifier_kind := if expr.left_type.has_flag(.option) { with_modifier_kind := if expr.left_type.has_flag(.option) {
@ -1464,6 +1474,10 @@ fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_return
} }
// allow `f() or {}` // allow `f() or {}`
return return
} else if !node.err_used {
if err_var := node.scope.find_var('err') {
c.cur_or_expr.err_used = err_var.is_used
}
} }
mut valid_stmts := node.stmts.filter(it !is ast.SemicolonStmt) mut valid_stmts := node.stmts.filter(it !is ast.SemicolonStmt)
mut last_stmt := if valid_stmts.len > 0 { valid_stmts.last() } else { node.stmts.last() } mut last_stmt := if valid_stmts.len > 0 { valid_stmts.last() } else { node.stmts.last() }
@ -1809,7 +1823,10 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
unwrapped_typ := c.unwrap_generic(node.typ) unwrapped_typ := c.unwrap_generic(node.typ)
c.expected_or_type = unwrapped_typ.clear_option_and_result() c.expected_or_type = unwrapped_typ.clear_option_and_result()
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type) c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_block
c.check_or_expr(node.or_block, unwrapped_typ, c.expected_or_type, node) c.check_or_expr(node.or_block, unwrapped_typ, c.expected_or_type, node)
c.cur_or_expr = last_cur_or_expr
c.expected_or_type = ast.void_type c.expected_or_type = ast.void_type
} }
return field.typ return field.typ
@ -4079,7 +4096,10 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
unwrapped_typ := typ.clear_option_and_result() unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type) c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_expr
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node) c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
c.cur_or_expr = last_cur_or_expr
return unwrapped_typ return unwrapped_typ
} }
return typ return typ
@ -4194,7 +4214,10 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
unwrapped_typ := typ.clear_option_and_result() unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type) c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_expr
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node) c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
c.cur_or_expr = last_cur_or_expr
return unwrapped_typ return unwrapped_typ
} }
return typ return typ
@ -4256,7 +4279,10 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
unwrapped_typ := typ.clear_option_and_result() unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type) c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_expr
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node) c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
c.cur_or_expr = last_cur_or_expr
} }
return typ return typ
} }

View file

@ -783,7 +783,10 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
if node.or_block.kind == .block { if node.or_block.kind == .block {
old_inside_or_block_value := c.inside_or_block_value old_inside_or_block_value := c.inside_or_block_value
c.inside_or_block_value = true c.inside_or_block_value = true
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_block
c.check_or_expr(node.or_block, typ, c.expected_or_type, node) c.check_or_expr(node.or_block, typ, c.expected_or_type, node)
c.cur_or_expr = last_cur_or_expr
c.inside_or_block_value = old_inside_or_block_value c.inside_or_block_value = old_inside_or_block_value
} }
c.expected_or_type = old_expected_or_type c.expected_or_type = old_expected_or_type
@ -3819,10 +3822,11 @@ fn scope_register_a_b(mut s ast.Scope, pos token.Pos, typ ast.Type) {
fn scope_register_var_name(mut s ast.Scope, pos token.Pos, typ ast.Type, name string) { fn scope_register_var_name(mut s ast.Scope, pos token.Pos, typ ast.Type, name string) {
s.register(ast.Var{ s.register(ast.Var{
name: name name: name
pos: pos pos: pos
typ: typ typ: typ
is_used: true is_used: false
is_special: true
}) })
} }

View file

@ -192,8 +192,10 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
if node.is_insert { if node.is_insert {
node.typ = ast.int_type node.typ = ast.int_type
} }
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_expr
c.check_orm_or_expr(mut node) c.check_orm_or_expr(mut node)
c.cur_or_expr = last_cur_or_expr
if node.is_insert { if node.is_insert {
return ast.int_type return ast.int_type
@ -211,8 +213,10 @@ fn (mut c Checker) sql_stmt(mut node ast.SqlStmt) ast.Type {
for mut line in node.lines { for mut line in node.lines {
c.sql_stmt_line(mut line) c.sql_stmt_line(mut line)
} }
last_cur_or_expr := c.cur_or_expr
c.cur_or_expr = &node.or_expr
c.check_orm_or_expr(mut node) c.check_orm_or_expr(mut node)
c.cur_or_expr = last_cur_or_expr
return ast.void_type return ast.void_type
} }
@ -605,7 +609,6 @@ fn (mut c Checker) check_orm_or_expr(mut expr ORMExpr) {
return return
} }
} }
return_type := if mut expr is ast.SqlExpr { return_type := if mut expr is ast.SqlExpr {
expr.typ expr.typ
} else { } else {

View file

@ -7177,7 +7177,10 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty
} }
if or_block.kind == .block { if or_block.kind == .block {
g.or_expr_return_type = return_type.clear_option_and_result() g.or_expr_return_type = return_type.clear_option_and_result()
g.writeln('\tIError err = ${cvar_name}${tmp_op}err;') if !g.pref.skip_unused || or_block.err_used
|| (g.fn_decl != unsafe { nil } && (g.fn_decl.is_main || g.fn_decl.is_test)) {
g.writeln('\tIError err = ${cvar_name}${tmp_op}err;')
}
g.inside_or_block = true g.inside_or_block = true
defer { defer {

View file

@ -310,8 +310,12 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
g.writeln('{') g.writeln('{')
// define `err` for the last branch after a `if val := opt {...}' guard // define `err` for the last branch after a `if val := opt {...}' guard
if is_guard && guard_idx == i - 1 { if is_guard && guard_idx == i - 1 {
cvar_name := guard_vars[guard_idx] if err_var := branch.scope.find_var('err') {
g.writeln('\tIError err = ${cvar_name}.err;') if !g.pref.skip_unused || err_var.is_used {
cvar_name := guard_vars[guard_idx]
g.writeln('\tIError err = ${cvar_name}.err;')
}
}
} }
} else if branch.cond is ast.IfGuardExpr { } else if branch.cond is ast.IfGuardExpr {
mut var_name := guard_vars[i] mut var_name := guard_vars[i]

View file

@ -1124,7 +1124,7 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, re
field_var := '${tmp}.${c_name(field.name)}' field_var := '${tmp}.${c_name(field.name)}'
field_c_typ := g.styp(final_field_typ) field_c_typ := g.styp(final_field_typ)
if sym.kind == .struct && sym.name != 'time.Time' { if sym.kind == .struct && sym.name != 'time.Time' {
mut sub := node.sub_structs[int(final_field_typ)] mut sub := node.sub_structs[int(final_field_typ)] or { continue }
mut where_expr := sub.where_expr as ast.InfixExpr mut where_expr := sub.where_expr as ast.InfixExpr
mut ident := where_expr.right as ast.Ident mut ident := where_expr.right as ast.Ident
primitive_type_index := g.table.find_type('orm.Primitive') primitive_type_index := g.table.find_type('orm.Primitive')
@ -1161,7 +1161,7 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, re
} else { } else {
verror('missing fkey attribute') verror('missing fkey attribute')
} }
sub := node.sub_structs[final_field_typ] sub := node.sub_structs[final_field_typ] or { continue }
if sub.has_where { if sub.has_where {
mut where_expr := sub.where_expr as ast.InfixExpr mut where_expr := sub.where_expr as ast.InfixExpr
mut left_where_expr := where_expr.left as ast.Ident mut left_where_expr := where_expr.left as ast.Ident

View file

@ -536,10 +536,11 @@ fn (mut p Parser) comptime_selector(left ast.Expr) ast.Expr {
mut or_kind := ast.OrKind.absent mut or_kind := ast.OrKind.absent
mut or_pos := p.tok.pos() mut or_pos := p.tok.pos()
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}
mut or_scope := &ast.Scope(unsafe { nil })
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
// `$method() or {}`` // `$method() or {}``
or_kind = .block or_kind = .block
or_stmts, or_pos = p.or_block(.with_err_var) or_stmts, or_pos, or_scope = p.or_block(.with_err_var)
} }
return ast.ComptimeCall{ return ast.ComptimeCall{
left: left left: left
@ -554,6 +555,7 @@ fn (mut p Parser) comptime_selector(left ast.Expr) ast.Expr {
stmts: or_stmts stmts: or_stmts
kind: or_kind kind: or_kind
pos: or_pos pos: or_pos
scope: or_scope
} }
} }
} }

View file

@ -727,11 +727,12 @@ fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_ident bo
fn (mut p Parser) gen_or_block() ast.OrExpr { fn (mut p Parser) gen_or_block() ast.OrExpr {
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
// `foo() or {}`` // `foo() or {}``
or_stmts, or_pos := p.or_block(.with_err_var) or_stmts, or_pos, or_scope := p.or_block(.with_err_var)
return ast.OrExpr{ return ast.OrExpr{
kind: ast.OrKind.block kind: ast.OrKind.block
stmts: or_stmts stmts: or_stmts
pos: or_pos pos: or_pos
scope: or_scope
} }
} else if p.tok.kind in [.question, .not] { } else if p.tok.kind in [.question, .not] {
or_pos := p.tok.pos() or_pos := p.tok.pos()
@ -820,11 +821,12 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}
mut or_kind := ast.OrKind.absent mut or_kind := ast.OrKind.absent
mut or_pos := p.tok.pos() mut or_pos := p.tok.pos()
mut or_scope := &ast.Scope(unsafe { nil })
// allow `x := <-ch or {...}` to handle closed channel // allow `x := <-ch or {...}` to handle closed channel
if op == .arrow { if op == .arrow {
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
or_kind = .block or_kind = .block
or_stmts, or_pos = p.or_block(.with_err_var) or_stmts, or_pos, or_scope = p.or_block(.with_err_var)
} }
if p.tok.kind == .question { if p.tok.kind == .question {
p.next() p.next()
@ -845,6 +847,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
stmts: or_stmts stmts: or_stmts
kind: or_kind kind: or_kind
pos: or_pos pos: or_pos
scope: or_scope
} }
} }
} }
@ -911,6 +914,7 @@ fn (mut p Parser) prefix_expr() ast.Expr {
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}
mut or_kind := ast.OrKind.absent mut or_kind := ast.OrKind.absent
mut or_pos := p.tok.pos() mut or_pos := p.tok.pos()
mut or_scope := &ast.Scope(unsafe { nil })
// allow `x := <-ch or {...}` to handle closed channel // allow `x := <-ch or {...}` to handle closed channel
if op == .arrow { if op == .arrow {
if mut right is ast.SelectorExpr { if mut right is ast.SelectorExpr {
@ -919,7 +923,7 @@ fn (mut p Parser) prefix_expr() ast.Expr {
right.or_block = ast.OrExpr{} right.or_block = ast.OrExpr{}
} else if p.tok.kind == .key_orelse { } else if p.tok.kind == .key_orelse {
or_kind = .block or_kind = .block
or_stmts, or_pos = p.or_block(.with_err_var) or_stmts, or_pos, or_scope = p.or_block(.with_err_var)
} else if p.tok.kind == .question { } else if p.tok.kind == .question {
p.next() p.next()
or_kind = .propagate_option or_kind = .propagate_option
@ -935,6 +939,7 @@ fn (mut p Parser) prefix_expr() ast.Expr {
stmts: or_stmts stmts: or_stmts
kind: or_kind kind: or_kind
pos: or_pos pos: or_pos
scope: or_scope
} }
} }
} }

View file

@ -74,10 +74,11 @@ fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr {
mut pos := first_pos.extend(last_pos) mut pos := first_pos.extend(last_pos)
mut or_stmts := []ast.Stmt{} // TODO: remove unnecessary allocations by just using .absent mut or_stmts := []ast.Stmt{} // TODO: remove unnecessary allocations by just using .absent
mut or_pos := p.tok.pos() mut or_pos := p.tok.pos()
mut or_scope := &ast.Scope(unsafe { nil })
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
// `foo() or {}`` // `foo() or {}``
or_kind = .block or_kind = .block
or_stmts, or_pos = p.or_block(.with_err_var) or_stmts, or_pos, or_scope = p.or_block(.with_err_var)
} }
if p.tok.kind in [.question, .not] { if p.tok.kind in [.question, .not] {
is_not := p.tok.kind == .not is_not := p.tok.kind == .not
@ -108,6 +109,7 @@ fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr {
stmts: or_stmts stmts: or_stmts
kind: or_kind kind: or_kind
pos: or_pos pos: or_pos
scope: or_scope
} }
scope: p.scope scope: p.scope
comments: comments comments: comments

View file

@ -53,8 +53,9 @@ fn (mut p Parser) if_expr(is_comptime bool, is_expr bool) ast.IfExpr {
name: 'err' name: 'err'
typ: ast.error_type typ: ast.error_type
pos: p.tok.pos() pos: p.tok.pos()
is_used: true is_used: false
is_stack_obj: true is_stack_obj: true
is_special: true
}) })
} }
branches << ast.IfBranch{ branches << ast.IfBranch{

View file

@ -185,10 +185,11 @@ fn (mut p Parser) parse_sql_or_block() ast.OrExpr {
mut stmts := []ast.Stmt{} mut stmts := []ast.Stmt{}
mut kind := ast.OrKind.absent mut kind := ast.OrKind.absent
mut pos := p.tok.pos() mut pos := p.tok.pos()
mut or_scope := &ast.Scope(unsafe { nil })
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
kind = .block kind = .block
stmts, pos = p.or_block(.with_err_var) stmts, pos, or_scope = p.or_block(.with_err_var)
} else if p.tok.kind == .not { } else if p.tok.kind == .not {
kind = .propagate_result kind = .propagate_result
p.next() p.next()
@ -198,6 +199,7 @@ fn (mut p Parser) parse_sql_or_block() ast.OrExpr {
stmts: stmts stmts: stmts
kind: kind kind: kind
pos: pos pos: pos
scope: or_scope
} }
} }

View file

@ -1232,13 +1232,14 @@ fn (mut p Parser) ident(language ast.Language) ast.Ident {
mut or_kind := ast.OrKind.absent mut or_kind := ast.OrKind.absent
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}
mut or_pos := token.Pos{} mut or_pos := token.Pos{}
mut or_scope := &ast.Scope(unsafe { nil })
if allowed_cases && p.tok.kind == .question && p.peek_tok.kind != .lpar { // var?, not var?( if allowed_cases && p.tok.kind == .question && p.peek_tok.kind != .lpar { // var?, not var?(
or_kind = ast.OrKind.propagate_option or_kind = ast.OrKind.propagate_option
p.check(.question) p.check(.question)
} else if allowed_cases && p.tok.kind == .key_orelse { } else if allowed_cases && p.tok.kind == .key_orelse {
or_kind = ast.OrKind.block or_kind = ast.OrKind.block
or_stmts, or_pos = p.or_block(.no_err_var) or_stmts, or_pos, or_scope = p.or_block(.no_err_var)
} else if is_following_concrete_types { } else if is_following_concrete_types {
// `generic_fn[int]` // `generic_fn[int]`
concrete_types = p.parse_concrete_types() concrete_types = p.parse_concrete_types()
@ -1281,6 +1282,7 @@ fn (mut p Parser) ident(language ast.Language) ast.Ident {
kind: or_kind kind: or_kind
stmts: or_stmts stmts: or_stmts
pos: or_pos pos: or_pos
scope: or_scope
} }
concrete_types: concrete_types concrete_types: concrete_types
} }
@ -1752,7 +1754,7 @@ enum OrBlockErrVarMode {
with_err_var with_err_var
} }
fn (mut p Parser) or_block(err_var_mode OrBlockErrVarMode) ([]ast.Stmt, token.Pos) { fn (mut p Parser) or_block(err_var_mode OrBlockErrVarMode) ([]ast.Stmt, token.Pos, &ast.Scope) {
was_inside_or_expr := p.inside_or_expr was_inside_or_expr := p.inside_or_expr
defer { defer {
p.inside_or_expr = was_inside_or_expr p.inside_or_expr = was_inside_or_expr
@ -1762,6 +1764,7 @@ fn (mut p Parser) or_block(err_var_mode OrBlockErrVarMode) ([]ast.Stmt, token.Po
mut pos := p.tok.pos() mut pos := p.tok.pos()
p.next() p.next()
p.open_scope() p.open_scope()
or_scope := p.scope
defer { defer {
p.close_scope() p.close_scope()
} }
@ -1771,14 +1774,15 @@ fn (mut p Parser) or_block(err_var_mode OrBlockErrVarMode) ([]ast.Stmt, token.Po
name: 'err' name: 'err'
typ: ast.error_type typ: ast.error_type
pos: p.tok.pos() pos: p.tok.pos()
is_used: true is_used: false
is_stack_obj: true is_stack_obj: true
is_special: true
}) })
} }
stmts := p.parse_block_no_scope(false) stmts := p.parse_block_no_scope(false)
pos = pos.extend(p.prev_tok.pos()) pos = pos.extend(p.prev_tok.pos())
return stmts, pos return stmts, pos, or_scope
} }
fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr { fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
@ -1802,11 +1806,12 @@ fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
mut or_kind_high := ast.OrKind.absent mut or_kind_high := ast.OrKind.absent
mut or_stmts_high := []ast.Stmt{} mut or_stmts_high := []ast.Stmt{}
mut or_pos_high := token.Pos{} mut or_pos_high := token.Pos{}
mut or_scope := &ast.Scope(unsafe { nil })
if !p.or_is_handled { if !p.or_is_handled {
// a[..end] or {...} // a[..end] or {...}
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
or_stmts_high, or_pos_high = p.or_block(.no_err_var) or_stmts_high, or_pos_high, or_scope = p.or_block(.no_err_var)
return ast.IndexExpr{ return ast.IndexExpr{
left: left left: left
pos: pos_high pos: pos_high
@ -1821,6 +1826,7 @@ fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
kind: .block kind: .block
stmts: or_stmts_high stmts: or_stmts_high
pos: or_pos_high pos: or_pos_high
scope: or_scope
} }
is_gated: is_gated is_gated: is_gated
} }
@ -1870,11 +1876,11 @@ fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
mut or_kind_low := ast.OrKind.absent mut or_kind_low := ast.OrKind.absent
mut or_stmts_low := []ast.Stmt{} mut or_stmts_low := []ast.Stmt{}
mut or_pos_low := token.Pos{} mut or_pos_low := token.Pos{}
mut or_scope := &ast.Scope(unsafe { nil })
if !p.or_is_handled { if !p.or_is_handled {
// a[start..end] or {...} // a[start..end] or {...}
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
or_stmts_low, or_pos_low = p.or_block(.no_err_var) or_stmts_low, or_pos_low, or_scope = p.or_block(.no_err_var)
return ast.IndexExpr{ return ast.IndexExpr{
left: left left: left
pos: pos_low pos: pos_low
@ -1890,6 +1896,7 @@ fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
kind: .block kind: .block
stmts: or_stmts_low stmts: or_stmts_low
pos: or_pos_low pos: or_pos_low
scope: or_scope
} }
is_gated: is_gated is_gated: is_gated
} }
@ -1930,10 +1937,11 @@ fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
mut or_kind := ast.OrKind.absent mut or_kind := ast.OrKind.absent
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}
mut or_pos := token.Pos{} mut or_pos := token.Pos{}
mut or_scope := &ast.Scope(unsafe { nil })
if !p.or_is_handled { if !p.or_is_handled {
// a[i] or { ... } // a[i] or { ... }
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
or_stmts, or_pos = p.or_block(.no_err_var) or_stmts, or_pos, or_scope = p.or_block(.no_err_var)
return ast.IndexExpr{ return ast.IndexExpr{
left: left left: left
index: expr index: expr
@ -1942,6 +1950,7 @@ fn (mut p Parser) index_expr(left ast.Expr, is_gated bool) ast.IndexExpr {
kind: .block kind: .block
stmts: or_stmts stmts: or_stmts
pos: or_pos pos: or_pos
scope: or_scope
} }
is_gated: is_gated is_gated: is_gated
} }
@ -2079,9 +2088,10 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
mut or_kind := ast.OrKind.absent mut or_kind := ast.OrKind.absent
mut or_stmts := []ast.Stmt{} mut or_stmts := []ast.Stmt{}
mut or_pos := token.Pos{} mut or_pos := token.Pos{}
mut or_scope := &ast.Scope(unsafe { nil })
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
or_kind = .block or_kind = .block
or_stmts, or_pos = p.or_block(.with_err_var) or_stmts, or_pos, or_scope = p.or_block(.with_err_var)
} else if p.tok.kind == .not { } else if p.tok.kind == .not {
or_kind = .propagate_result or_kind = .propagate_result
or_pos = p.tok.pos() or_pos = p.tok.pos()
@ -2101,6 +2111,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
kind: or_kind kind: or_kind
stmts: or_stmts stmts: or_stmts
pos: or_pos pos: or_pos
scope: or_scope
} }
scope: p.scope scope: p.scope
next_token: p.tok.kind next_token: p.tok.kind