diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 97f5e84a78..de724b9b7a 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -217,11 +217,6 @@ mut: typ table.Type } -pub struct StmtBlock { -pub: - stmts []Stmt -} - pub struct File { pub: path string @@ -340,13 +335,20 @@ pub struct MatchExpr { pub: tok_kind token.Kind cond Expr - blocks []StmtBlock - match_exprs []Expr + branches []MatchBranch pos token.Position mut: typ table.Type } +pub struct MatchBranch { +pub: + exprs []Expr + stmts []Stmt + pos token.Position +} + + pub struct CompIf { pub: cond Expr diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index db6a56a5ab..1ad00a5663 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -666,20 +666,20 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type { pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { t := c.expr(node.cond) + c.expected_type = t mut ret_type := table.void_type - for i, block in node.blocks { - if i < node.match_exprs.len { - match_expr := node.match_exprs[i] + for branch in node.branches { + for expr in branch.exprs { c.expected_type = t - typ := c.expr(match_expr) + typ := c.expr(expr) typ_sym := c.table.get_type_symbol(typ) // TODO: if typ_sym.kind == .sum_type {} } - c.stmts(block.stmts) + c.stmts(branch.stmts) // If the last statement is an expression, return its type - if block.stmts.len > 0 { - match block.stmts[block.stmts.len - 1] { + if branch.stmts.len > 0 { + match branch.stmts[branch.stmts.len - 1] { ast.ExprStmt { ret_type = c.expr(it.expr) } @@ -690,7 +690,7 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type { // node.typ = typ // return typ else {} - } + } } } node.typ = t diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 401c546481..b8030734d8 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -351,12 +351,17 @@ fn (g mut Gen) expr(node ast.Expr) { g.write('$type_sym.name $tmp = ') g.expr(it.cond) g.writeln(';') // $it.blocks.len') - for i, block in it.blocks { - match_expr := it.match_exprs[i] - g.write('if $tmp == ') - g.expr(match_expr) + for branch in it.branches { + g.write('if ') + for i, expr in branch.exprs { + g.write('$tmp == ') + g.expr(expr) + if i < branch.exprs.len-1 { + g.write(' || ') + } + } g.writeln('{') - g.stmts(block.stmts) + g.stmts(branch.stmts) g.writeln('}') } } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 61ab5f63dd..6f4c9aad45 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1702,27 +1702,28 @@ fn (p mut Parser) global_decl() ast.GlobalDecl { } } -fn (p mut Parser) match_expr() ast.Expr { +fn (p mut Parser) match_expr() ast.MatchExpr { p.check(.key_match) is_mut := p.tok.kind == .key_mut if is_mut { p.next() } cond,_ := p.expr(0) - // sym := p.table.get_type_symbol(typ) - // p.warn('match typ $sym.name') p.check(.lcbr) - mut blocks := []ast.StmtBlock - mut match_exprs := []ast.Expr - // mut return_type := table.void_type + mut branches := []ast.MatchBranch for { + mut exprs := []ast.Expr p.open_scope() + // final else + if p.tok.kind == .key_else { + p.next() + } // Sum type match - if p.tok.kind == .name && (p.tok.lit[0].is_capital() || p.peek_tok.kind == .dot) { + else if p.tok.kind == .name && (p.tok.lit[0].is_capital() || p.peek_tok.kind == .dot) { // if sym.kind == .sum_type { // p.warn('is sum') typ := p.parse_type() - match_exprs << ast.Type{ + exprs << ast.Type{ typ: typ } p.scope.register_var(ast.VarDecl{ @@ -1733,8 +1734,8 @@ fn (p mut Parser) match_expr() ast.Expr { else { // Expression match for { - match_expr,_ := p.expr(0) - match_exprs << match_expr + expr,_ := p.expr(0) + exprs << expr if p.tok.kind != .comma { break } @@ -1743,45 +1744,21 @@ fn (p mut Parser) match_expr() ast.Expr { } // p.warn('match block') stmts := p.parse_block() - blocks << ast.StmtBlock{ + branches << ast.MatchBranch{ + exprs: exprs stmts: stmts + } - if p.tok.kind == .key_else { - p.next() - blocks << ast.StmtBlock{ - stmts: p.parse_block() - } - } - // 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('match expr ret $type_sym.name') - return_type = it.typ - } - else {} - } - } - */ - p.close_scope() if p.tok.kind == .rcbr { break } } p.check(.rcbr) - mut node := ast.Expr{} - node = ast.MatchExpr{ - blocks: blocks - match_exprs: match_exprs - // typ: typ - + return ast.MatchExpr{ + branches: branches cond: cond } - return node - // return node,return_type } fn (p mut Parser) enum_decl() ast.EnumDecl {