gen: access fields in multi-type sumtype match (#6541)

pull/6548/head
Enzo 2020-10-03 11:19:43 +02:00 committed by GitHub
parent 7b034a54e3
commit 677b0ba2d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 117 deletions

View File

@ -97,14 +97,7 @@ fn (mut f Fmt) find_comment(line_nr int) {
pub fn (mut f Fmt) write(s string) { pub fn (mut f Fmt) write(s string) {
if !f.buffering { if !f.buffering {
if f.indent > 0 && f.empty_line { if f.indent > 0 && f.empty_line {
if f.indent < tabs.len { f.write_indent()
f.out.write(tabs[f.indent])
} else {
// too many indents, do it the slow way:
for _ in 0 .. f.indent {
f.out.write('\t')
}
}
f.line_len += f.indent * 4 f.line_len += f.indent * 4
} }
f.out.write(s) f.out.write(s)
@ -133,8 +126,7 @@ pub fn (mut f Fmt) writeln(s string) {
f.precedences = []int{} f.precedences = []int{}
} }
if f.indent > 0 && f.empty_line { if f.indent > 0 && f.empty_line {
// println(f.indent.str() + s) f.write_indent()
f.out.write(tabs[f.indent])
} }
f.out.writeln(if empty_fifo { f.out.writeln(if empty_fifo {
'' ''
@ -145,6 +137,17 @@ pub fn (mut f Fmt) writeln(s string) {
f.line_len = 0 f.line_len = 0
} }
fn (mut f Fmt) write_indent() {
if f.indent < tabs.len {
f.out.write(tabs[f.indent])
} else {
// too many indents, do it the slow way:
for _ in 0 .. f.indent {
f.out.write('\t')
}
}
}
// adjustments that can only be done after full line is processed. For now // adjustments that can only be done after full line is processed. For now
// only prevents line breaks if everything fits in max_len[last] by increasing // only prevents line breaks if everything fits in max_len[last] by increasing
// penalties to maximum // penalties to maximum
@ -1129,11 +1132,14 @@ pub fn (mut f Fmt) wrap_long_line(penalty int, add_indent bool) bool {
if f.out.buf[f.out.buf.len - 1] == ` ` { if f.out.buf[f.out.buf.len - 1] == ` ` {
f.out.go_back(1) f.out.go_back(1)
} }
f.write('\n' + tabs[f.indent + if add_indent { f.write('\n')
1 if add_indent {
} else { f.indent++
0 }
}]) f.write_indent()
if add_indent {
f.indent--
}
f.line_len = 0 f.line_len = 0
return true return true
} }

View File

@ -2693,7 +2693,12 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
g.expr(node.cond) g.expr(node.cond)
g.writeln(';') g.writeln(';')
g.write(cur_line) g.write(cur_line)
// TODO refactor, there are far too many indents
for j, branch in node.branches { for j, branch in node.branches {
mut sumtype_index := 0
// iterates through all types in sumtype branches
// it loops only once for other types
for {
is_last := j == node.branches.len - 1 is_last := j == node.branches.len - 1
if branch.is_else || (node.is_expr && is_last) { if branch.is_else || (node.is_expr && is_last) {
if node.branches.len > 1 { if node.branches.len > 1 {
@ -2717,8 +2722,9 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
} else { } else {
g.write('if (') g.write('if (')
} }
for i, expr in branch.exprs { if node.is_sum_type && branch.exprs.len > 0 {
if node.is_sum_type { // the multiple expressions of sumtypes are treated by the immediate `for` loop
// TODO move sumtype match to there own function
g.write(cond_var) g.write(cond_var)
sym := g.table.get_type_symbol(node.cond_type) sym := g.table.get_type_symbol(node.cond_type)
// branch_sym := g.table.get_type_symbol(branch.typ) // branch_sym := g.table.get_type_symbol(branch.typ)
@ -2730,8 +2736,13 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
// g.write('._interface_idx == _${sym.name}_${branch_sym} ') // g.write('._interface_idx == _${sym.name}_${branch_sym} ')
g.write('._interface_idx == ') g.write('._interface_idx == ')
} }
g.expr(expr) g.expr(branch.exprs[sumtype_index])
} else if type_sym.kind == .string { } else {
for i, expr in branch.exprs {
if i > 0 {
g.write(' || ')
}
if type_sym.kind == .string {
if (expr as ast.StringLiteral).val == '' { if (expr as ast.StringLiteral).val == '' {
g.write('${cond_var}.len == 0') g.write('${cond_var}.len == 0')
} else { } else {
@ -2766,8 +2777,6 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
g.write(' == ') g.write(' == ')
g.expr(expr) g.expr(expr)
} }
if i < branch.exprs.len - 1 {
g.write(' || ')
} }
} }
if is_expr { if is_expr {
@ -2777,13 +2786,12 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
} }
} }
// g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/') // g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/')
if node.is_sum_type && branch.exprs.len > 0 && !node.is_expr { if node.is_sum_type && branch.exprs.len > 0 {
// The first node in expr is an ast.Type if !node.is_expr {
// Use it to generate `it` variable. // Use the nodes in the expr to generate `it` variable.
first_expr := branch.exprs[0] type_expr := branch.exprs[sumtype_index]
match first_expr { if type_expr is ast.Type {
ast.Type { it_type := g.typ(type_expr.typ)
it_type := g.typ(first_expr.typ)
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it') // g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
g.write('\t$it_type* it = ($it_type*)') g.write('\t$it_type* it = ($it_type*)')
g.write(cond_var) g.write(cond_var)
@ -2794,16 +2802,20 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
// for now we just copy it // for now we just copy it
g.writeln('\t$it_type* $node.var_name = it;') g.writeln('\t$it_type* $node.var_name = it;')
} }
} } else {
else {
verror('match sum type') verror('match sum type')
} }
} }
sumtype_index++
} }
g.stmts(branch.stmts) g.stmts(branch.stmts)
if g.inside_ternary == 0 && node.branches.len > 1 { if g.inside_ternary == 0 && node.branches.len > 1 {
g.write('}') g.write('}')
} }
if !node.is_sum_type || branch.exprs.len == 0 || sumtype_index == branch.exprs.len {
break
}
}
} }
if is_expr { if is_expr {
g.decrement_inside_ternary() g.decrement_inside_ternary()

View File

@ -562,10 +562,6 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
return args, types_only, is_variadic return args, types_only, is_variadic
} }
fn (p &Parser) fileis(s string) bool {
return p.file_name.contains(s)
}
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) { fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
sym := p.table.get_type_symbol(typ) sym := p.table.get_type_symbol(typ)
if sym.kind !in [.array, .struct_, .map, .placeholder, .sum_type] && !typ.is_ptr() { if sym.kind !in [.array, .struct_, .map, .placeholder, .sum_type] && !typ.is_ptr() {

View File

@ -269,13 +269,6 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit { fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
first_pos := p.tok.position() first_pos := p.tok.position()
/*
defer {
if p.fileis('x.v') {
p.warn('end of struct init $short_syntax')
}
}
*/
typ := if short_syntax { table.void_type } else { p.parse_type() } typ := if short_syntax { table.void_type } else { p.parse_type() }
p.expr_mod = '' p.expr_mod = ''
// sym := p.table.get_type_symbol(typ) // sym := p.table.get_type_symbol(typ)

View File

@ -189,12 +189,11 @@ type NATOAlphabet = Alfa | Bravo | Charlie
fn test_match_sum_type_multiple_type() { fn test_match_sum_type_multiple_type() {
a := Alfa{} a := Alfa{}
// TODO This currently works because cgen takes the first type as the type of `l`
// it would fail if we `a` was of type `Bravo`
match NATOAlphabet(a) as l { match NATOAlphabet(a) as l {
Alfa, Bravo { Alfa, Bravo {
assert l.char == `a` assert l.char == `a`
assert l.letter() == `a` // TODO make methods work
// assert l.letter() == `a`
} }
Charlie { Charlie {
assert false assert false