parser/checker/gen: match shaddow cond var & as support: p1

pull/5416/head
joe-conigliaro 2020-06-19 00:33:16 +10:00
parent 7be952605b
commit 68143b7b22
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
8 changed files with 84 additions and 49 deletions

View File

@ -442,6 +442,7 @@ pub:
branches []MatchBranch
pos token.Position
is_mut bool // `match mut ast_node {`
var_name string
pub mut:
is_expr bool // returns a value
return_type table.Type

View File

@ -126,22 +126,33 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
}
}
}
// TODO: remove sponge - put back match
if !needs_braces {
mut sub_expr := lit.exprs[i]
for {
match sub_expr {
Ident {
break
}
SelectorExpr {
sub_expr = it.expr
continue
}
else {
needs_braces = true
break
}
if sub_expr is Ident { break }
else if sub_expr is SelectorExpr {
se := sub_expr as SelectorExpr
sub_expr = se.expr
continue
}
else {
needs_braces = true
break
}
// match sub_expr {
// Ident {
// break
// }
// SelectorExpr {
// sub_expr = it.expr
// continue
// }
// else {
// needs_braces = true
// break
// }
// }
}
}
if needs_fspec {

View File

@ -93,13 +93,15 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool {
return true
}
// sum type
if got_type_sym.kind == .sum_type {
sum_info := got_type_sym.info as table.SumType
// TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
if expected.set_nr_muls(0) in sum_info.variants {
return true
}
}
// TODO: there is a bug when casting sumtype the other way if its pointer
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
// if got_type_sym.kind == .sum_type {
// sum_info := got_type_sym.info as table.SumType
// // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
// if expected.set_nr_muls(0) in sum_info.variants {
// return true
// }
// }
if exp_type_sym.kind == .sum_type {
sum_info := exp_type_sym.info as table.SumType
// TODO: handle `match SumType { &PtrVariant {} }` currently just checking base

View File

@ -170,19 +170,19 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
}
}
ast.TypeDecl {
type_decl := stmt as ast.TypeDecl
if type_decl is ast.AliasTypeDecl {
alias_decl := type_decl as ast.AliasTypeDecl
// type_decl := stmt as ast.TypeDecl
if it is ast.AliasTypeDecl {
alias_decl := it as ast.AliasTypeDecl
if alias_decl.is_pub {
c.warn('type alias `$alias_decl.name` $no_pub_in_main_warning', alias_decl.pos)
}
} else if type_decl is ast.SumTypeDecl {
sum_decl := type_decl as ast.SumTypeDecl
} else if it is ast.SumTypeDecl {
sum_decl := it as ast.SumTypeDecl
if sum_decl.is_pub {
c.warn('sum type `$sum_decl.name` $no_pub_in_main_warning', sum_decl.pos)
}
} else if type_decl is ast.FnTypeDecl {
fn_decl := type_decl as ast.FnTypeDecl
} else if it is ast.FnTypeDecl {
fn_decl := it as ast.FnTypeDecl
if fn_decl.is_pub {
c.warn('type alias `$fn_decl.name` $no_pub_in_main_warning', fn_decl.pos)
}

View File

@ -1227,7 +1227,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
}
fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
match val {
// TODO: remove sponge
tmp_val := val
match tmp_val {
ast.Ident {
mut has_var := false
for lx in left {
@ -1987,6 +1989,10 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
g.write('\t$it_type* it = ($it_type*)')
g.expr(node.cond)
g.writeln('.obj; // ST it')
if node.var_name.len > 0 {
// for now we just copy it
g.writeln('\t$it_type* $node.var_name = it;')
}
}
else {
verror('match sum type')

View File

@ -559,8 +559,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
match expr {
ast.IntegerLiteral {
// `foo(2)` => `mov edi,0x2`
int_lit := expr as ast.IntegerLiteral
g.mov(fn_arg_registers[i], int_lit.val.int())
g.mov(fn_arg_registers[i], it.val.int())
}
ast.Ident {
// `foo(x)` => `mov edi,DWORD PTR [rbp-0x8]`

View File

@ -99,6 +99,11 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
cond_pos := p.tok.position()
cond := p.expr(0)
p.inside_match = false
mut var_name := ''
if p.tok.kind == .key_as {
p.next()
var_name = p.check_name()
}
p.check(.lcbr)
mut branches := []ast.MatchBranch{}
for {
@ -114,6 +119,20 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
} else if p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot) &&
(p.tok.lit in table.builtin_type_names || (p.tok.lit[0].is_capital() && !p.tok.lit.is_upper()) ||
p.peek_tok.kind == .dot) {
if var_name.len == 0 {
match cond {
ast.Ident {
// shadow match cond variable
var_name = it.name
}
// ast.SelectorExpr {
// p.error('expecting `as` (eg. `match user.attribute as user_attr`) when matching struct fields')
// }
else {
// p.error('only variables can be used in sum types matches')
}
}
}
// Sum type match
typ := p.parse_type()
exprs << ast.Type{
@ -126,32 +145,23 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
is_used: true
is_mut: is_mut
})
if var_name.len > 0 {
// Register shadow variable or `as` variable with actual type
p.scope.register(var_name, ast.Var{
name: var_name
typ: typ.to_ptr()
pos: cond_pos
is_used: true
is_mut: is_mut
})
}
// TODO
if p.tok.kind == .comma {
p.next()
p.parse_type()
}
is_sum_type = true
// Make sure a variable used for the sum type match
mut var_name := ''
match cond {
ast.Ident {
var_name = it.name
}
else {
// p.error('only variables can be used in sum types matches')
}
}
if var_name != '' {
// Register a shadow variable with the actual type
// (this replaces the old `it`)
// TODO doesn't work right now (fixed, uncomment when merging)
// p.scope.register(var_name, ast.Var{
// name: var_name
// typ: typ.to_ptr()
// })
// println(var_name)
}
} else {
// Expression match
for {
@ -200,5 +210,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
is_sum_type: is_sum_type
pos: pos
is_mut: is_mut
var_name: var_name
}
}

View File

@ -166,6 +166,11 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
node = p.index_expr(node)
p.is_stmt_ident = is_stmt_ident
} else if p.tok.kind == .key_as {
// sum type match `match x as alias` so return early
if p.inside_match {
return node
}
// sum type as cast `x := SumType as Variant`
pos := p.tok.position()
p.next()
typ = p.parse_type()