parser: fix comptime if script mode (fix #6419) (#14578)

master
yuyi 2022-06-01 18:27:27 +08:00 committed by GitHub
parent 5a2c271bd4
commit 786045c7da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 34 deletions

View File

@ -667,10 +667,15 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
return p.error('unexpected eof')
}
if_expr := p.if_expr(true)
return ast.ExprStmt{
cur_stmt := ast.ExprStmt{
expr: if_expr
pos: if_expr.pos
}
if comptime_if_expr_contains_top_stmt(if_expr) {
return cur_stmt
} else {
return p.other_stmts(cur_stmt)
}
}
.hash {
return p.hash()
@ -688,39 +693,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
return p.comment_stmt()
}
else {
p.inside_fn = true
if p.pref.is_script && !p.pref.is_test {
p.script_mode = true
p.script_mode_start_token = p.tok
if p.table.known_fn('main.main') {
p.error('function `main` is already defined, put your script statements inside it')
}
p.open_scope()
mut stmts := []ast.Stmt{}
for p.tok.kind != .eof {
stmts << p.stmt(false)
}
p.close_scope()
p.script_mode = false
return ast.FnDecl{
name: 'main.main'
short_name: 'main'
mod: 'main'
is_main: true
stmts: stmts
file: p.file_name
return_type: ast.void_type
scope: p.scope
label_names: p.label_names
}
} else if p.pref.is_fmt {
return p.stmt(false)
} else {
return p.error('bad top level statement ' + p.tok.str())
}
return p.other_stmts(ast.empty_stmt())
}
}
if p.should_abort {
@ -732,6 +705,66 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
return ast.empty_stmt()
}
fn comptime_if_expr_contains_top_stmt(if_expr ast.IfExpr) bool {
for branch in if_expr.branches {
for stmt in branch.stmts {
if stmt is ast.ExprStmt {
if stmt.expr is ast.IfExpr {
if !comptime_if_expr_contains_top_stmt(stmt.expr) {
return false
}
} else if stmt.expr is ast.CallExpr {
return false
}
} else if stmt is ast.AssignStmt {
return false
} else if stmt is ast.HashStmt {
return true
}
}
}
return true
}
fn (mut p Parser) other_stmts(cur_stmt ast.Stmt) ast.Stmt {
p.inside_fn = true
if p.pref.is_script && !p.pref.is_test {
p.script_mode = true
p.script_mode_start_token = p.tok
if p.table.known_fn('main.main') {
p.error('function `main` is already defined, put your script statements inside it')
}
p.open_scope()
mut stmts := []ast.Stmt{}
if cur_stmt != ast.empty_stmt() {
stmts << cur_stmt
}
for p.tok.kind != .eof {
stmts << p.stmt(false)
}
p.close_scope()
p.script_mode = false
return ast.FnDecl{
name: 'main.main'
short_name: 'main'
mod: 'main'
is_main: true
stmts: stmts
file: p.file_name
return_type: ast.void_type
scope: p.scope
label_names: p.label_names
}
} else if p.pref.is_fmt {
return p.stmt(false)
} else {
return p.error('bad top level statement ' + p.tok.str())
}
}
// TODO [if vfmt]
pub fn (mut p Parser) check_comment() ast.Comment {
if p.tok.kind == .comment {

View File

@ -0,0 +1 @@
others

View File

@ -0,0 +1,5 @@
$if vinix {
println('vinix')
} $else {
println('others')
}