gen: access fields in multi-type sumtype match (#6541)
parent
7b034a54e3
commit
677b0ba2d2
|
@ -97,14 +97,7 @@ fn (mut f Fmt) find_comment(line_nr int) {
|
|||
pub fn (mut f Fmt) write(s string) {
|
||||
if !f.buffering {
|
||||
if f.indent > 0 && f.empty_line {
|
||||
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')
|
||||
}
|
||||
}
|
||||
f.write_indent()
|
||||
f.line_len += f.indent * 4
|
||||
}
|
||||
f.out.write(s)
|
||||
|
@ -133,8 +126,7 @@ pub fn (mut f Fmt) writeln(s string) {
|
|||
f.precedences = []int{}
|
||||
}
|
||||
if f.indent > 0 && f.empty_line {
|
||||
// println(f.indent.str() + s)
|
||||
f.out.write(tabs[f.indent])
|
||||
f.write_indent()
|
||||
}
|
||||
f.out.writeln(if empty_fifo {
|
||||
''
|
||||
|
@ -145,6 +137,17 @@ pub fn (mut f Fmt) writeln(s string) {
|
|||
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
|
||||
// only prevents line breaks if everything fits in max_len[last] by increasing
|
||||
// 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] == ` ` {
|
||||
f.out.go_back(1)
|
||||
}
|
||||
f.write('\n' + tabs[f.indent + if add_indent {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}])
|
||||
f.write('\n')
|
||||
if add_indent {
|
||||
f.indent++
|
||||
}
|
||||
f.write_indent()
|
||||
if add_indent {
|
||||
f.indent--
|
||||
}
|
||||
f.line_len = 0
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -2693,32 +2693,38 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
|||
g.expr(node.cond)
|
||||
g.writeln(';')
|
||||
g.write(cur_line)
|
||||
// TODO refactor, there are far too many indents
|
||||
for j, branch in node.branches {
|
||||
is_last := j == node.branches.len - 1
|
||||
if branch.is_else || (node.is_expr && is_last) {
|
||||
if node.branches.len > 1 {
|
||||
if is_expr {
|
||||
// TODO too many branches. maybe separate ?: matches
|
||||
g.write(' : ')
|
||||
} else {
|
||||
g.writeln(' else {')
|
||||
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
|
||||
if branch.is_else || (node.is_expr && is_last) {
|
||||
if node.branches.len > 1 {
|
||||
if is_expr {
|
||||
// TODO too many branches. maybe separate ?: matches
|
||||
g.write(' : ')
|
||||
} else {
|
||||
g.writeln(' else {')
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if j > 0 {
|
||||
if is_expr {
|
||||
g.write(' : ')
|
||||
} else {
|
||||
g.write(' else ')
|
||||
}
|
||||
}
|
||||
if is_expr {
|
||||
g.write('(')
|
||||
} else {
|
||||
g.write('if (')
|
||||
}
|
||||
for i, expr in branch.exprs {
|
||||
if node.is_sum_type {
|
||||
if j > 0 {
|
||||
if is_expr {
|
||||
g.write(' : ')
|
||||
} else {
|
||||
g.write(' else ')
|
||||
}
|
||||
}
|
||||
if is_expr {
|
||||
g.write('(')
|
||||
} else {
|
||||
g.write('if (')
|
||||
}
|
||||
if node.is_sum_type && branch.exprs.len > 0 {
|
||||
// the multiple expressions of sumtypes are treated by the immediate `for` loop
|
||||
// TODO move sumtype match to there own function
|
||||
g.write(cond_var)
|
||||
sym := g.table.get_type_symbol(node.cond_type)
|
||||
// branch_sym := g.table.get_type_symbol(branch.typ)
|
||||
|
@ -2730,79 +2736,85 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
|||
// g.write('._interface_idx == _${sym.name}_${branch_sym} ')
|
||||
g.write('._interface_idx == ')
|
||||
}
|
||||
g.expr(expr)
|
||||
} else if type_sym.kind == .string {
|
||||
if (expr as ast.StringLiteral).val == '' {
|
||||
g.write('${cond_var}.len == 0')
|
||||
} else {
|
||||
g.write('string_eq(')
|
||||
g.write(cond_var)
|
||||
g.write(', ')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
} else if expr is ast.RangeExpr {
|
||||
// if type is unsigned and low is 0, check is unneeded
|
||||
mut skip_low := false
|
||||
if expr.low is ast.IntegerLiteral as expr_low {
|
||||
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] &&
|
||||
expr_low.val == '0' {
|
||||
skip_low = true
|
||||
g.expr(branch.exprs[sumtype_index])
|
||||
} else {
|
||||
for i, expr in branch.exprs {
|
||||
if i > 0 {
|
||||
g.write(' || ')
|
||||
}
|
||||
if type_sym.kind == .string {
|
||||
if (expr as ast.StringLiteral).val == '' {
|
||||
g.write('${cond_var}.len == 0')
|
||||
} else {
|
||||
g.write('string_eq(')
|
||||
g.write(cond_var)
|
||||
g.write(', ')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
} else if expr is ast.RangeExpr {
|
||||
// if type is unsigned and low is 0, check is unneeded
|
||||
mut skip_low := false
|
||||
if expr.low is ast.IntegerLiteral as expr_low {
|
||||
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] &&
|
||||
expr_low.val == '0' {
|
||||
skip_low = true
|
||||
}
|
||||
}
|
||||
g.write('(')
|
||||
if !skip_low {
|
||||
g.write(cond_var)
|
||||
g.write(' >= ')
|
||||
g.expr(expr.low)
|
||||
g.write(' && ')
|
||||
}
|
||||
g.write(cond_var)
|
||||
g.write(' <= ')
|
||||
g.expr(expr.high)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.write(cond_var)
|
||||
g.write(' == ')
|
||||
g.expr(expr)
|
||||
}
|
||||
}
|
||||
g.write('(')
|
||||
if !skip_low {
|
||||
g.write(cond_var)
|
||||
g.write(' >= ')
|
||||
g.expr(expr.low)
|
||||
g.write(' && ')
|
||||
}
|
||||
g.write(cond_var)
|
||||
g.write(' <= ')
|
||||
g.expr(expr.high)
|
||||
g.write(')')
|
||||
}
|
||||
if is_expr {
|
||||
g.write(') ? ')
|
||||
} else {
|
||||
g.write(cond_var)
|
||||
g.write(' == ')
|
||||
g.expr(expr)
|
||||
}
|
||||
if i < branch.exprs.len - 1 {
|
||||
g.write(' || ')
|
||||
g.writeln(') {')
|
||||
}
|
||||
}
|
||||
if is_expr {
|
||||
g.write(') ? ')
|
||||
} else {
|
||||
g.writeln(') {')
|
||||
}
|
||||
}
|
||||
// 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 {
|
||||
// The first node in expr is an ast.Type
|
||||
// Use it to generate `it` variable.
|
||||
first_expr := branch.exprs[0]
|
||||
match first_expr {
|
||||
ast.Type {
|
||||
it_type := g.typ(first_expr.typ)
|
||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||
g.write('\t$it_type* it = ($it_type*)')
|
||||
g.write(cond_var)
|
||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||
g.write(dot_or_ptr)
|
||||
g.writeln('_object; // ST it')
|
||||
if node.var_name.len > 0 {
|
||||
// for now we just copy it
|
||||
g.writeln('\t$it_type* $node.var_name = it;')
|
||||
// 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 {
|
||||
if !node.is_expr {
|
||||
// Use the nodes in the expr to generate `it` variable.
|
||||
type_expr := branch.exprs[sumtype_index]
|
||||
if type_expr is ast.Type {
|
||||
it_type := g.typ(type_expr.typ)
|
||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||
g.write('\t$it_type* it = ($it_type*)')
|
||||
g.write(cond_var)
|
||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||
g.write(dot_or_ptr)
|
||||
g.writeln('_object; // 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')
|
||||
}
|
||||
}
|
||||
else {
|
||||
verror('match sum type')
|
||||
}
|
||||
sumtype_index++
|
||||
}
|
||||
g.stmts(branch.stmts)
|
||||
if g.inside_ternary == 0 && node.branches.len > 1 {
|
||||
g.write('}')
|
||||
}
|
||||
if !node.is_sum_type || branch.exprs.len == 0 || sumtype_index == branch.exprs.len {
|
||||
break
|
||||
}
|
||||
}
|
||||
g.stmts(branch.stmts)
|
||||
if g.inside_ternary == 0 && node.branches.len > 1 {
|
||||
g.write('}')
|
||||
}
|
||||
}
|
||||
if is_expr {
|
||||
|
|
|
@ -562,10 +562,6 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
|||
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) {
|
||||
sym := p.table.get_type_symbol(typ)
|
||||
if sym.kind !in [.array, .struct_, .map, .placeholder, .sum_type] && !typ.is_ptr() {
|
||||
|
|
|
@ -269,13 +269,6 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
|
||||
fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||
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() }
|
||||
p.expr_mod = ''
|
||||
// sym := p.table.get_type_symbol(typ)
|
||||
|
|
|
@ -189,12 +189,11 @@ type NATOAlphabet = Alfa | Bravo | Charlie
|
|||
|
||||
fn test_match_sum_type_multiple_type() {
|
||||
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 {
|
||||
Alfa, Bravo {
|
||||
assert l.char == `a`
|
||||
assert l.letter() == `a`
|
||||
// TODO make methods work
|
||||
// assert l.letter() == `a`
|
||||
}
|
||||
Charlie {
|
||||
assert false
|
||||
|
|
Loading…
Reference in New Issue