cgen: further fixes to and array/map of fns (#5916)

pull/5926/head
Ruofan XU 2020-07-22 08:30:44 +08:00 committed by GitHub
parent c3a2e9b5c4
commit a370dd2867
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 50 deletions

View File

@ -912,6 +912,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
// `for num in nums {`
g.writeln('// FOR IN array')
styp := g.typ(it.val_type)
val_sym := g.table.get_type_symbol(it.val_type)
cond_type_is_ptr := it.cond_type.is_ptr()
atmp := g.new_tmp_var()
atmp_type := if cond_type_is_ptr { 'array *' } else { 'array' }
@ -922,7 +923,13 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
op_field := if cond_type_is_ptr { '->' } else { '.' }
g.writeln('for (int $i = 0; $i < $atmp${op_field}len; ++$i) {')
if it.val_var != '_' {
g.writeln('\t$styp ${c_name(it.val_var)} = (($styp*)$atmp${op_field}data)[$i];')
if val_sym.kind == .function {
g.write('\t')
g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(it.val_var))
g.writeln(' = ((voidptr*)$atmp${op_field}data)[$i];')
} else {
g.write('\t$styp ${c_name(it.val_var)} = (($styp*)$atmp${op_field}data)[$i];')
}
}
g.stmts(it.stmts)
g.writeln('}')
@ -931,6 +938,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
g.writeln('// FOR IN map')
key_styp := g.typ(it.key_type)
val_styp := g.typ(it.val_type)
val_sym := g.table.get_type_symbol(it.val_type)
keys_tmp := 'keys_' + g.new_tmp_var()
idx := g.new_tmp_var()
key := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
@ -949,8 +957,13 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
g.writeln('\t$key_styp $key = /*kkkk*/ (($key_styp*)${keys_tmp}.data)[$idx];')
}
if it.val_var != '_' {
g.write('\t$val_styp ${c_name(it.val_var)} = /*vvv*/ (*($val_styp*)map_get($atmp')
g.writeln(', $key, &($val_styp[]){ $zero }));')
if val_sym.kind == .function {
g.write('\t')
g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(it.val_var))
g.writeln(' = (*(voidptr*)map_get($atmp, $key, &(voidptr[]){ $zero }));')
} else {
g.writeln('\t$val_styp ${c_name(it.val_var)} = (*($val_styp*)map_get($atmp, $key, &($val_styp[]){ $zero }));')
}
}
g.stmts(it.stmts)
g.writeln('}')
@ -1142,6 +1155,20 @@ fn (mut g Gen) gen_assert_single_expr(e ast.Expr, t table.Type) {
g.write(' /* typeof: ' + typeof(e) + ' type: ' + t.str() + ' */ ')
}
fn (g &Gen) write_fn_ptr_decl(func &table.FnType, ptr_name string) {
ret_styp := g.typ(func.func.return_type)
g.write('$ret_styp (*$ptr_name) (')
arg_len := func.func.args.len
for i, arg in func.func.args {
arg_typ := g.table.get_type_symbol(arg.typ)
g.write('$arg_typ.str() $arg.name')
if i < arg_len - 1 {
g.write(', ')
}
}
g.write(')')
}
fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
if assign_stmt.is_static {
g.write('static ')
@ -1198,23 +1225,13 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
for i, left in assign_stmt.left {
match left {
ast.Ident {
var_type := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(var_type)
left_typ := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(left_typ)
if left_sym.kind == .function {
func := left_sym.info as table.FnType
ret_styp := g.typ(func.func.return_type)
g.write('$ret_styp (*_var_$left.pos.pos) (')
arg_len := func.func.args.len
for j, arg in func.func.args {
arg_type := g.table.get_type_symbol(arg.typ)
g.write('$arg_type.str() $arg.name')
if j < arg_len - 1 {
g.write(', ')
}
}
g.writeln(') = $left.name;')
g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos')
g.writeln(' = $left.name;')
} else {
styp := g.typ(var_type)
styp := g.typ(left_typ)
g.writeln('$styp _var_$left.pos.pos = $left.name;')
}
}
@ -1222,24 +1239,14 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
sym := g.table.get_type_symbol(left.left_type)
if sym.kind == .array {
info := sym.info as table.Array
styp := g.typ(info.elem_type)
elem_typ := g.table.get_type_symbol(info.elem_type)
if elem_typ.kind == .function {
var_type := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(var_type)
func := left_sym.info as table.FnType
ret_styp := g.typ(func.func.return_type)
g.write('$ret_styp (*_var_$left.pos.pos) (')
arg_len := func.func.args.len
for j, arg in func.func.args {
arg_type := g.table.get_type_symbol(arg.typ)
g.write('$arg_type.str() $arg.name')
if j < arg_len - 1 {
g.write(', ')
}
}
g.write(') = *(voidptr*)array_get(')
left_typ := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(left_typ)
g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos')
g.write(' = *(voidptr*)array_get(')
} else {
styp := g.typ(info.elem_type)
g.write('$styp _var_$left.pos.pos = *($styp*)array_get(')
}
if left.left_type.is_ptr() {
@ -1253,22 +1260,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
info := sym.info as table.Map
styp := g.typ(info.value_type)
zero := g.type_default(info.value_type)
value_typ := g.table.get_type_symbol(info.value_type)
if value_typ.kind == .function {
var_type := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(var_type)
func := left_sym.info as table.FnType
ret_styp := g.typ(func.func.return_type)
g.write('$ret_styp (*_var_$left.pos.pos) (')
arg_len := func.func.args.len
for j, arg in func.func.args {
arg_type := g.table.get_type_symbol(arg.typ)
g.write('$arg_type.str() $arg.name')
if j < arg_len - 1 {
g.write(', ')
}
}
g.write(') = *(voidptr*)map_get(')
val_typ := g.table.get_type_symbol(info.value_type)
if val_typ.kind == .function {
left_type := assign_stmt.left_types[i]
left_sym := g.table.get_type_symbol(left_type)
g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos')
g.write(' = *(voidptr*)map_get(')
} else {
g.write('$styp _var_$left.pos.pos = *($styp*)map_get(')
}
@ -1278,7 +1275,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.expr(left.left)
g.write(', ')
g.expr(left.index)
if value_typ.kind == .function {
if val_typ.kind == .function {
g.writeln(', &(voidptr[]){ $zero });')
} else {
g.writeln(', &($styp[]){ $zero });')

View File

@ -24,6 +24,9 @@ fn test_array_with_fns() {
b[0] = a[0]
f4 := b[0]
assert f4('bbbbbb') == 26
for func in b {
assert func('ccccccc') == 27
}
}
fn test_map_with_fns() {
@ -42,4 +45,7 @@ fn test_map_with_fns() {
b['one'] = a['one']
f4 := b['one']
assert f4('bbbbbb') == 26
for _, func in b {
assert func('ccccccc') == 27
}
}