checker: check if BranchStmt is in a loop

pull/4282/head
Daniel Däschle 2020-04-07 12:29:11 +02:00 committed by GitHub
parent fd75cce0f3
commit fe0942043c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 3 deletions

View File

@ -31,6 +31,7 @@ mut:
//assigned_var_name string //assigned_var_name string
// fn_decl ast.FnDecl // fn_decl ast.FnDecl
pref &pref.Preferences // Preferences shared from V struct pref &pref.Preferences // Preferences shared from V struct
in_for_count int // if checker is currently in an for loop
} }
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker { pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
@ -597,6 +598,11 @@ fn (c mut Checker) stmt(node ast.Stmt) {
ast.Block { ast.Block {
c.stmts(it.stmts) c.stmts(it.stmts)
} }
ast.BranchStmt {
if c.in_for_count == 0 {
c.error('$it.tok.lit statement not within a loop', it.tok.position())
}
}
// ast.Attr {} // ast.Attr {}
ast.CompIf { ast.CompIf {
// c.expr(it.cond) // c.expr(it.cond)
@ -660,6 +666,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
c.stmts(it.stmts) c.stmts(it.stmts)
} }
ast.ForStmt { ast.ForStmt {
c.in_for_count++
typ := c.expr(it.cond) typ := c.expr(it.cond)
if !it.is_inf && table.type_idx(typ) != table.bool_type_idx { if !it.is_inf && table.type_idx(typ) != table.bool_type_idx {
c.error('non-bool used as for condition', it.pos) c.error('non-bool used as for condition', it.pos)
@ -667,15 +674,19 @@ fn (c mut Checker) stmt(node ast.Stmt) {
// TODO: update loop var type // TODO: update loop var type
// how does this work currenly? // how does this work currenly?
c.stmts(it.stmts) c.stmts(it.stmts)
c.in_for_count--
} }
ast.ForCStmt { ast.ForCStmt {
c.in_for_count++
c.stmt(it.init) c.stmt(it.init)
c.expr(it.cond) c.expr(it.cond)
// c.stmt(it.inc) // c.stmt(it.inc)
c.expr(it.inc) c.expr(it.inc)
c.stmts(it.stmts) c.stmts(it.stmts)
c.in_for_count--
} }
ast.ForInStmt { ast.ForInStmt {
c.in_for_count++
typ := c.expr(it.cond) typ := c.expr(it.cond)
if it.is_range { if it.is_range {
c.expr(it.high) c.expr(it.high)
@ -690,7 +701,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
} }
else { else {
table.int_type} table.int_type}
} }
it.key_type = key_type it.key_type = key_type
scope.update_var_type(it.key_var, key_type) scope.update_var_type(it.key_var, key_type)
} }
@ -705,6 +716,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
scope.update_var_type(it.val_var, value_type) scope.update_var_type(it.val_var, value_type)
} }
c.stmts(it.stmts) c.stmts(it.stmts)
c.in_for_count--
} }
ast.GoStmt{ ast.GoStmt{
c.expr(it.call_expr) c.expr(it.call_expr)

View File

@ -379,7 +379,7 @@ pub fn (s mut Scanner) scan() token.Token {
// Check if not .eof to prevent panic // Check if not .eof to prevent panic
next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` }
if token.is_key(name) { if token.is_key(name) {
return s.new_token(token.key_to_token(name), '') return s.new_token(token.key_to_token(name), name)
} }
// 'asdf $b' => "b" is the last name in the string, dont start parsing string // 'asdf $b' => "b" is the last name in the string, dont start parsing string
// at the next ', skip it // at the next ', skip it
@ -1019,7 +1019,7 @@ pub fn (s &Scanner) error(msg string) {
pos := token.Position{ pos := token.Position{
line_nr: s.line_nr line_nr: s.line_nr
pos: s.pos pos: s.pos
} }
eprintln(util.formated_error('error', msg, s.file_path, pos)) eprintln(util.formated_error('error', msg, s.file_path, pos))
exit(1) exit(1)
} }