cgen: split up array_init() (#14178)

yuyi 2022-04-27 01:58:47 +08:00 committed by Jef Roosens
parent 07d465cbaa
commit 8a75d68421
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
1 changed files with 189 additions and 178 deletions

View File

@ -22,182 +22,165 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
array_styp = g.typ(array_type.typ) array_styp = g.typ(array_type.typ)
g.write('HEAP($array_styp, ') g.write('HEAP($array_styp, ')
} }
len := node.exprs.len
if array_type.unaliased_sym.kind == .array_fixed { if array_type.unaliased_sym.kind == .array_fixed {
if node.has_it { g.fixed_array_init(node, array_type)
g.inside_lambda = true } else if len == 0 {
tmp := g.new_tmp_var() // `[]int{len: 6, cap:10, init:22}`
mut s := g.go_before_stmt(0) g.array_init_with_fields(node, elem_type, is_amp, shared_styp)
s_ends_with_ln := s.ends_with('\n') } else {
s = s.trim_space() // `[1, 2, 3]`
ret_typ := g.typ(node.typ) elem_styp := g.typ(elem_type.typ)
elem_typ := g.typ(node.elem_type) noscan := g.check_noscan(elem_type.typ)
g.empty_line = true if elem_type.unaliased_sym.kind == .function {
g.write('$ret_typ $tmp =') g.write('new_array_from_c_array($len, $len, sizeof(voidptr), _MOV((voidptr[$len]){')
g.write('{') } else if g.is_empty_struct(elem_type) {
if node.has_val { g.write('new_array_from_c_array${noscan}($len, $len, sizeof(voidptr), _MOV(($elem_styp[$len]){')
for i, expr in node.exprs { } else {
if expr.is_auto_deref_var() { g.write('new_array_from_c_array${noscan}($len, $len, sizeof($elem_styp), _MOV(($elem_styp[$len]){')
g.write('*') }
} if len > 8 {
g.write('0') g.writeln('')
if i != node.exprs.len - 1 { g.write('\t\t')
g.write(', ') }
} for i, expr in node.exprs {
} if node.expr_types[i] == ast.string_type && expr !is ast.StringLiteral
} else if node.has_default { && expr !is ast.StringInterLiteral {
g.write('0') g.write('string_clone(')
info := array_type.unaliased_sym.info as ast.ArrayFixed g.expr(expr)
for _ in 1 .. info.size { g.write(')')
} else {
g.expr_with_cast(expr, node.expr_types[i], node.elem_type)
}
if i != len - 1 {
if i > 0 && i & 7 == 0 { // i > 0 && i % 8 == 0
g.writeln(',')
g.write('\t\t')
} else {
g.write(', ') g.write(', ')
g.write('0')
} }
} else {
g.write('0')
} }
g.write('}')
g.writeln(';')
g.writeln('{')
g.indent++
g.writeln('$elem_typ* pelem = ($elem_typ*)$tmp;')
g.writeln('int _len = (int)sizeof($tmp) / sizeof($elem_typ);')
g.writeln('for(int it=0; it<_len; it++, pelem++) {')
g.indent++
g.write('*pelem = ')
g.expr(node.default_expr)
g.writeln(';')
g.indent--
g.writeln('}')
g.indent--
g.writeln('}')
if s_ends_with_ln {
g.writeln(s)
} else {
g.write(s)
}
g.write(tmp)
g.inside_lambda = false
return
} }
need_tmp_var := g.inside_call && !g.inside_struct_init && node.exprs.len == 0 g.write('}))')
mut stmt_str := '' if g.is_shared {
mut tmp_var := '' g.write('}, sizeof($shared_styp))')
if need_tmp_var { } else if is_amp {
tmp_var = g.new_tmp_var() g.write(')')
stmt_str = g.go_before_stmt(0)
ret_typ := g.typ(node.typ)
g.empty_line = true
g.write('$ret_typ $tmp_var = ')
} }
}
}
fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type) {
if node.has_it {
g.inside_lambda = true
tmp := g.new_tmp_var()
mut s := g.go_before_stmt(0)
s_ends_with_ln := s.ends_with('\n')
s = s.trim_space()
ret_typ := g.typ(node.typ)
elem_typ := g.typ(node.elem_type)
g.empty_line = true
g.write('$ret_typ $tmp =')
g.write('{') g.write('{')
if node.has_val { if node.has_val {
for i, expr in node.exprs { for i, expr in node.exprs {
if expr.is_auto_deref_var() { if expr.is_auto_deref_var() {
g.write('*') g.write('*')
} }
g.expr(expr) g.write('0')
if i != node.exprs.len - 1 { if i != node.exprs.len - 1 {
g.write(', ') g.write(', ')
} }
} }
} else if node.has_default { } else if node.has_default {
g.expr(node.default_expr) g.write('0')
info := array_type.unaliased_sym.info as ast.ArrayFixed info := array_type.unaliased_sym.info as ast.ArrayFixed
for _ in 1 .. info.size { for _ in 1 .. info.size {
g.write(', ') g.write(', ')
g.expr(node.default_expr) g.write('0')
} }
} else { } else {
g.write('0') g.write('0')
} }
g.write('}') g.write('}')
if need_tmp_var { g.writeln(';')
g.writeln(';') g.writeln('{')
g.write(stmt_str) g.indent++
g.write(tmp_var) g.writeln('$elem_typ* pelem = ($elem_typ*)$tmp;')
g.writeln('int _len = (int)sizeof($tmp) / sizeof($elem_typ);')
g.writeln('for(int it=0; it<_len; it++, pelem++) {')
g.indent++
g.write('*pelem = ')
g.expr(node.default_expr)
g.writeln(';')
g.indent--
g.writeln('}')
g.indent--
g.writeln('}')
if s_ends_with_ln {
g.writeln(s)
} else {
g.write(s)
} }
g.write(tmp)
g.inside_lambda = false
return return
} }
need_tmp_var := g.inside_call && !g.inside_struct_init && node.exprs.len == 0
mut stmt_str := ''
mut tmp_var := ''
if need_tmp_var {
tmp_var = g.new_tmp_var()
stmt_str = g.go_before_stmt(0)
ret_typ := g.typ(node.typ)
g.empty_line = true
g.write('$ret_typ $tmp_var = ')
}
g.write('{')
if node.has_val {
for i, expr in node.exprs {
if expr.is_auto_deref_var() {
g.write('*')
}
g.expr(expr)
if i != node.exprs.len - 1 {
g.write(', ')
}
}
} else if node.has_default {
g.expr(node.default_expr)
info := array_type.unaliased_sym.info as ast.ArrayFixed
for _ in 1 .. info.size {
g.write(', ')
g.expr(node.default_expr)
}
} else {
g.write('0')
}
g.write('}')
if need_tmp_var {
g.writeln(';')
g.write(stmt_str)
g.write(tmp_var)
}
}
// `[]int{len: 6, cap: 10, init: it * it}`
fn (mut g Gen) array_init_with_fields(node ast.ArrayInit, elem_type Type, is_amp bool, shared_styp string) {
elem_styp := g.typ(elem_type.typ) elem_styp := g.typ(elem_type.typ)
noscan := g.check_noscan(elem_type.typ) noscan := g.check_noscan(elem_type.typ)
if node.exprs.len == 0 { is_default_array := elem_type.unaliased_sym.kind == .array && node.has_default
is_default_array := elem_type.unaliased_sym.kind == .array && node.has_default is_default_map := elem_type.unaliased_sym.kind == .map && node.has_default
is_default_map := elem_type.unaliased_sym.kind == .map && node.has_default if node.has_it { // []int{len: 6, init: it * it} when variable it is used in init expression
if node.has_it { // []int{len: 6, init: it * it} when variable it is used in init expression g.inside_lambda = true
g.inside_lambda = true tmp := g.new_tmp_var()
tmp := g.new_tmp_var() mut s := g.go_before_stmt(0)
mut s := g.go_before_stmt(0) s_ends_with_ln := s.ends_with('\n')
s_ends_with_ln := s.ends_with('\n') s = s.trim_space()
s = s.trim_space() ret_typ := g.typ(node.typ)
ret_typ := g.typ(node.typ) elem_typ := g.typ(node.elem_type)
elem_typ := g.typ(node.elem_type) g.empty_line = true
g.empty_line = true g.write('$ret_typ $tmp =')
g.write('$ret_typ $tmp =')
if is_default_array {
g.write('__new_array_with_array_default${noscan}(')
} else if is_default_map {
g.write('__new_array_with_map_default${noscan}(')
} else {
g.write('__new_array_with_default${noscan}(')
}
if node.has_len {
g.expr(node.len_expr)
g.write(', ')
} else {
g.write('0, ')
}
if node.has_cap {
g.expr(node.cap_expr)
g.write(', ')
} else {
g.write('0, ')
}
if elem_type.unaliased_sym.kind == .function || g.is_empty_struct(elem_type) {
g.write('sizeof(voidptr), ')
} else {
g.write('sizeof($elem_styp), ')
}
if is_default_array {
g.write('($elem_styp[]){')
g.expr(node.default_expr)
g.write('}[0])')
} else if node.has_len && node.elem_type == ast.string_type {
g.write('&($elem_styp[]){')
g.write('_SLIT("")')
g.write('})')
} else if node.has_len && elem_type.unaliased_sym.kind in [.array, .map] {
g.write('(voidptr)&($elem_styp[]){')
g.write(g.type_default(node.elem_type))
g.write('}[0])')
} else {
g.write('0)')
}
if g.is_shared {
g.write('}, sizeof($shared_styp))')
} else if is_amp {
g.write(')')
}
g.writeln(';')
g.writeln('{')
g.indent++
g.writeln('$elem_typ* pelem = ($elem_typ*)${tmp}.data;')
g.writeln('for(int it=0; it<${tmp}.len; it++, pelem++) {')
g.indent++
g.write('*pelem = ')
g.expr(node.default_expr)
g.writeln(';')
g.indent--
g.writeln('}')
g.indent--
g.writeln('}')
if s_ends_with_ln {
g.writeln(s)
} else {
g.write(s)
}
g.write(tmp)
g.inside_lambda = false
return
}
if is_default_array { if is_default_array {
g.write('__new_array_with_array_default${noscan}(') g.write('__new_array_with_array_default${noscan}(')
} else if is_default_map { } else if is_default_map {
@ -222,14 +205,10 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
} else { } else {
g.write('sizeof($elem_styp), ') g.write('sizeof($elem_styp), ')
} }
if is_default_array || is_default_map { if is_default_array {
g.write('($elem_styp[]){') g.write('($elem_styp[]){')
g.expr(node.default_expr) g.expr(node.default_expr)
g.write('}[0])') g.write('}[0])')
} else if node.has_default {
g.write('&($elem_styp[]){')
g.expr_with_cast(node.default_expr, node.default_type, node.elem_type)
g.write('})')
} else if node.has_len && node.elem_type == ast.string_type { } else if node.has_len && node.elem_type == ast.string_type {
g.write('&($elem_styp[]){') g.write('&($elem_styp[]){')
g.write('_SLIT("")') g.write('_SLIT("")')
@ -246,39 +225,71 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
} else if is_amp { } else if is_amp {
g.write(')') g.write(')')
} }
g.writeln(';')
g.writeln('{')
g.indent++
g.writeln('$elem_typ* pelem = ($elem_typ*)${tmp}.data;')
g.writeln('for(int it=0; it<${tmp}.len; it++, pelem++) {')
g.indent++
g.write('*pelem = ')
g.expr(node.default_expr)
g.writeln(';')
g.indent--
g.writeln('}')
g.indent--
g.writeln('}')
if s_ends_with_ln {
g.writeln(s)
} else {
g.write(s)
}
g.write(tmp)
g.inside_lambda = false
return return
} }
len := node.exprs.len if is_default_array {
if elem_type.unaliased_sym.kind == .function { g.write('__new_array_with_array_default${noscan}(')
g.write('new_array_from_c_array($len, $len, sizeof(voidptr), _MOV((voidptr[$len]){') } else if is_default_map {
} else if g.is_empty_struct(elem_type) { g.write('__new_array_with_map_default${noscan}(')
g.write('new_array_from_c_array${noscan}($len, $len, sizeof(voidptr), _MOV(($elem_styp[$len]){')
} else { } else {
g.write('new_array_from_c_array${noscan}($len, $len, sizeof($elem_styp), _MOV(($elem_styp[$len]){') g.write('__new_array_with_default${noscan}(')
} }
if len > 8 { if node.has_len {
g.writeln('') g.expr(node.len_expr)
g.write('\t\t') g.write(', ')
} else {
g.write('0, ')
} }
for i, expr in node.exprs { if node.has_cap {
if node.expr_types[i] == ast.string_type && expr !is ast.StringLiteral g.expr(node.cap_expr)
&& expr !is ast.StringInterLiteral { g.write(', ')
g.write('string_clone(') } else {
g.expr(expr) g.write('0, ')
g.write(')') }
} else { if elem_type.unaliased_sym.kind == .function || g.is_empty_struct(elem_type) {
g.expr_with_cast(expr, node.expr_types[i], node.elem_type) g.write('sizeof(voidptr), ')
} } else {
if i != len - 1 { g.write('sizeof($elem_styp), ')
if i > 0 && i & 7 == 0 { // i > 0 && i % 8 == 0 }
g.writeln(',') if is_default_array || is_default_map {
g.write('\t\t') g.write('($elem_styp[]){')
} else { g.expr(node.default_expr)
g.write(', ') g.write('}[0])')
} } else if node.has_default {
} g.write('&($elem_styp[]){')
g.expr_with_cast(node.default_expr, node.default_type, node.elem_type)
g.write('})')
} else if node.has_len && node.elem_type == ast.string_type {
g.write('&($elem_styp[]){')
g.write('_SLIT("")')
g.write('})')
} else if node.has_len && elem_type.unaliased_sym.kind in [.array, .map] {
g.write('(voidptr)&($elem_styp[]){')
g.write(g.type_default(node.elem_type))
g.write('}[0])')
} else {
g.write('0)')
} }
g.write('}))')
if g.is_shared { if g.is_shared {
g.write('}, sizeof($shared_styp))') g.write('}, sizeof($shared_styp))')
} else if is_amp { } else if is_amp {