parser/checker/gen: match shaddow cond var & as support: p1
parent
7be952605b
commit
68143b7b22
|
@ -442,6 +442,7 @@ pub:
|
||||||
branches []MatchBranch
|
branches []MatchBranch
|
||||||
pos token.Position
|
pos token.Position
|
||||||
is_mut bool // `match mut ast_node {`
|
is_mut bool // `match mut ast_node {`
|
||||||
|
var_name string
|
||||||
pub mut:
|
pub mut:
|
||||||
is_expr bool // returns a value
|
is_expr bool // returns a value
|
||||||
return_type table.Type
|
return_type table.Type
|
||||||
|
|
|
@ -126,22 +126,33 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: remove sponge - put back match
|
||||||
if !needs_braces {
|
if !needs_braces {
|
||||||
mut sub_expr := lit.exprs[i]
|
mut sub_expr := lit.exprs[i]
|
||||||
for {
|
for {
|
||||||
match sub_expr {
|
if sub_expr is Ident { break }
|
||||||
Ident {
|
else if sub_expr is SelectorExpr {
|
||||||
break
|
se := sub_expr as SelectorExpr
|
||||||
}
|
sub_expr = se.expr
|
||||||
SelectorExpr {
|
continue
|
||||||
sub_expr = it.expr
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
needs_braces = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
needs_braces = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// match sub_expr {
|
||||||
|
// Ident {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// SelectorExpr {
|
||||||
|
// sub_expr = it.expr
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// needs_braces = true
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needs_fspec {
|
if needs_fspec {
|
||||||
|
|
|
@ -93,13 +93,15 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// sum type
|
// sum type
|
||||||
if got_type_sym.kind == .sum_type {
|
// TODO: there is a bug when casting sumtype the other way if its pointer
|
||||||
sum_info := got_type_sym.info as table.SumType
|
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
|
||||||
// TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
|
// if got_type_sym.kind == .sum_type {
|
||||||
if expected.set_nr_muls(0) in sum_info.variants {
|
// sum_info := got_type_sym.info as table.SumType
|
||||||
return true
|
// // 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 {
|
if exp_type_sym.kind == .sum_type {
|
||||||
sum_info := exp_type_sym.info as table.SumType
|
sum_info := exp_type_sym.info as table.SumType
|
||||||
// TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
|
// TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
|
||||||
|
|
|
@ -170,19 +170,19 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.TypeDecl {
|
ast.TypeDecl {
|
||||||
type_decl := stmt as ast.TypeDecl
|
// type_decl := stmt as ast.TypeDecl
|
||||||
if type_decl is ast.AliasTypeDecl {
|
if it is ast.AliasTypeDecl {
|
||||||
alias_decl := type_decl as ast.AliasTypeDecl
|
alias_decl := it as ast.AliasTypeDecl
|
||||||
if alias_decl.is_pub {
|
if alias_decl.is_pub {
|
||||||
c.warn('type alias `$alias_decl.name` $no_pub_in_main_warning', alias_decl.pos)
|
c.warn('type alias `$alias_decl.name` $no_pub_in_main_warning', alias_decl.pos)
|
||||||
}
|
}
|
||||||
} else if type_decl is ast.SumTypeDecl {
|
} else if it is ast.SumTypeDecl {
|
||||||
sum_decl := type_decl as ast.SumTypeDecl
|
sum_decl := it as ast.SumTypeDecl
|
||||||
if sum_decl.is_pub {
|
if sum_decl.is_pub {
|
||||||
c.warn('sum type `$sum_decl.name` $no_pub_in_main_warning', sum_decl.pos)
|
c.warn('sum type `$sum_decl.name` $no_pub_in_main_warning', sum_decl.pos)
|
||||||
}
|
}
|
||||||
} else if type_decl is ast.FnTypeDecl {
|
} else if it is ast.FnTypeDecl {
|
||||||
fn_decl := type_decl as ast.FnTypeDecl
|
fn_decl := it as ast.FnTypeDecl
|
||||||
if fn_decl.is_pub {
|
if fn_decl.is_pub {
|
||||||
c.warn('type alias `$fn_decl.name` $no_pub_in_main_warning', fn_decl.pos)
|
c.warn('type alias `$fn_decl.name` $no_pub_in_main_warning', fn_decl.pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
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 {
|
ast.Ident {
|
||||||
mut has_var := false
|
mut has_var := false
|
||||||
for lx in left {
|
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.write('\t$it_type* it = ($it_type*)')
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
g.writeln('.obj; // ST it')
|
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 {
|
else {
|
||||||
verror('match sum type')
|
verror('match sum type')
|
||||||
|
|
|
@ -559,8 +559,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
|
||||||
match expr {
|
match expr {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
// `foo(2)` => `mov edi,0x2`
|
// `foo(2)` => `mov edi,0x2`
|
||||||
int_lit := expr as ast.IntegerLiteral
|
g.mov(fn_arg_registers[i], it.val.int())
|
||||||
g.mov(fn_arg_registers[i], int_lit.val.int())
|
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
// `foo(x)` => `mov edi,DWORD PTR [rbp-0x8]`
|
// `foo(x)` => `mov edi,DWORD PTR [rbp-0x8]`
|
||||||
|
|
|
@ -99,6 +99,11 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
cond_pos := p.tok.position()
|
cond_pos := p.tok.position()
|
||||||
cond := p.expr(0)
|
cond := p.expr(0)
|
||||||
p.inside_match = false
|
p.inside_match = false
|
||||||
|
mut var_name := ''
|
||||||
|
if p.tok.kind == .key_as {
|
||||||
|
p.next()
|
||||||
|
var_name = p.check_name()
|
||||||
|
}
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut branches := []ast.MatchBranch{}
|
mut branches := []ast.MatchBranch{}
|
||||||
for {
|
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) &&
|
} 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.tok.lit in table.builtin_type_names || (p.tok.lit[0].is_capital() && !p.tok.lit.is_upper()) ||
|
||||||
p.peek_tok.kind == .dot) {
|
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
|
// Sum type match
|
||||||
typ := p.parse_type()
|
typ := p.parse_type()
|
||||||
exprs << ast.Type{
|
exprs << ast.Type{
|
||||||
|
@ -126,32 +145,23 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
is_used: true
|
is_used: true
|
||||||
is_mut: is_mut
|
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
|
// TODO
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
p.next()
|
p.next()
|
||||||
p.parse_type()
|
p.parse_type()
|
||||||
}
|
}
|
||||||
is_sum_type = true
|
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 {
|
} else {
|
||||||
// Expression match
|
// Expression match
|
||||||
for {
|
for {
|
||||||
|
@ -200,5 +210,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
is_sum_type: is_sum_type
|
is_sum_type: is_sum_type
|
||||||
pos: pos
|
pos: pos
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
|
var_name: var_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,11 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
node = p.index_expr(node)
|
node = p.index_expr(node)
|
||||||
p.is_stmt_ident = is_stmt_ident
|
p.is_stmt_ident = is_stmt_ident
|
||||||
} else if p.tok.kind == .key_as {
|
} 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()
|
pos := p.tok.position()
|
||||||
p.next()
|
p.next()
|
||||||
typ = p.parse_type()
|
typ = p.parse_type()
|
||||||
|
|
Loading…
Reference in New Issue