cgen: add map string generation
parent
5c3742fbd2
commit
b288ecb795
|
@ -135,6 +135,16 @@ fn (d mut DenseArray) push(kv KeyValue) u32 {
|
||||||
return push_index
|
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
|
// Move all zeros to the end of the array
|
||||||
// and resize array
|
// and resize array
|
||||||
fn (d mut DenseArray) zeros_to_end() {
|
fn (d mut DenseArray) zeros_to_end() {
|
||||||
|
|
|
@ -2284,7 +2284,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
g.write('%.*s')
|
g.write('%.*s')
|
||||||
} else if node.expr_types[i] in [table.f32_type, table.f64_type] {
|
} else if node.expr_types[i] in [table.f32_type, table.f64_type] {
|
||||||
g.write('%g')
|
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')
|
g.write('%.*s')
|
||||||
} else if node.expr_types[i] == table.i16_type {
|
} else if node.expr_types[i] == table.i16_type {
|
||||||
g.write('%"PRId16"')
|
g.write('%"PRId16"')
|
||||||
|
@ -2364,6 +2364,17 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
g.write('${str_fn_name}(')
|
g.write('${str_fn_name}(')
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(').str')
|
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') {
|
} else if sym.kind == .struct_ && !sym.has_method('str') {
|
||||||
styp := g.typ(node.expr_types[i])
|
styp := g.typ(node.expr_types[i])
|
||||||
str_fn_name := styp_to_str_fn_name(styp)
|
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.Array { g.gen_str_for_array(it, styp, str_fn_name) }
|
||||||
table.Enum { g.gen_str_for_enum(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.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}\'") }
|
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
|
mut fnames2strfunc := map[string]string
|
||||||
for i, field in info.fields {
|
for i, field in info.fields {
|
||||||
sym := g.table.get_type_symbol(field.typ)
|
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_styp := g.typ(field.typ)
|
||||||
field_fn_name := styp_to_str_fn_name( field_styp )
|
field_fn_name := styp_to_str_fn_name( field_styp )
|
||||||
fnames2strfunc[ field_styp ] = field_fn_name
|
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('}')
|
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 {
|
fn (g Gen) type_to_fmt(typ table.Type) string {
|
||||||
sym := g.table.get_type_symbol(typ)
|
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'
|
return '%.*s'
|
||||||
} else if typ == table.string_type {
|
} else if typ == table.string_type {
|
||||||
return "\'%.*s\'"
|
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