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) {
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -2693,32 +2693,38 @@ 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 {
|
||||||
is_last := j == node.branches.len - 1
|
mut sumtype_index := 0
|
||||||
if branch.is_else || (node.is_expr && is_last) {
|
// iterates through all types in sumtype branches
|
||||||
if node.branches.len > 1 {
|
// it loops only once for other types
|
||||||
if is_expr {
|
for {
|
||||||
// TODO too many branches. maybe separate ?: matches
|
is_last := j == node.branches.len - 1
|
||||||
g.write(' : ')
|
if branch.is_else || (node.is_expr && is_last) {
|
||||||
} else {
|
if node.branches.len > 1 {
|
||||||
g.writeln(' else {')
|
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 {
|
} else {
|
||||||
g.write('if (')
|
if j > 0 {
|
||||||
}
|
if is_expr {
|
||||||
for i, expr in branch.exprs {
|
g.write(' : ')
|
||||||
if node.is_sum_type {
|
} 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)
|
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,79 +2736,85 @@ 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 {
|
||||||
if (expr as ast.StringLiteral).val == '' {
|
for i, expr in branch.exprs {
|
||||||
g.write('${cond_var}.len == 0')
|
if i > 0 {
|
||||||
} else {
|
g.write(' || ')
|
||||||
g.write('string_eq(')
|
}
|
||||||
g.write(cond_var)
|
if type_sym.kind == .string {
|
||||||
g.write(', ')
|
if (expr as ast.StringLiteral).val == '' {
|
||||||
g.expr(expr)
|
g.write('${cond_var}.len == 0')
|
||||||
g.write(')')
|
} else {
|
||||||
}
|
g.write('string_eq(')
|
||||||
} else if expr is ast.RangeExpr {
|
g.write(cond_var)
|
||||||
// if type is unsigned and low is 0, check is unneeded
|
g.write(', ')
|
||||||
mut skip_low := false
|
g.expr(expr)
|
||||||
if expr.low is ast.IntegerLiteral as expr_low {
|
g.write(')')
|
||||||
if node.cond_type in [table.u16_type, table.u32_type, table.u64_type] &&
|
}
|
||||||
expr_low.val == '0' {
|
} else if expr is ast.RangeExpr {
|
||||||
skip_low = true
|
// 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 {
|
if is_expr {
|
||||||
g.write(cond_var)
|
g.write(') ? ')
|
||||||
g.write(' >= ')
|
|
||||||
g.expr(expr.low)
|
|
||||||
g.write(' && ')
|
|
||||||
}
|
|
||||||
g.write(cond_var)
|
|
||||||
g.write(' <= ')
|
|
||||||
g.expr(expr.high)
|
|
||||||
g.write(')')
|
|
||||||
} else {
|
} else {
|
||||||
g.write(cond_var)
|
g.writeln(') {')
|
||||||
g.write(' == ')
|
|
||||||
g.expr(expr)
|
|
||||||
}
|
|
||||||
if i < branch.exprs.len - 1 {
|
|
||||||
g.write(' || ')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_expr {
|
// g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/')
|
||||||
g.write(') ? ')
|
if node.is_sum_type && branch.exprs.len > 0 {
|
||||||
} else {
|
if !node.is_expr {
|
||||||
g.writeln(') {')
|
// Use the nodes in the expr to generate `it` variable.
|
||||||
}
|
type_expr := branch.exprs[sumtype_index]
|
||||||
}
|
if type_expr is ast.Type {
|
||||||
// g.writeln('/* M sum_type=$node.is_sum_type is_expr=$node.is_expr exp_type=${g.typ(node.expected_type)}*/')
|
it_type := g.typ(type_expr.typ)
|
||||||
if node.is_sum_type && branch.exprs.len > 0 && !node.is_expr {
|
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||||
// The first node in expr is an ast.Type
|
g.write('\t$it_type* it = ($it_type*)')
|
||||||
// Use it to generate `it` variable.
|
g.write(cond_var)
|
||||||
first_expr := branch.exprs[0]
|
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||||
match first_expr {
|
g.write(dot_or_ptr)
|
||||||
ast.Type {
|
g.writeln('_object; // ST it')
|
||||||
it_type := g.typ(first_expr.typ)
|
if node.var_name.len > 0 {
|
||||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
// for now we just copy it
|
||||||
g.write('\t$it_type* it = ($it_type*)')
|
g.writeln('\t$it_type* $node.var_name = it;')
|
||||||
g.write(cond_var)
|
}
|
||||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
} else {
|
||||||
g.write(dot_or_ptr)
|
verror('match sum type')
|
||||||
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 {
|
sumtype_index++
|
||||||
verror('match sum type')
|
}
|
||||||
}
|
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 {
|
if is_expr {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue