diff --git a/compiler/cgen.v b/compiler/cgen.v index 708a0c9ea3..3395b21903 100644 --- a/compiler/cgen.v +++ b/compiler/cgen.v @@ -263,7 +263,6 @@ fn build_thirdparty_obj_file(flag string) { cc := if os.user_os() == 'windows' { 'gcc' } else { 'cc' } // TODO clang support on Windows res := os.exec('$cc -fPIC -c -o $obj_path $cfiles') or { panic(err) - return // TODO remove return } println(res) } diff --git a/compiler/comptime.v b/compiler/comptime.v index fc226f2c3d..28d10ae618 100644 --- a/compiler/comptime.v +++ b/compiler/comptime.v @@ -39,6 +39,20 @@ fn (p mut Parser) comp_time() { println(SupportedPlatforms) p.error('unknown platform `$name`') } + if_returns := p.returns + p.returns = false + p.gen('/* returns $p.returns */') + if p.tok == .dollar && p.peek() == .key_else { + p.next() + p.next() + p.check(.lcbr) + p.genln('#else') + p.statements_no_rcbr() + p.genln('#endif') + else_returns := p.returns + p.returns = if_returns && else_returns + p.gen('/* returns $p.returns */') + } } else if p.tok == .key_for { p.next() @@ -65,13 +79,6 @@ fn (p mut Parser) comp_time() { p.check(.rcbr) // } } - else if p.tok == .key_else { - p.next() - p.check(.lcbr) - p.genln('#else') - p.statements_no_rcbr() - p.genln('#endif') - } // $vweb.html() // Compile vweb html template to V code, parse that V code and embed the resulting V functions // that returns an html string diff --git a/compiler/fn.v b/compiler/fn.v index 8e88105627..0930b16920 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -124,6 +124,7 @@ fn (p mut Parser) fn_decl() { p.next() } p.returns = false + p.gen('/* returns $p.returns */') p.next() mut f := new_fn(p.mod, is_pub) // Method receiver diff --git a/compiler/main.v b/compiler/main.v index 54a24a85c7..60d7fd6e59 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -139,14 +139,12 @@ fn main() { vexec := os.args[0] _ := os.exec('$vexec vget.v') or { panic(err) - return // TODO remove return } //println('Done.') } println('Installing module ${mod}...') _ := os.exec('$vget $mod') or { panic(err) - return // TODO remove return } return } @@ -891,7 +889,6 @@ mut args := '' } panic('C error. This should never happen. ' + 'Please create a GitHub issue: https://github.com/vlang/v/issues/new/choose') - return // TODO remove return } diff := time.ticks() - ticks // Print the C command @@ -914,7 +911,6 @@ mut args := '' ' /usr/lib/x86_64-linux-gnu/libc.so ' + '/usr/lib/x86_64-linux-gnu/crtn.o') or { panic(err) - return // TODO remove return } println(ress) println('linux cross compilation done. resulting binary: "$v.out_name"') @@ -1226,7 +1222,7 @@ fn new_v(args[]string) *V { } else { println('vlib not found. It should be next to the V executable. ') - println('Go to https://vlang.io to install V.') + println('Go to https://vlang.io to install V.') exit(1) } mut out_name_c := out_name.all_after('/') + '.c' @@ -1327,7 +1323,6 @@ fn run_repl() []string { os.write_file(file, source_code) s := os.exec('$vexe run $file -repl') or { panic(err) - break // TODO remove break } vals := s.split('\n') for i:=0; i < vals.len; i++ { @@ -1345,7 +1340,6 @@ fn run_repl() []string { os.write_file(temp_file, temp_source_code) s := os.exec('$vexe run $temp_file -repl') or { panic(err) - break // TODO remove break } lines << line vals := s.split('\n') @@ -1411,20 +1405,17 @@ fn update_v() { vroot := os.dir(os.executable()) s := os.exec('git -C "$vroot" pull --rebase origin master') or { panic(err) - return // TODO remove return } println(s) $if windows { os.mv('$vroot/v.exe', '$vroot/v_old.exe') s2 := os.exec('$vroot/make.bat') or { panic(err) - return // TODO remove return } println(s2) } $else { s2 := os.exec('make -C "$vroot"') or { panic(err) - return // TODO remove return } println(s2) } diff --git a/compiler/msvc_win.v b/compiler/msvc_win.v index 5db91d0b4b..6bd65fd6f7 100644 --- a/compiler/msvc_win.v +++ b/compiler/msvc_win.v @@ -28,37 +28,40 @@ const ( KEY_ENUMERATE_SUB_KEYS = (0x0008) ) -// Given a root key look for the subkey 'version' and get the path -fn find_windows_kit_internal(key RegKey, version string) ?string { - required_bytes := 0 // TODO mut - result := C.RegQueryValueExW(key, version.to_wide(), 0, 0, 0, &required_bytes) +// Given a root key look for one of the subkeys in 'versions' and get the path +fn find_windows_kit_internal(key RegKey, versions []string) ?string { + for version in versions { + required_bytes := 0 // TODO mut + result := C.RegQueryValueExW(key, version.to_wide(), 0, 0, 0, &required_bytes) - length := required_bytes / 2 + length := required_bytes / 2 - if result != 0 { - return error('') + if result != 0 { + continue + } + + alloc_length := (required_bytes + 2) + + mut value := &u16(malloc(alloc_length)) + if !value { + continue + } + + result2 := C.RegQueryValueExW(key, version.to_wide(), 0, 0, value, &alloc_length) + + if result2 != 0 { + continue + } + + // We might need to manually null terminate this thing + // So just make sure that we do that + if (value[length - 1] != u16(0)) { + value[length] = u16(0) + } + + return string_from_wide(value) } - - alloc_length := (required_bytes + 2) - - mut value := &u16(malloc(alloc_length)) - if !value { - return error('') - } - - result2 := C.RegQueryValueExW(key, version.to_wide(), 0, 0, value, &alloc_length) - - if result2 != 0 { - return error('') - } - - // We might need to manually null terminate this thing - // So just make sure that we do that - if (value[length - 1] != u16(0)) { - value[length] = u16(0) - } - - return string_from_wide(value) + return error('windows kit not found') } struct WindowsKit { @@ -82,13 +85,8 @@ fn find_windows_kit_root() ?WindowsKit { return error('Unable to open root key') } // Try and find win10 kit - kit_root := find_windows_kit_internal(root_key, 'KitsRoot10') or { - // Fallback to windows 8 - k := find_windows_kit_internal(root_key, 'KitsRoot81') or { - println('Unable to find windows sdk') - return error('Unable to find a windows kit') - } - k + kit_root := find_windows_kit_internal(root_key, ['KitsRoot10', 'KitsRoot81']) or { + return error('Unable to find a windows kit') } kit_lib := kit_root + 'Lib' @@ -135,8 +133,7 @@ fn find_vs() ?VsInstallation { // If its not there then end user needs to update their visual studio // installation! res := os.exec('""%ProgramFiles(x86)%\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath"') or { - panic(err) - return error(err)// TODO remove return + return error(err) } // println('res: "$res"') @@ -347,7 +344,6 @@ pub fn (v mut V) cc_msvc() { _ := os.exec(cmd) or { println(err) panic('msvc error') - return // TODO remove return } // println(res) // println('C OUTPUT:') @@ -391,7 +387,6 @@ fn build_thirdparty_obj_file_with_msvc(flag string) { res := os.exec('""$msvc.exe_path\\cl.exe" /volatile:ms /Z7 $include_string /c $cfiles /Fo"$obj_path" /D_UNICODE /DUNICODE"') or { panic(err) - return // TODO remove return } println(res) } diff --git a/compiler/parser.v b/compiler/parser.v index 34fe7f97cf..3b84f06346 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -102,7 +102,6 @@ fn platform_postfix_to_ifdefguard(name string) string { case '_mac.v': return '#ifdef __APPLE__' } panic('bad platform_postfix "$name"') - return '' } fn (v mut V) new_parser(path string, pass Pass) Parser { @@ -296,7 +295,6 @@ fn (p mut Parser) parse() { if false && !p.first_pass() && p.fileis('main.v') { out := os.create('/var/tmp/fmt.v') or { panic('failed to create fmt.v') - return } out.writeln(p.scanner.fmt_out.str()) out.close() @@ -1103,6 +1101,9 @@ fn (p mut Parser) vh_genln(s string) { } fn (p mut Parser) statement(add_semi bool) string { + if(p.returns) { + p.error('unreachable code') + } p.cgen.is_tmp = false tok := p.tok mut q := '' @@ -1321,6 +1322,7 @@ fn (p mut Parser) var_decl() { if !p.returns && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break { p.error('`or` block must return/continue/break/panic') } + p.returns = false } p.register_var(Var { name: name @@ -1983,7 +1985,6 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { p.cgen.insert_before('$typ $tmp = $tmp_val;') } return typ - return 'void' } // else if p.pref.is_verbose && p.assigned_var != '' { // p.error('didnt assign') @@ -2905,7 +2906,6 @@ fn os_name_to_ifdef(name string) string { case 'msvc': return '_MSC_VER' } panic('bad os ifdef name "$name"') - return '' } fn (p mut Parser) if_st(is_expr bool, elif_depth int) string { @@ -3167,6 +3167,7 @@ fn (p mut Parser) for_st() { p.statements() p.close_scope() p.for_expr_cnt-- + p.returns = false // TODO handle loops that are guaranteed to return } fn (p mut Parser) switch_statement() { @@ -3180,7 +3181,9 @@ fn (p mut Parser) switch_statement() { expr := p.cgen.end_tmp() p.check(.lcbr) mut i := 0 + mut all_cases_return := true for p.tok == .key_case || p.tok == .key_default || p.peek() == .arrow || p.tok == .key_else { + p.returns = false if p.tok == .key_default || p.tok == .key_else { p.genln('else { // default:') if p.tok == .key_default { @@ -3191,7 +3194,8 @@ fn (p mut Parser) switch_statement() { p.check(.arrow) } p.statements() - break + p.returns = all_cases_return && p.returns + return } if i > 0 { p.gen('else ') @@ -3228,8 +3232,10 @@ fn (p mut Parser) switch_statement() { p.gen(')) {') p.genln('/* case */') p.statements() + all_cases_return = all_cases_return && p.returns i++ } + p.returns = false // only get here when no default, so return is not guaranteed } fn (p mut Parser) assert_statement() { diff --git a/compiler/scanner.v b/compiler/scanner.v index 5ee9164bb3..e125d133ef 100644 --- a/compiler/scanner.v +++ b/compiler/scanner.v @@ -33,7 +33,6 @@ fn new_scanner(file_path string) *Scanner { mut raw_text := os.read_file(file_path) or { panic('scanner: failed to open "$file_path"') - return &Scanner{} } // BOM check diff --git a/compiler/table.v b/compiler/table.v index e5dc646092..e0660ca784 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -739,8 +739,7 @@ fn (t mut Table) fn_gen_types(fn_name string) []string { return f.types } } - panic('function $fn_name not found') // TODO panic or return []? - return []string // TODO remove return + panic('function $fn_name not found') } // `foo()` @@ -830,7 +829,6 @@ fn (fit mut FileImportTable) register_import(mod string) { fn (fit mut FileImportTable) register_alias(alias string, mod string) { if alias in fit.imports { panic('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".') - return } if mod.contains('.internal.') { mod_parts := mod.split('.') diff --git a/compiler/tests/option_test.v b/compiler/tests/option_test.v index 6e90d207fc..6e3733ac9e 100644 --- a/compiler/tests/option_test.v +++ b/compiler/tests/option_test.v @@ -19,7 +19,6 @@ fn err_call(ok bool) ?int { fn test_option_for_base_type_without_variable() { val := err_call(true) or { panic(err) - return } assert val == 42 } diff --git a/examples/news_fetcher.v b/examples/news_fetcher.v index 4b00991148..f2df8aea89 100644 --- a/examples/news_fetcher.v +++ b/examples/news_fetcher.v @@ -36,12 +36,10 @@ fn (f mut Fetcher) fetch() { resp := http.get('https://hacker-news.firebaseio.com/v0/item/${id}.json') or { println('failed to fetch data from /v0/item/${id}.json') exit(1) - return // TODO remove return } story := json.decode(Story, resp.text) or { println('failed to decode a story') exit(1) - return // TODO remove return } f.wg.done() println('#$cursor) $story.title | $story.url') diff --git a/make_tests.bat b/make_tests.bat index 72b5ce3a02..7b94074683 100644 --- a/make_tests.bat +++ b/make_tests.bat @@ -1,29 +1,49 @@ @echo off +echo fetch v.c curl -O https://raw.githubusercontent.com/vlang/vc/master/v.c +if %ERRORLEVEL% NEQ 0 goto :fail + +echo build vc using gcc gcc -std=gnu11 -DUNICODE -D_UNICODE -w -o vc.exe v.c del v.c +if %ERRORLEVEL% NEQ 0 goto :fail +echo build v using vc vc.exe -o v.exe compiler +if %ERRORLEVEL% NEQ 0 goto :fail + +echo build v.msvc using v v.exe -os msvc -o v.msvc.exe compiler +if %ERRORLEVEL% NEQ 0 goto :fail + +echo build v.msvc.2 using v.msvc v.msvc.exe -os msvc -o v.msvc.2.exe compiler +if %ERRORLEVEL% NEQ 0 goto :fail + +echo build v.gcc using v.msvc v.msvc.exe -o v.gcc.exe compiler +if %ERRORLEVEL% NEQ 0 goto :fail setlocal EnableDelayedExpansion +echo testing v for /r . %%x in (*_test.v) do ( v -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail ) +echo testing v.msvc for /r . %%x in (*_test.v) do ( v.msvc.exe -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail ) +echo testing v -os msvc for /r . %%x in (*_test.v) do ( v -os msvc -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail ) +echo testing v.msvc -os msvc for /r . %%x in (*_test.v) do ( v.msvc.exe -os msvc -o test.exe -debug %%x if !ERRORLEVEL! NEQ 0 goto :fail @@ -36,3 +56,4 @@ echo fail exit /b 1 :done +echo pass \ No newline at end of file diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 00c70eada7..4d4449ec35 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -77,7 +77,6 @@ pub fn (a mut array) sort_with_compare(compare voidptr) { pub fn (a mut array) insert(i int, val voidptr) { if i >= a.len { panic('array.insert: index larger than length') - return } a._push(val) size := a.element_size diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 52da5a7124..a035f4e963 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -18,7 +18,9 @@ fn on_panic(f fn (int) int) { } pub fn print_backtrace() { - return + if true { + return // TODO + } $if mac { buffer := [100]voidptr nr_ptrs := C.backtrace(buffer, 100) diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 1a372daa05..7a7c4aa6ba 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -94,8 +94,7 @@ fn (n & Node) find(key string, out voidptr, element_size int) bool{ } else { return n.right.find(key, out, element_size) } - } - return false + } } // same as `find`, but doesn't return a value. Used by `exists` @@ -116,8 +115,7 @@ fn (n & Node) find2(key string, element_size int) bool{ } else { return n.right.find2(key, element_size) } - } - return false + } } fn (m mut map) _set(key string, val voidptr) { @@ -215,7 +213,6 @@ pub fn (m mut map) delete(key string) { pub fn (m map) exists(key string) bool { panic('map.exists(key) was removed from the language. Use `key in map` instead.') - return false } fn (m map) _exists(key string) bool { diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index d5a56beab4..a923454288 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -40,7 +40,6 @@ pub fn tos(s byteptr, len int) string { pub fn tos_clone(s byteptr) string { if isnil(s) { panic('tos: nil string') - return string{} } len := strlen(s) res := tos(s, len) @@ -52,7 +51,6 @@ pub fn tos_clone(s byteptr) string { fn tos2(s byteptr) string { if isnil(s) { panic('tos2: nil string') - return string{} } len := C.strlen(s) res := tos(s, len) @@ -337,7 +335,6 @@ pub fn (s string) right(n int) string { pub fn (s string) substr(start, end int) string { if start > end || start > s.len || end > s.len || start < 0 || end < 0 { panic('substr($start, $end) out of bounds (len=$s.len)') - return '' } len := end - start diff --git a/vlib/freetype/freetype.v b/vlib/freetype/freetype.v index d21ad94486..9e5abc8c85 100644 --- a/vlib/freetype/freetype.v +++ b/vlib/freetype/freetype.v @@ -84,7 +84,8 @@ struct Cfg { fn ft_load_char(_face Face, code i64) Character { // #FT_Face face = *(FT_Face*)(_face); FT_ULong code = *(FT_ULong*)(code); # FT_Face face = *((FT_Face*)_face.cobj); - # if (FT_Load_Char(face, code, FT_LOAD_RENDER)) + # int condition = FT_Load_Char(face, code, FT_LOAD_RENDER); + if (C.condition != 0) { println('freetype: Failed to load Glyph') exit(1) @@ -170,7 +171,8 @@ pub fn new_context(cfg gg.Cfg) *Context { } println('Trying to load font from $font_path') # FT_Face face; - # if (FT_New_Face(ft, font_path.str, 0, &face)) + # int condition = FT_New_Face(ft, font_path.str, 0, &face); + if (C.condition != 0) // # if (FT_New_Face(ft, "/Library/Fonts/Courier New.ttf", 0, &face)) // # if (FT_New_Face(ft, "/System/Library/Fonts/Apple Color Emoji.ttc", 0, &face)) { diff --git a/vlib/gg/gg.v b/vlib/gg/gg.v index d871fd6002..e0d0f1971c 100644 --- a/vlib/gg/gg.v +++ b/vlib/gg/gg.v @@ -274,7 +274,7 @@ pub fn (ctx &GG) draw_rect2(x, y, w, h f32, c gx.Color) { fn todo_remove_me(cfg Cfg, scale int) { // Can only have text in ortho mode if !cfg.use_ortho { - return &GG{} + return } mut width := cfg.width * scale mut height := cfg.height * scale diff --git a/vlib/http/http.v b/vlib/http/http.v index 0424b2465c..e578c17688 100644 --- a/vlib/http/http.v +++ b/vlib/http/http.v @@ -169,22 +169,18 @@ fn build_request_headers(user_agent, method, host_name, path string) string { pub fn unescape_url(s string) string { panic('http.unescape_url() was replaced with urllib.query_unescape()') - return '' } pub fn escape_url(s string) string { panic('http.escape_url() was replaced with urllib.query_escape()') - return '' } pub fn unescape(s string) string { panic('http.unescape() was replaced with http.unescape_url()') - return '' } pub fn escape(s string) string { panic('http.escape() was replaced with http.escape_url()') - return '' } type wsfn fn (s string, ptr voidptr) diff --git a/vlib/json/json_test.v b/vlib/json/json_test.v index 18fc7d3b22..5a8c823af8 100644 --- a/vlib/json/json_test.v +++ b/vlib/json/json_test.v @@ -9,7 +9,6 @@ fn test_parse_user() { s := '{"age": 10, "nums": [1,2,3]}' u := json.decode(User, s) or { exit(1) - return } assert u.age == 10 assert u.nums.len == 3 diff --git a/vlib/log/log.v b/vlib/log/log.v index 0b16217732..3726b94e40 100644 --- a/vlib/log/log.v +++ b/vlib/log/log.v @@ -39,7 +39,6 @@ fn (l Log) log_file(s string, e string) { filename := l.output f := os.open_append(l.output) or { panic('error reading file $filename') - return } timestamp := time.now().format_ss() f.writeln('$timestamp [$e] $s') diff --git a/vlib/math/fractions/fraction.v b/vlib/math/fractions/fraction.v index 0c93881ea4..ac8a41853a 100644 --- a/vlib/math/fractions/fraction.v +++ b/vlib/math/fractions/fraction.v @@ -19,7 +19,6 @@ pub fn fraction(n i64, d i64) Fraction{ } else { panic('Denominator cannot be zero') - return Fraction{} // TODO remove return } } diff --git a/vlib/os/os.v b/vlib/os/os.v index d64723a2b1..ebfcc499fc 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -870,6 +870,7 @@ pub fn fork() int { pid := C.fork() return pid } + panic('os.fork not supported in windows') // TODO } pub fn wait() int { @@ -877,6 +878,7 @@ pub fn wait() int { pid := C.wait(0) return pid } + panic('os.wait not supported in windows') // TODO } pub fn file_last_mod_unix(path string) int { diff --git a/vlib/os/os_test.v b/vlib/os/os_test.v index feafd1d0ce..9dbf1d6279 100644 --- a/vlib/os/os_test.v +++ b/vlib/os/os_test.v @@ -27,7 +27,6 @@ fn test_write_and_read_string_to_file() { read_hello := os.read_file(filename) or { panic('error reading file $filename') - return } assert hello == read_hello diff --git a/vlib/os/os_win.v b/vlib/os/os_win.v index 9b5a84e68b..cfb21b3bda 100644 --- a/vlib/os/os_win.v +++ b/vlib/os/os_win.v @@ -40,6 +40,7 @@ pub fn get_module_filename(handle HANDLE) ?string { return error('Cannot get file name from handle.') } } + panic('this should be unreachable') // TODO remove unreachable after loop } // Ref - https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessagea#parameters diff --git a/vlib/vweb/tmpl/tmpl.v b/vlib/vweb/tmpl/tmpl.v index 14a2596993..152a711fc4 100644 --- a/vlib/vweb/tmpl/tmpl.v +++ b/vlib/vweb/tmpl/tmpl.v @@ -17,13 +17,11 @@ pub fn compile_template(path string) string { //lines := os.read_lines(path) mut html := os.read_file(path) or { panic('html failed') - return '' } mut header := '' if os.file_exists('header.html') { h := os.read_file('header.html') or { panic('html failed') - return '' } header = h.replace('\'', '"') } diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 2d643ebae7..62e2527038 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -85,13 +85,12 @@ $html pub fn run(port int) { println('Running vweb app on http://localhost:$port ...') - l := net.listen(port) or { panic('failed to listen') return } + l := net.listen(port) or { panic('failed to listen') } mut app := T{} app.init() for { conn := l.accept() or { panic('accept() failed') - return } // TODO move this to handle_conn(conn, app) s := conn.read_line()