Skip to content

Commit 2ad8339

Browse files
authored
all: implement scoped defer (part 1) (#25639)
1 parent 565e6ef commit 2ad8339

27 files changed

+285
-89
lines changed

vlib/v/ast/ast.v

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub struct Block {
221221
pub:
222222
is_unsafe bool
223223
pos token.Pos
224+
scope &Scope
224225
pub mut:
225226
stmts []Stmt
226227
}
@@ -808,6 +809,7 @@ pub struct BranchStmt {
808809
pub:
809810
kind token.Kind
810811
label string
812+
scope &Scope
811813
pos token.Pos
812814
}
813815

@@ -887,6 +889,7 @@ pub mut:
887889
// function return statement
888890
pub struct Return {
889891
pub:
892+
scope &Scope
890893
pos token.Pos
891894
comments []Comment
892895
pub mut:
@@ -1326,6 +1329,7 @@ pub:
13261329
is_else bool
13271330
is_timeout bool
13281331
post_comments []Comment
1332+
scope &Scope
13291333
pub mut:
13301334
stmt Stmt // `a := <-ch` or `ch <- a`
13311335
stmts []Stmt // right side
@@ -1542,13 +1546,20 @@ pub:
15421546
is_markused bool
15431547
}
15441548

1549+
pub enum DeferMode {
1550+
scoped // default
1551+
function
1552+
}
1553+
15451554
// TODO: handle this differently
15461555
// v1 excludes non current os ifdefs so
15471556
// the defer's never get added in the first place
15481557
@[minify]
15491558
pub struct DeferStmt {
15501559
pub:
1551-
pos token.Pos
1560+
pos token.Pos
1561+
scope &Scope
1562+
mode DeferMode
15521563
pub mut:
15531564
stmts []Stmt
15541565
defer_vars []Ident

vlib/v/ast/scope.v

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
// that can be found in the LICENSE file.
44
module ast
55

6+
pub const empty_scope = &Scope{
7+
parent: unsafe { nil }
8+
}
9+
610
@[heap]
711
pub struct Scope {
812
pub mut:
@@ -251,6 +255,11 @@ pub fn (s &Scope) contains(pos int) bool {
251255
return pos >= s.start_pos && pos <= s.end_pos
252256
}
253257

258+
@[inline]
259+
pub fn (s &Scope) == (o &Scope) bool {
260+
return s.start_pos == o.start_pos && s.end_pos == o.end_pos
261+
}
262+
254263
pub fn (s &Scope) has_inherited_vars() bool {
255264
for _, obj in s.objects {
256265
if obj is Var {

vlib/v/checker/fn.v

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
502502
node.stmts.last().pos
503503
}
504504
node.stmts << ast.Return{
505-
pos: return_pos // node.pos
505+
scope: node.scope
506+
pos: return_pos // node.pos
506507
}
507508
}
508509
}
@@ -512,7 +513,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
512513
sym := c.table.sym(node.return_type)
513514
if sym.kind == .void {
514515
node.stmts << ast.Return{
515-
pos: node.pos
516+
scope: node.scope
517+
pos: node.pos
516518
}
517519
}
518520
}

vlib/v/checker/lambda_expr.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as
7070
}
7171
} else {
7272
stmts << ast.Return{
73+
scope: node.scope
7374
pos: node.pos
7475
exprs: [node.expr]
7576
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
vlib/v/checker/tests/invalid_defer_mode_err.vv:4:8: error: unknown `defer` mode: `fn1`
2+
2 | defer {} // ok
3+
3 | defer(fn) {} // ok
4+
4 | defer(fn1) {} // fail
5+
| ~~~
6+
5 | }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
defer {} // ok
3+
defer(fn) {} // ok
4+
defer(fn1) {} // fail
5+
}

vlib/v/fmt/fmt.v

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -981,12 +981,15 @@ pub fn (mut f Fmt) const_decl(node ast.ConstDecl) {
981981
}
982982

983983
fn (mut f Fmt) defer_stmt(node ast.DeferStmt) {
984-
f.write('defer ')
984+
f.write('defer')
985+
if node.mode == .function {
986+
f.write('(fn)')
987+
}
985988
if node.stmts.len == 0 {
986-
f.writeln('{}')
989+
f.writeln(' {}')
987990
} else if node.stmts.len == 1 && node.pos.line_nr == node.pos.last_line
988991
&& stmt_is_single_line(node.stmts[0]) {
989-
f.write('{ ')
992+
f.write(' { ')
990993
// the control stmts (return/break/continue...) print a newline inside them,
991994
// so, since this'll all be on one line, trim any possible whitespace
992995
str := f.node_str(node.stmts[0]).trim_space()
@@ -1000,7 +1003,7 @@ fn (mut f Fmt) defer_stmt(node ast.DeferStmt) {
10001003
// f.stmt(node.stmts[0])
10011004
f.writeln(' }')
10021005
} else {
1003-
f.writeln('{')
1006+
f.writeln(' {')
10041007
f.stmts(node.stmts)
10051008
f.writeln('}')
10061009
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
fn main() {
2+
defer(fn) { println('${@FN} - 0 - defer') }
3+
{
4+
defer { println('${@FN} - 1 - defer') }
5+
{
6+
defer { println('${@FN} - 2 - defer') }
7+
println('exit fn main().scope.2')
8+
}
9+
println('exit fn main().scope.1')
10+
}
11+
12+
defer(fn) {
13+
println('defer(fn)')
14+
}
15+
println('exit fn main().scope.0')
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fn main() {
2+
defer (fn) { println('${@FN} - 0 - defer') }
3+
{
4+
defer { println('${@FN} - 1 - defer') }
5+
{
6+
defer { println('${@FN} - 2 - defer') }
7+
println('exit fn main().scope.2')
8+
}
9+
println('exit fn main().scope.1')
10+
}
11+
defer
12+
(fn)
13+
{
14+
println('defer(fn)')
15+
}
16+
println('exit fn main().scope.0')
17+
}

0 commit comments

Comments
 (0)