v2: update MatchExpr

pull/3937/head
Joe Conigliaro 2020-03-04 21:59:45 +11:00
parent ed763df42e
commit e71948461e
4 changed files with 43 additions and 59 deletions

View File

@ -217,11 +217,6 @@ mut:
typ table.Type typ table.Type
} }
pub struct StmtBlock {
pub:
stmts []Stmt
}
pub struct File { pub struct File {
pub: pub:
path string path string
@ -340,13 +335,20 @@ pub struct MatchExpr {
pub: pub:
tok_kind token.Kind tok_kind token.Kind
cond Expr cond Expr
blocks []StmtBlock branches []MatchBranch
match_exprs []Expr
pos token.Position pos token.Position
mut: mut:
typ table.Type typ table.Type
} }
pub struct MatchBranch {
pub:
exprs []Expr
stmts []Stmt
pos token.Position
}
pub struct CompIf { pub struct CompIf {
pub: pub:
cond Expr cond Expr

View File

@ -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 { pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
t := c.expr(node.cond) t := c.expr(node.cond)
mut ret_type := table.void_type
for i, block in node.blocks {
if i < node.match_exprs.len {
match_expr := node.match_exprs[i]
c.expected_type = t c.expected_type = t
typ := c.expr(match_expr) mut ret_type := table.void_type
for branch in node.branches {
for expr in branch.exprs {
c.expected_type = t
typ := c.expr(expr)
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
// TODO: // TODO:
if typ_sym.kind == .sum_type {} 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 the last statement is an expression, return its type
if block.stmts.len > 0 { if branch.stmts.len > 0 {
match block.stmts[block.stmts.len - 1] { match branch.stmts[branch.stmts.len - 1] {
ast.ExprStmt { ast.ExprStmt {
ret_type = c.expr(it.expr) ret_type = c.expr(it.expr)
} }

View File

@ -351,12 +351,17 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write('$type_sym.name $tmp = ') g.write('$type_sym.name $tmp = ')
g.expr(it.cond) g.expr(it.cond)
g.writeln(';') // $it.blocks.len') g.writeln(';') // $it.blocks.len')
for i, block in it.blocks { for branch in it.branches {
match_expr := it.match_exprs[i] g.write('if ')
g.write('if $tmp == ') for i, expr in branch.exprs {
g.expr(match_expr) g.write('$tmp == ')
g.expr(expr)
if i < branch.exprs.len-1 {
g.write(' || ')
}
}
g.writeln('{') g.writeln('{')
g.stmts(block.stmts) g.stmts(branch.stmts)
g.writeln('}') g.writeln('}')
} }
} }

View File

@ -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) p.check(.key_match)
is_mut := p.tok.kind == .key_mut is_mut := p.tok.kind == .key_mut
if is_mut { if is_mut {
p.next() p.next()
} }
cond,_ := p.expr(0) cond,_ := p.expr(0)
// sym := p.table.get_type_symbol(typ)
// p.warn('match typ $sym.name')
p.check(.lcbr) p.check(.lcbr)
mut blocks := []ast.StmtBlock mut branches := []ast.MatchBranch
mut match_exprs := []ast.Expr
// mut return_type := table.void_type
for { for {
mut exprs := []ast.Expr
p.open_scope() p.open_scope()
// final else
if p.tok.kind == .key_else {
p.next()
}
// Sum type match // 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 { // if sym.kind == .sum_type {
// p.warn('is sum') // p.warn('is sum')
typ := p.parse_type() typ := p.parse_type()
match_exprs << ast.Type{ exprs << ast.Type{
typ: typ typ: typ
} }
p.scope.register_var(ast.VarDecl{ p.scope.register_var(ast.VarDecl{
@ -1733,8 +1734,8 @@ fn (p mut Parser) match_expr() ast.Expr {
else { else {
// Expression match // Expression match
for { for {
match_expr,_ := p.expr(0) expr,_ := p.expr(0)
match_exprs << match_expr exprs << expr
if p.tok.kind != .comma { if p.tok.kind != .comma {
break break
} }
@ -1743,45 +1744,21 @@ fn (p mut Parser) match_expr() ast.Expr {
} }
// p.warn('match block') // p.warn('match block')
stmts := p.parse_block() stmts := p.parse_block()
blocks << ast.StmtBlock{ branches << ast.MatchBranch{
exprs: exprs
stmts: stmts 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() p.close_scope()
if p.tok.kind == .rcbr { if p.tok.kind == .rcbr {
break break
} }
} }
p.check(.rcbr) p.check(.rcbr)
mut node := ast.Expr{} return ast.MatchExpr{
node = ast.MatchExpr{ branches: branches
blocks: blocks
match_exprs: match_exprs
// typ: typ
cond: cond cond: cond
} }
return node
// return node,return_type
} }
fn (p mut Parser) enum_decl() ast.EnumDecl { fn (p mut Parser) enum_decl() ast.EnumDecl {