ast/cgen/parser: combine IfExpr branches into single node
parent
c993489fe9
commit
a331abf675
|
@ -337,9 +337,7 @@ mut:
|
||||||
pub struct IfExpr {
|
pub struct IfExpr {
|
||||||
pub:
|
pub:
|
||||||
tok_kind token.Kind
|
tok_kind token.Kind
|
||||||
cond Expr
|
branches []IfBranch
|
||||||
stmts []Stmt
|
|
||||||
else_stmts []Stmt
|
|
||||||
left Expr // `a` in `a := if ...`
|
left Expr // `a` in `a := if ...`
|
||||||
pos token.Position
|
pos token.Position
|
||||||
mut:
|
mut:
|
||||||
|
@ -348,6 +346,13 @@ mut:
|
||||||
has_else bool
|
has_else bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct IfBranch {
|
||||||
|
pub:
|
||||||
|
cond Expr
|
||||||
|
stmts []Stmt
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MatchExpr {
|
pub struct MatchExpr {
|
||||||
pub:
|
pub:
|
||||||
tok_kind token.Kind
|
tok_kind token.Kind
|
||||||
|
|
|
@ -909,20 +909,22 @@ pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
||||||
// println('$c.file.path $node.pos.line_nr IF: checker exp type = ' + sym.name)
|
// println('$c.file.path $node.pos.line_nr IF: checker exp type = ' + sym.name)
|
||||||
node.is_expr = true
|
node.is_expr = true
|
||||||
}
|
}
|
||||||
typ := c.expr(node.cond)
|
|
||||||
node.typ = table.void_type
|
node.typ = table.void_type
|
||||||
// node.typ = typ
|
for i, branch in node.branches {
|
||||||
|
typ := c.expr(branch.cond)
|
||||||
|
if i < node.branches.len-1 || !node.has_else {
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
// if typ_sym.kind != .bool {
|
// if typ_sym.kind != .bool {
|
||||||
if table.type_idx(typ) != table.bool_type_idx {
|
if table.type_idx(typ) != table.bool_type_idx {
|
||||||
c.error('non-bool (`$typ_sym.name`) used as if condition', node.pos)
|
c.error('non-bool (`$typ_sym.name`) used as if condition', node.pos)
|
||||||
}
|
}
|
||||||
c.stmts(node.stmts)
|
|
||||||
if node.else_stmts.len > 0 {
|
|
||||||
c.stmts(node.else_stmts)
|
|
||||||
}
|
}
|
||||||
if node.stmts.len > 0 {
|
c.stmts(branch.stmts)
|
||||||
match node.stmts[node.stmts.len - 1] {
|
}
|
||||||
|
if node.has_else && node.is_expr {
|
||||||
|
last_branch := node.branches[node.branches.len-1]
|
||||||
|
if last_branch.stmts.len > 0 {
|
||||||
|
match last_branch.stmts[last_branch.stmts.len - 1] {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
// type_sym := p.table.get_type_symbol(it.typ)
|
// type_sym := p.table.get_type_symbol(it.typ)
|
||||||
// p.warn('if expr ret $type_sym.name')
|
// p.warn('if expr ret $type_sym.name')
|
||||||
|
@ -933,8 +935,8 @@ pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return typ
|
}
|
||||||
// return table.void_type
|
return table.bool_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
||||||
|
|
|
@ -378,38 +378,38 @@ fn (f mut Fmt) expr(node ast.Expr) {
|
||||||
f.write(it.val)
|
f.write(it.val)
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
single_line := it.stmts.len == 1 && it.else_stmts.len == 1 && it.typ != table.void_type
|
single_line := it.branches.len == 2 && it.has_else //
|
||||||
|
&& it.branches[0].stmts.len == 1 && it.branches[1].stmts.len == 1
|
||||||
f.single_line_if = single_line
|
f.single_line_if = single_line
|
||||||
|
for i, branch in it.branches {
|
||||||
|
if i == 0 {
|
||||||
f.write('if ')
|
f.write('if ')
|
||||||
f.expr(it.cond)
|
f.expr(branch.cond)
|
||||||
if single_line {
|
|
||||||
f.write(' {')
|
f.write(' {')
|
||||||
}
|
}
|
||||||
else {
|
else if i < it.branches.len-1 || !it.has_else {
|
||||||
f.writeln(' {')
|
f.write('} else if ')
|
||||||
|
f.expr(branch.cond)
|
||||||
|
f.write(' {')
|
||||||
}
|
}
|
||||||
f.stmts(it.stmts)
|
else if i == it.branches.len-1 && it.has_else {
|
||||||
if single_line {
|
f.write('} else {')
|
||||||
f.write(' ')
|
|
||||||
}
|
}
|
||||||
f.write('}')
|
|
||||||
if it.has_else {
|
|
||||||
f.write(' else ')
|
|
||||||
}
|
|
||||||
else if it.else_stmts.len > 0 {
|
|
||||||
f.write(' else {')
|
|
||||||
if single_line {
|
if single_line {
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
f.writeln('')
|
f.writeln('')
|
||||||
}
|
}
|
||||||
f.stmts(it.else_stmts)
|
f.stmts(branch.stmts)
|
||||||
if single_line {
|
if single_line {
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
}
|
}
|
||||||
f.write('}')
|
|
||||||
}
|
}
|
||||||
|
// if !single_line {
|
||||||
|
// f.writeln('')
|
||||||
|
// }
|
||||||
|
f.write('}')
|
||||||
f.single_line_if = false
|
f.single_line_if = false
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
|
|
|
@ -1176,27 +1176,27 @@ fn (g mut Gen) if_expr(node ast.IfExpr) {
|
||||||
}
|
}
|
||||||
// one line ?:
|
// one line ?:
|
||||||
// TODO clean this up once `is` is supported
|
// TODO clean this up once `is` is supported
|
||||||
if node.is_expr && node.stmts.len == 1 && node.else_stmts.len == 1 && type_sym.kind != .void {
|
// TODO: make sure only one stmt in eac branch
|
||||||
cond := node.cond
|
if node.is_expr && node.branches.len >= 2 && node.has_else && type_sym.kind != .void {
|
||||||
stmt1 := node.stmts[0]
|
|
||||||
else_stmt1 := node.else_stmts[0]
|
|
||||||
match stmt1 {
|
|
||||||
ast.ExprStmt {
|
|
||||||
g.inside_ternary = true
|
g.inside_ternary = true
|
||||||
g.expr(cond)
|
for i, branch in node.branches {
|
||||||
g.write(' ? ')
|
if i > 0 {
|
||||||
expr_stmt := stmt1 as ast.ExprStmt
|
|
||||||
g.expr(expr_stmt.expr)
|
|
||||||
g.write(' : ')
|
g.write(' : ')
|
||||||
g.stmt(else_stmt1)
|
|
||||||
}
|
}
|
||||||
else {}
|
if i < node.branches.len-1 || !node.has_else {
|
||||||
|
g.expr(branch.cond)
|
||||||
|
g.write(' ? ')
|
||||||
}
|
}
|
||||||
|
g.stmts(branch.stmts)
|
||||||
|
}
|
||||||
|
g.inside_ternary = false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mut is_guard := false
|
|
||||||
guard_ok := g.new_tmp_var()
|
guard_ok := g.new_tmp_var()
|
||||||
match node.cond {
|
mut is_guard := false
|
||||||
|
for i, branch in node.branches {
|
||||||
|
if i == 0 {
|
||||||
|
match branch.cond {
|
||||||
ast.IfGuardExpr {
|
ast.IfGuardExpr {
|
||||||
is_guard = true
|
is_guard = true
|
||||||
g.writeln('bool $guard_ok;')
|
g.writeln('bool $guard_ok;')
|
||||||
|
@ -1206,34 +1206,38 @@ fn (g mut Gen) if_expr(node ast.IfExpr) {
|
||||||
g.writeln('if (($guard_ok = ${it.var_name}.ok)) {')
|
g.writeln('if (($guard_ok = ${it.var_name}.ok)) {')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.inside_ternary = false
|
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(node.cond)
|
g.expr(branch.cond)
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, stmt in node.stmts {
|
|
||||||
|
}
|
||||||
|
else if i < node.branches.len-1 || !node.has_else {
|
||||||
|
g.writeln('} else if (')
|
||||||
|
g.expr(branch.cond)
|
||||||
|
g.write(') {')
|
||||||
|
}
|
||||||
|
else if i == node.branches.len-1 && node.has_else {
|
||||||
|
if is_guard {
|
||||||
|
g.writeln('} if (!$guard_ok) { /* else */')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.writeln('} else {')
|
||||||
|
}
|
||||||
|
}
|
||||||
// Assign ret value
|
// Assign ret value
|
||||||
if i == node.stmts.len - 1 && type_sym.kind != .void {}
|
// if i == node.stmts.len - 1 && type_sym.kind != .void {}
|
||||||
// g.writeln('$tmp =')
|
// g.writeln('$tmp =')
|
||||||
g.stmt(stmt)
|
//
|
||||||
|
g.stmts(branch.stmts)
|
||||||
|
// g.writeln('')
|
||||||
}
|
}
|
||||||
if is_guard {
|
if is_guard {
|
||||||
g.write('}')
|
g.write('}')
|
||||||
}
|
}
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if node.else_stmts.len > 0 {
|
|
||||||
if is_guard {
|
|
||||||
g.writeln('if (!$guard_ok) { /* else */')
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
g.writeln('else { ')
|
|
||||||
}
|
|
||||||
g.stmts(node.else_stmts)
|
|
||||||
g.writeln('}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.inside_ternary = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
||||||
|
|
|
@ -34,6 +34,12 @@ pub fn (g mut JsGen) writeln(s string) {
|
||||||
g.out.writeln(s)
|
g.out.writeln(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g mut JsGen) stmts(stmts []ast.Stmt) {
|
||||||
|
for stmt in stmts {
|
||||||
|
g.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (g mut JsGen) stmt(node ast.Stmt) {
|
fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
match node {
|
match node {
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
|
@ -163,14 +169,24 @@ fn (g mut JsGen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
|
for i, branch in it.branches {
|
||||||
|
if i == 0 {
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(it.cond)
|
g.expr(branch.cond)
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
for stmt in it.stmts {
|
|
||||||
g.stmt(stmt)
|
|
||||||
}
|
}
|
||||||
|
else if i < it.branches.len-1 || !it.has_else {
|
||||||
|
g.write('else if (')
|
||||||
|
g.expr(branch.cond)
|
||||||
|
g.writeln(') {')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.write('else {')
|
||||||
|
}
|
||||||
|
g.stmts(branch.stmts)
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
println(term.red('jsgen.expr(): bad node'))
|
println(term.red('jsgen.expr(): bad node'))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1175,16 +1175,33 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) if_expr() ast.Expr {
|
fn (p mut Parser) if_expr() ast.IfExpr {
|
||||||
p.inside_if = true
|
p.inside_if = true
|
||||||
// defer {
|
|
||||||
// }
|
|
||||||
mut node := ast.Expr{}
|
|
||||||
p.check(.key_if)
|
|
||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
// `if x := opt() {`
|
mut branches := []ast.IfBranch
|
||||||
|
mut has_else := false
|
||||||
|
for p.tok.kind in [.key_if, .key_else] {
|
||||||
|
branch_pos := p.tok.position()
|
||||||
|
if p.tok.kind == .key_if {
|
||||||
|
p.check(.key_if)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.check(.key_else)
|
||||||
|
if p.tok.kind == .key_if {
|
||||||
|
p.check(.key_if)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
has_else = true
|
||||||
|
branches << ast.IfBranch{
|
||||||
|
stmts: p.parse_block()
|
||||||
|
pos: branch_pos
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
mut cond := ast.Expr{}
|
mut cond := ast.Expr{}
|
||||||
mut is_or := false
|
mut is_or := false
|
||||||
|
// `if x := opt() {`
|
||||||
if p.peek_tok.kind == .decl_assign {
|
if p.peek_tok.kind == .decl_assign {
|
||||||
is_or = true
|
is_or = true
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
|
@ -1204,53 +1221,24 @@ fn (p mut Parser) if_expr() ast.Expr {
|
||||||
cond = p.expr(0)
|
cond = p.expr(0)
|
||||||
}
|
}
|
||||||
p.inside_if = false
|
p.inside_if = false
|
||||||
mut has_else := false
|
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
mut else_stmts := []ast.Stmt
|
|
||||||
if p.tok.kind == .key_else {
|
|
||||||
p.check(.key_else)
|
|
||||||
if p.tok.kind == .key_if {
|
|
||||||
// The next if block is handled by next if_expr()
|
|
||||||
has_else = true
|
|
||||||
}
|
|
||||||
// p.if_expr()
|
|
||||||
else {
|
|
||||||
else_stmts = p.parse_block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_or {
|
if is_or {
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
}
|
}
|
||||||
// mut typ := table.void_type
|
branches << ast.IfBranch{
|
||||||
// mut left := ast.Expr{}
|
|
||||||
// If the last statement is an expression, return its type
|
|
||||||
/*
|
|
||||||
if stmts.len > 0 {
|
|
||||||
match stmts[stmts.len - 1] {
|
|
||||||
ast.ExprStmt {
|
|
||||||
type_sym := p.table.get_type_symbol(it.typ)
|
|
||||||
p.warn('if expr ret $type_sym.name')
|
|
||||||
typ = it.typ
|
|
||||||
// return node,it.ti
|
|
||||||
// left =
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
node = ast.IfExpr{
|
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
else_stmts: else_stmts
|
pos: branch_pos
|
||||||
// typ: typ
|
}
|
||||||
|
if p.tok.kind != .key_else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ast.IfExpr{
|
||||||
|
branches: branches
|
||||||
pos: pos
|
pos: pos
|
||||||
has_else: has_else
|
has_else: has_else
|
||||||
// left: left
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return node
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) string_expr() ast.Expr {
|
fn (p mut Parser) string_expr() ast.Expr {
|
||||||
|
|
Loading…
Reference in New Issue