1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

defer statement

This commit is contained in:
Alexander Medvednikov 2019-07-15 22:09:34 +02:00
parent d58174e77f
commit 17c6ba04a2
3 changed files with 24 additions and 6 deletions

View File

@ -25,11 +25,11 @@ mut:
typ string // return type typ string // return type
is_c bool is_c bool
receiver_typ string receiver_typ string
is_public bool is_public bool
is_method bool is_method bool
returns_error bool returns_error bool
is_decl bool // type myfn fn(int, int) is_decl bool // type myfn fn(int, int)
defer string defer_text string
} }
fn (f &Fn) find_var(name string) Var { fn (f &Fn) find_var(name string) Var {
@ -380,7 +380,7 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
if p.pref.is_prof && f.name != 'main' && f.name != 'time__ticks' { if p.pref.is_prof && f.name != 'main' && f.name != 'time__ticks' {
p.genln('double _PROF_START = time__ticks();//$f.name') p.genln('double _PROF_START = time__ticks();//$f.name')
cgen_name := p.table.cgen_name(f) cgen_name := p.table.cgen_name(f)
f.defer = ' ${cgen_name}_time += time__ticks() - _PROF_START;' f.defer_text = ' ${cgen_name}_time += time__ticks() - _PROF_START;'
} }
p.statements_no_curly_end() p.statements_no_curly_end()
// Print counting result after all statements in main // Print counting result after all statements in main
@ -388,7 +388,7 @@ pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
p.genln(p.print_prof_counters()) p.genln(p.print_prof_counters())
} }
// Counting or not, always need to add defer before the end // Counting or not, always need to add defer before the end
p.genln(f.defer) p.genln(f.defer_text)
if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' { if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' {
p.error('$f.name must return "$typ"') p.error('$f.name must return "$typ"')
} }

View File

@ -1022,6 +1022,9 @@ fn (p mut Parser) statement(add_semi bool) string {
label := p.check_name() label := p.check_name()
p.genln('goto $label;') p.genln('goto $label;')
return '' return ''
case Token.key_defer:
p.defer_st()
return ''
case Token.hash: case Token.hash:
p.chash() p.chash()
return '' return ''
@ -1038,7 +1041,7 @@ fn (p mut Parser) statement(add_semi bool) string {
case Token.key_return: case Token.key_return:
p.return_st() p.return_st()
case Token.lcbr:// {} block case Token.lcbr:// {} block
p.next() p.check(.lcbr)
p.genln('{') p.genln('{')
p.statements() p.statements()
return '' return ''
@ -3088,7 +3091,7 @@ else {
} }
fn (p mut Parser) return_st() { fn (p mut Parser) return_st() {
p.cgen.insert_before(p.cur_fn.defer) p.cgen.insert_before(p.cur_fn.defer_text)
p.check(.key_return) p.check(.key_return)
fn_returns := p.cur_fn.typ != 'void' fn_returns := p.cur_fn.typ != 'void'
@ -3265,6 +3268,19 @@ fn (p mut Parser) attribute() {
p.error('bad attribute usage') p.error('bad attribute usage')
} }
fn (p mut Parser) defer_st() {
p.check(.key_defer)
// Wrap everything inside the defer block in /**/ comments, and save it in
// `defer_text`. It will be inserted before every `return`.
p.genln('/*')
pos := p.cgen.lines.len
p.check(.lcbr)
p.genln('{')
p.statements()
p.cur_fn.defer_text = p.cgen.lines.right(pos).join('\n')
p.genln('*/')
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -75,6 +75,7 @@ enum Token {
key_const key_const
key_continue key_continue
key_default key_default
key_defer
key_else key_else
key_embed key_embed
key_enum key_enum
@ -213,6 +214,7 @@ fn build_token_str() []string {
s[Token.key_union] = 'union' s[Token.key_union] = 'union'
s[Token.key_static] = 'static' s[Token.key_static] = 'static'
s[Token.key_as] = 'as' s[Token.key_as] = 'as'
s[Token.key_defer] = 'defer'
return s return s
} }