gen: separate sumtype from classic match (#6547)
parent
2622070f14
commit
35a83464d0
|
@ -2671,17 +2671,6 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
g.inside_ternary++
|
g.inside_ternary++
|
||||||
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')
|
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')
|
||||||
}
|
}
|
||||||
type_sym := g.table.get_type_symbol(node.cond_type)
|
|
||||||
if node.is_sum_type {
|
|
||||||
g.match_sumtype_exprs << node.cond
|
|
||||||
g.match_sumtype_syms << type_sym
|
|
||||||
}
|
|
||||||
defer {
|
|
||||||
if node.is_sum_type {
|
|
||||||
g.match_sumtype_exprs.pop()
|
|
||||||
g.match_sumtype_syms.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cur_line := if is_expr {
|
cur_line := if is_expr {
|
||||||
g.empty_line = true
|
g.empty_line = true
|
||||||
g.go_before_stmt(0)
|
g.go_before_stmt(0)
|
||||||
|
@ -2693,12 +2682,101 @@ 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
|
if node.is_sum_type {
|
||||||
|
g.match_expr_sumtype(node, is_expr, cond_var)
|
||||||
|
} else {
|
||||||
|
g.match_expr_classic(node, is_expr, cond_var)
|
||||||
|
}
|
||||||
|
if is_expr {
|
||||||
|
g.decrement_inside_ternary()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string) {
|
||||||
|
type_sym := g.table.get_type_symbol(node.cond_type)
|
||||||
|
g.match_sumtype_exprs << node.cond
|
||||||
|
g.match_sumtype_syms << type_sym
|
||||||
|
defer {
|
||||||
|
g.match_sumtype_exprs.pop()
|
||||||
|
g.match_sumtype_syms.pop()
|
||||||
|
}
|
||||||
for j, branch in node.branches {
|
for j, branch in node.branches {
|
||||||
mut sumtype_index := 0
|
mut sumtype_index := 0
|
||||||
// iterates through all types in sumtype branches
|
// iterates through all types in sumtype branches
|
||||||
// it loops only once for other types
|
|
||||||
for {
|
for {
|
||||||
|
is_last := j == node.branches.len - 1
|
||||||
|
if branch.is_else || (node.is_expr && is_last) {
|
||||||
|
if is_expr {
|
||||||
|
// TODO too many branches. maybe separate ?: matches
|
||||||
|
g.write(' : ')
|
||||||
|
} else {
|
||||||
|
g.writeln(' else {')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if j > 0 || sumtype_index > 0 {
|
||||||
|
if is_expr {
|
||||||
|
g.write(' : ')
|
||||||
|
} else {
|
||||||
|
g.write(' else ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_expr {
|
||||||
|
g.write('(')
|
||||||
|
} else {
|
||||||
|
g.write('if (')
|
||||||
|
}
|
||||||
|
g.write(cond_var)
|
||||||
|
sym := g.table.get_type_symbol(node.cond_type)
|
||||||
|
// branch_sym := g.table.get_type_symbol(branch.typ)
|
||||||
|
if sym.kind == .sum_type {
|
||||||
|
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||||
|
g.write(dot_or_ptr)
|
||||||
|
g.write('typ == ')
|
||||||
|
} else if sym.kind == .interface_ {
|
||||||
|
// g.write('._interface_idx == _${sym.name}_${branch_sym} ')
|
||||||
|
g.write('._interface_idx == ')
|
||||||
|
}
|
||||||
|
g.expr(branch.exprs[sumtype_index])
|
||||||
|
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 !branch.is_else && !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 {
|
||||||
|
verror('match sum type')
|
||||||
|
}
|
||||||
|
it_type := g.typ((type_expr as ast.Type).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.stmts(branch.stmts)
|
||||||
|
if g.inside_ternary == 0 {
|
||||||
|
g.write('}')
|
||||||
|
}
|
||||||
|
sumtype_index++
|
||||||
|
if branch.exprs.len == 0 || sumtype_index == branch.exprs.len {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var string) {
|
||||||
|
type_sym := g.table.get_type_symbol(node.cond_type)
|
||||||
|
for j, branch in node.branches {
|
||||||
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 {
|
||||||
|
@ -2722,22 +2800,6 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
} else {
|
} else {
|
||||||
g.write('if (')
|
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)
|
|
||||||
if sym.kind == .sum_type {
|
|
||||||
dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' }
|
|
||||||
g.write(dot_or_ptr)
|
|
||||||
g.write('typ == ')
|
|
||||||
} else if sym.kind == .interface_ {
|
|
||||||
// g.write('._interface_idx == _${sym.name}_${branch_sym} ')
|
|
||||||
g.write('._interface_idx == ')
|
|
||||||
}
|
|
||||||
g.expr(branch.exprs[sumtype_index])
|
|
||||||
} else {
|
|
||||||
for i, expr in branch.exprs {
|
for i, expr in branch.exprs {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
g.write(' || ')
|
g.write(' || ')
|
||||||
|
@ -2778,47 +2840,16 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if is_expr {
|
if is_expr {
|
||||||
g.write(') ? ')
|
g.write(') ? ')
|
||||||
} else {
|
} else {
|
||||||
g.writeln(') {')
|
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 {
|
|
||||||
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')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
g.decrement_inside_ternary()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3008,11 +3039,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||||
fn (mut g Gen) should_write_asterisk_due_to_match_sumtype(expr ast.Expr) bool {
|
fn (mut g Gen) should_write_asterisk_due_to_match_sumtype(expr ast.Expr) bool {
|
||||||
if expr is ast.Ident {
|
if expr is ast.Ident {
|
||||||
typ := if expr.info is ast.IdentVar { (expr.info as ast.IdentVar).typ } else { (expr.info as ast.IdentFn).typ }
|
typ := if expr.info is ast.IdentVar { (expr.info as ast.IdentVar).typ } else { (expr.info as ast.IdentFn).typ }
|
||||||
return if typ.is_ptr() && g.match_sumtype_has_no_struct_and_contains(expr) {
|
return typ.is_ptr() && g.match_sumtype_has_no_struct_and_contains(expr)
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,9 @@ pub mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (f &Fn) method_equals(o &Fn) bool {
|
fn (f &Fn) method_equals(o &Fn) bool {
|
||||||
return f.params[1..].equals(o.params[1..]) &&
|
return f.params[1..].equals(o.params[1..]) && f.return_type == o.return_type && f.return_type_source_name ==
|
||||||
f.return_type == o.return_type &&
|
o.return_type_source_name && f.is_variadic == o.is_variadic && f.language == o.language &&
|
||||||
f.return_type_source_name == o.return_type_source_name &&
|
f.is_generic == o.is_generic && f.is_pub == o.is_pub && f.mod == o.mod && f.name == o.name
|
||||||
f.is_variadic == o.is_variadic &&
|
|
||||||
f.language == o.language &&
|
|
||||||
f.is_generic == o.is_generic &&
|
|
||||||
f.is_pub == o.is_pub &&
|
|
||||||
f.mod == o.mod &&
|
|
||||||
f.name == o.name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Param {
|
pub struct Param {
|
||||||
|
@ -62,11 +56,8 @@ pub:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p &Param) equals(o &Param) bool {
|
fn (p &Param) equals(o &Param) bool {
|
||||||
return p.name == o.name
|
return p.name == o.name && p.is_mut == o.is_mut && p.typ == o.typ && p.type_source_name ==
|
||||||
&& p.is_mut == o.is_mut
|
o.type_source_name && p.is_hidden == o.is_hidden
|
||||||
&& p.typ == o.typ
|
|
||||||
&& p.type_source_name == o.type_source_name
|
|
||||||
&& p.is_hidden == o.is_hidden
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p []Param) equals(o []Param) bool {
|
fn (p []Param) equals(o []Param) bool {
|
||||||
|
|
|
@ -165,6 +165,20 @@ fn test_sum_type_name() {
|
||||||
assert f(a) == 'A1'
|
assert f(a) == 'A1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn f_else(s Sum) string {
|
||||||
|
match s {
|
||||||
|
A1 { return typeof(s) }
|
||||||
|
else { return '' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_sum_type_else() {
|
||||||
|
a := A1{
|
||||||
|
pos: 22
|
||||||
|
}
|
||||||
|
assert f_else(a) == 'A1'
|
||||||
|
}
|
||||||
|
|
||||||
struct Alfa {
|
struct Alfa {
|
||||||
char rune = `a`
|
char rune = `a`
|
||||||
}
|
}
|
||||||
|
@ -183,11 +197,13 @@ fn (b Bravo) letter() rune {
|
||||||
return b.char
|
return b.char
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Charlie {}
|
struct Charlie {
|
||||||
|
char rune = `c`
|
||||||
|
}
|
||||||
|
|
||||||
type NATOAlphabet = Alfa | Bravo | Charlie
|
type NATOAlphabet = Alfa | Bravo | Charlie
|
||||||
|
|
||||||
fn test_match_sum_type_multiple_type() {
|
fn test_match_sumtype_multiple_types() {
|
||||||
a := Alfa{}
|
a := Alfa{}
|
||||||
match NATOAlphabet(a) as l {
|
match NATOAlphabet(a) as l {
|
||||||
Alfa, Bravo {
|
Alfa, Bravo {
|
||||||
|
@ -199,4 +215,10 @@ fn test_match_sum_type_multiple_type() {
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// test one branch
|
||||||
|
match NATOAlphabet(a) as l {
|
||||||
|
Alfa, Bravo, Charlie {
|
||||||
|
assert l.char == `a`
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue