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

parser: disallow statements after a return, branch check $if, $else, switch, and loops correctly

This commit is contained in:
Julian Schurhammer
2019-08-10 20:26:42 +12:00
committed by Alexander Medvednikov
parent 58b52aa9fb
commit 1864e92ff4
26 changed files with 97 additions and 94 deletions

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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() {

View File

@ -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

View File

@ -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<Bar>()`
@ -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('.')

View File

@ -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
}