cgen: add map string generation
parent
5c3742fbd2
commit
b288ecb795
|
@ -135,6 +135,16 @@ fn (d mut DenseArray) push(kv KeyValue) u32 {
|
|||
return push_index
|
||||
}
|
||||
|
||||
// Private function. Used to implement array[] operator
|
||||
fn (d DenseArray) get(i int) voidptr {
|
||||
$if !no_bounds_checking? {
|
||||
if i < 0 || i >= d.size {
|
||||
panic('DenseArray.get: index out of range (i == $i, d.len == $d.size)')
|
||||
}
|
||||
}
|
||||
return byteptr(d.data) + i * sizeof(KeyValue)
|
||||
}
|
||||
|
||||
// Move all zeros to the end of the array
|
||||
// and resize array
|
||||
fn (d mut DenseArray) zeros_to_end() {
|
||||
|
|
|
@ -2284,7 +2284,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
|||
g.write('%.*s')
|
||||
} else if node.expr_types[i] in [table.f32_type, table.f64_type] {
|
||||
g.write('%g')
|
||||
} else if sym.kind == .struct_ && !sym.has_method('str') {
|
||||
} else if sym.kind in [.struct_, .map] && !sym.has_method('str') {
|
||||
g.write('%.*s')
|
||||
} else if node.expr_types[i] == table.i16_type {
|
||||
g.write('%"PRId16"')
|
||||
|
@ -2364,6 +2364,17 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
|||
g.write('${str_fn_name}(')
|
||||
g.expr(expr)
|
||||
g.write(').str')
|
||||
} else if sym.kind == .map && !sym.has_method('str') {
|
||||
styp := g.typ(node.expr_types[i])
|
||||
str_fn_name := styp_to_str_fn_name(styp)
|
||||
g.gen_str_for_type(sym, styp, str_fn_name)
|
||||
g.write('${str_fn_name}(')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
g.write('.len, ')
|
||||
g.write('${str_fn_name}(')
|
||||
g.expr(expr)
|
||||
g.write(').str')
|
||||
} else if sym.kind == .struct_ && !sym.has_method('str') {
|
||||
styp := g.typ(node.expr_types[i])
|
||||
str_fn_name := styp_to_str_fn_name(styp)
|
||||
|
@ -2845,6 +2856,7 @@ fn (mut g Gen) gen_str_for_type(sym table.TypeSymbol, styp string, str_fn_name s
|
|||
table.Array { g.gen_str_for_array(it, styp, str_fn_name) }
|
||||
table.Enum { g.gen_str_for_enum(it, styp, str_fn_name) }
|
||||
table.Struct { g.gen_str_for_struct(it, styp, str_fn_name) }
|
||||
table.Map { g.gen_str_for_map(it, styp, str_fn_name) }
|
||||
else { verror("could not generate string method $str_fn_name for type \'${styp}\'") }
|
||||
}
|
||||
}
|
||||
|
@ -2899,7 +2911,7 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
|
|||
mut fnames2strfunc := map[string]string
|
||||
for i, field in info.fields {
|
||||
sym := g.table.get_type_symbol(field.typ)
|
||||
if sym.kind in [.struct_, .array, .array_fixed, .enum_] {
|
||||
if sym.kind in [.struct_, .array, .array_fixed, .map, .enum_] {
|
||||
field_styp := g.typ(field.typ)
|
||||
field_fn_name := styp_to_str_fn_name( field_styp )
|
||||
fnames2strfunc[ field_styp ] = field_fn_name
|
||||
|
@ -2990,9 +3002,51 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
|
|||
g.auto_str_funcs.writeln('}')
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string) {
|
||||
key_sym := g.table.get_type_symbol(info.key_type)
|
||||
key_styp := g.typ(info.key_type)
|
||||
if key_sym.kind == .struct_ && !key_sym.has_method('str') {
|
||||
g.gen_str_for_type(key_sym, key_styp, styp_to_str_fn_name(key_styp))
|
||||
}
|
||||
val_sym := g.table.get_type_symbol(info.value_type)
|
||||
val_styp := g.typ(info.value_type)
|
||||
if val_sym.kind == .struct_ && !val_sym.has_method('str') {
|
||||
g.gen_str_for_type(val_sym, val_styp, styp_to_str_fn_name(val_styp))
|
||||
}
|
||||
zero := g.type_default(info.value_type)
|
||||
g.definitions.writeln('string ${str_fn_name}($styp m); // auto')
|
||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp m) { /* gen_str_for_map */')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(m.key_values.size*10);')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos3("$styp"));')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos3("{"));')
|
||||
g.auto_str_funcs.writeln('\tfor (unsigned int i = 0; i < m.key_values.size; i++) {')
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, (*(string*)DenseArray_get(m.key_values, i)));')
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, tos3(": "));')
|
||||
g.auto_str_funcs.write('\t$val_styp it = (*($val_styp*)map_get3(')
|
||||
g.auto_str_funcs.write('m, (*(string*)DenseArray_get(m.key_values, i))')
|
||||
g.auto_str_funcs.write(', ')
|
||||
g.auto_str_funcs.writeln(' &($val_styp[]) { $zero }));')
|
||||
if val_sym.kind == .string {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, it);')
|
||||
} else if val_sym.kind == .struct_ && !val_sym.has_method('str') {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${val_styp}_str(it,0));')
|
||||
} else if val_sym.kind in [.f32, .f64] {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, _STR("%g", it));')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write(&sb, ${val_styp}_str(it));')
|
||||
}
|
||||
g.auto_str_funcs.writeln('\t\tif (i != m.key_values.size-1) {')
|
||||
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write(&sb, tos3(", "));')
|
||||
g.auto_str_funcs.writeln('\t\t}')
|
||||
g.auto_str_funcs.writeln('\t}')
|
||||
g.auto_str_funcs.writeln('\tstrings__Builder_write(&sb, tos3("}"));')
|
||||
g.auto_str_funcs.writeln('\treturn strings__Builder_str(&sb);')
|
||||
g.auto_str_funcs.writeln('}')
|
||||
}
|
||||
|
||||
fn (g Gen) type_to_fmt(typ table.Type) string {
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
if sym.kind in [.struct_, .array, .array_fixed] {
|
||||
if sym.kind in [.struct_, .array, .array_fixed, .map] {
|
||||
return '%.*s'
|
||||
} else if typ == table.string_type {
|
||||
return "\'%.*s\'"
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
struct Test {
|
||||
a bool
|
||||
b int
|
||||
y string
|
||||
}
|
||||
|
||||
fn test_interpolation_map_to_string() {
|
||||
a := map[string]string
|
||||
a['1'] = 'one'
|
||||
a['2'] = 'two'
|
||||
a['3'] = 'three'
|
||||
assert '$a' == 'map_string_string{1: one, 2: two, 3: three}'
|
||||
b := map[string]int
|
||||
b['1'] = 1
|
||||
b['2'] = 2
|
||||
b['3'] = 3
|
||||
assert '$b' == 'map_string_int{1: 1, 2: 2, 3: 3}'
|
||||
c := map[string]bool
|
||||
c['1'] = true
|
||||
c['2'] = false
|
||||
assert '$c' == 'map_string_bool{1: true, 2: false}'
|
||||
d := map[string]Test
|
||||
d['1'] = Test{true, 0, 'abc'}
|
||||
d['2'] = Test{true, 1, 'def'}
|
||||
d['3'] = Test{false, 2, 'ghi'}
|
||||
assert '$d'.replace('\n', '').replace('\'', '"') == 'map_string_Test{1: Test { a: true b: 0 y: "abc"}, 2: Test { a: true b: 1 y: "def"}, 3: Test { a: false b: 2 y: "ghi"}}'
|
||||
}
|
Loading…
Reference in New Issue