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