From 802ff1d012b004953b977d560003216853971585 Mon Sep 17 00:00:00 2001 From: Emily Hudson Date: Wed, 7 Aug 2019 15:51:21 +0000 Subject: [PATCH] compiler: scoped defer + build tests with msvc --- compiler/fn.v | 12 ++++++++--- compiler/parser.v | 40 +++++++++++++++++++++++++++++-------- make_tests.bat | 9 +++++++-- vlib/crypto/rand/rand_win.v | 3 ++- vlib/math/stats_test.v | 2 +- 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/compiler/fn.v b/compiler/fn.v index df1702cb02..47904a0d32 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -29,7 +29,7 @@ mut: is_method bool returns_error bool is_decl bool // type myfn fn(int, int) - defer_text string + defer_text []string //gen_types []string } @@ -44,9 +44,15 @@ fn (f &Fn) find_var(name string) Var { fn (f mut Fn) open_scope() { + f.defer_text << '' f.scope_level++ } +fn (f mut Fn) close_scope() { + f.scope_level-- + f.defer_text = f.defer_text.left(f.scope_level + 1) +} + fn (f &Fn) mark_var_used(v Var) { for i, vv in f.local_vars { if vv.name == v.name { @@ -442,7 +448,7 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0); if p.pref.is_prof && f.name != 'main' && f.name != 'time__ticks' { p.genln('double _PROF_START = time__ticks();//$f.name') cgen_name := p.table.cgen_name(f) - f.defer_text = ' ${cgen_name}_time += time__ticks() - _PROF_START;' + f.defer_text[f.scope_level] = ' ${cgen_name}_time += time__ticks() - _PROF_START;' } if is_generic { // Don't need to generate body for the actual generic definition @@ -455,7 +461,7 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0); p.genln(p.print_prof_counters()) } // Counting or not, always need to add defer before the end - p.genln(f.defer_text) + p.genln(f.defer_text[f.scope_level]) if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' { p.error('$f.name must return "$typ"') } diff --git a/compiler/parser.v b/compiler/parser.v index 211c6d63fe..1e4eae52b0 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -1069,13 +1069,18 @@ fn (p mut Parser) close_scope() { else if v.ptr { //p.genln('free($v.name); // close_scope free') } - } - + } } + + if p.cur_fn.defer_text.last() != '' { + p.genln(p.cur_fn.defer_text.last()) + //p.cur_fn.defer_text[f] = '' + } + + p.cur_fn.close_scope() p.cur_fn.var_idx = i + 1 // println('close_scope new var_idx=$f.var_idx\n') - p.cur_fn.scope_level-- -} +} fn (p mut Parser) genln(s string) { p.cgen.genln(s) @@ -3237,13 +3242,27 @@ fn (p mut Parser) return_st() { } else { ret := p.cgen.cur_line.right(ph) - p.cgen(p.cur_fn.defer_text) - if p.cur_fn.defer_text == '' || expr_type == 'void*' { + + // @emily33901: Scoped defer + // Check all of our defer texts to see if there is one at a higher scope level + // The one for our current scope would be the last so any before that need to be + // added. + + mut total_text := '' + + for text in p.cur_fn.defer_text { + if text != '' { + // In reverse order + total_text = text + total_text + } + } + + if total_text == '' || expr_type == 'void*' { p.cgen.resetln('return $ret') } else { tmp := p.get_tmp() p.cgen.resetln('$expr_type $tmp = $ret;\n') - p.genln(p.cur_fn.defer_text) + p.genln(total_text) p.genln('return $tmp;') } } @@ -3397,9 +3416,14 @@ fn (p mut Parser) defer_st() { // Save everything inside the defer block to `defer_text`. // It will be inserted before every `return` + + // Emily: TODO: all variables that are used in this defer statement need to be evaluated when the block + // is defined otherwise they could change over the course of the function + // (make temps out of them) + p.genln('{') p.statements() - p.cur_fn.defer_text = p.cgen.lines.right(pos).join('\n') + p.cur_fn.defer_text + p.cur_fn.defer_text.last() = p.cgen.lines.right(pos).join('\n') + p.cur_fn.defer_text.last() // Rollback p.cgen.lines p.cgen.lines = p.cgen.lines.left(pos) diff --git a/make_tests.bat b/make_tests.bat index 5ce60c9816..e79ec2ecb6 100644 --- a/make_tests.bat +++ b/make_tests.bat @@ -1,11 +1,14 @@ @echo off + curl -O https://raw.githubusercontent.com/vlang/vc/master/v.c gcc -std=gnu11 -DUNICODE -D_UNICODE -w -o vc.exe v.c del v.c + vc.exe -o v.exe compiler v.exe -os msvc -o v.msvc.exe compiler v.msvc.exe -os msvc -o v.msvc.2.exe compiler v.msvc.exe -o v.gcc.exe compiler + setlocal EnableDelayedExpansion for /r . %%x in (*_test.v) do ( v -o test.exe -debug %%x @@ -15,14 +18,16 @@ for /r . %%x in (*_test.v) do ( v.msvc.exe -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail ) + for /r . %%x in (*_test.v) do ( - v.msvc.2.exe -o test.exe -debug %%x + v -os msvc -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail ) for /r . %%x in (*_test.v) do ( - v.gcc.exe -o test.exe -debug %%x + v.msvc.exe -os msvc -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail ) + goto :done :fail diff --git a/vlib/crypto/rand/rand_win.v b/vlib/crypto/rand/rand_win.v index 200b98ffb7..973c649d2a 100644 --- a/vlib/crypto/rand/rand_win.v +++ b/vlib/crypto/rand/rand_win.v @@ -4,7 +4,8 @@ module rand -#flag windows -Llibraries/bcrypt -lbcrypt +#flag windows -Llibraries/bcrypt +#flag windows -lbcrypt #include const ( diff --git a/vlib/math/stats_test.v b/vlib/math/stats_test.v index 368930a54f..6379fe0693 100644 --- a/vlib/math/stats_test.v +++ b/vlib/math/stats_test.v @@ -37,7 +37,7 @@ fn test_geometric_mean() { o = stats.geometric_mean(data) println(o) // Some issue with precision comparison in f64 using == operator hence serializing to string - assert o.str().eq('nan') || o.str().eq('-nan') || o.str().eq('-1.#IND00') || o == f64(0) // Because in math it yields a complex number + assert o.str().eq('nan') || o.str().eq('-nan') || o.str().eq('-1.#IND00') || o == f64(0) || o.str().eq('-nan(ind)') // Because in math it yields a complex number data = [f64(12.0),f64(7.88),f64(76.122),f64(54.83)] o = stats.geometric_mean(data) // Some issue with precision comparison in f64 using == operator hence serializing to string