Skip to content

Commit

Permalink
all: string interpolation code cleaning (#10204)
Browse files Browse the repository at this point in the history
  • Loading branch information
penguindark committed May 26, 2021
1 parent 5e26273 commit 2dd1d3f
Show file tree
Hide file tree
Showing 8 changed files with 17 additions and 491 deletions.
20 changes: 14 additions & 6 deletions vlib/builtin/string_interpolation.v
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,11 @@ pub const (
si_g64_code = '0xfe0f'
)

// replace _STR("\'%.*s\\000\'", 2, in_str)
[inline]
pub fn str_intp_sq(in_str string) string {
return 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("\'"), $si_s_code, {.d_s = $in_str}},{_SLIT("\'"), 0, {.d_c = 0 }}}))'
}

// replace _STR("\`%.*s\\000\`", 2, in_str)
[inline]
pub fn str_intp_rune(in_str string) string {
return 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("\`"), $si_s_code, {.d_s = $in_str}},{_SLIT("\`"), 0, {.d_c = 0 }}}))'
Expand All @@ -660,15 +658,25 @@ pub fn str_intp_g64(in_str string) string {
}

// replace %% with the in_str
[manualfree]
pub fn str_intp_sub(base_str string, in_str string) string {
index := base_str.index('%%') or {
eprintln('No strin interpolation %% parameteres')
exit(1)
}
// return base_str[..index] + in_str + base_str[index+2..]
if index + 2 < base_str.len {
return 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("${base_str[..index]}"), $si_s_code, {.d_s = $in_str }},{_SLIT("${base_str[
index + 2..]}"), 0, {.d_c = 0}}}))'

unsafe {
st_str := base_str[..index]
if index + 2 < base_str.len {
en_str := base_str[index + 2..]
res_str := 'str_intp(2, _MOV((StrIntpData[]){{_SLIT("$st_str"), $si_s_code, {.d_s = $in_str }},{_SLIT("$en_str"), 0, {.d_c = 0}}}))'
st_str.free()
en_str.free()
return res_str
}
res2_str := 'str_intp(1, _MOV((StrIntpData[]){{_SLIT("$st_str"), $si_s_code, {.d_s = $in_str }}}))'
st_str.free()
return res2_str
}
return 'str_intp(1, _MOV((StrIntpData[]){{_SLIT("${base_str[..index]}"), $si_s_code, {.d_s = $in_str }}}))'
}
9 changes: 0 additions & 9 deletions vlib/v/gen/c/auto_str_array.v
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,11 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string
} else {
g.auto_str_funcs.writeln('\t\tstring x = ${str_intp_g64('it')};')
}

// g.auto_str_funcs.writeln('\t\tstring x = _STR("%g", 1, it);')
} else if sym.kind == .rune {
// Rune are managed at this level as strings
g.auto_str_funcs.writeln('\t\tstring x = str_intp(2, _MOV((StrIntpData[]){{_SLIT("\`"), $si_s_code, {.d_s = ${elem_str_fn_name}(it) }}, {_SLIT("\`"), 0, {.d_c = 0 }}}));\n')

// g.auto_str_funcs.writeln('\t\tstring x = _STR("`%.*s\\000`", 2, ${elem_str_fn_name}(it));')
} else if sym.kind == .string {
g.auto_str_funcs.writeln('\t\tstring x = str_intp(2, _MOV((StrIntpData[]){{_SLIT("\'"), $si_s_code, {.d_s = it }}, {_SLIT("\'"), 0, {.d_c = 0 }}}));\n')

// g.auto_str_funcs.writeln('\t\tstring x = _STR("\'%.*s\\000\'", 2, it);')
} else {
// There is a custom .str() method, so use it.
// NB: we need to take account of whether the user has defined
Expand Down Expand Up @@ -146,14 +140,11 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${str_intp_g64('a[i]')} );')
}
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("%g", 1, a[i]));')
} else if sym.kind == .string {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${str_intp_sq('a[i]')});')
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("\'%.*s\\000\'", 2, a[i]));')
} else if sym.kind == .rune {
tmp_str := str_intp_rune('${elem_str_fn_name}( $deref a[i])')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, $tmp_str);')
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("`%.*s\\000`", 2, ${elem_str_fn_name}(a[i])));')
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( $deref a[i]));')
}
Expand Down
5 changes: 0 additions & 5 deletions vlib/v/gen/c/auto_str_map.v
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) {
}
if key_sym.kind == .string {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${str_intp_sq('key')});')
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("\'%.*s\\000\'", 2, key));')
} else if key_sym.kind == .rune {
tmp_str := str_intp_rune('${key_str_fn_name}(key)')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, $tmp_str);')
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("`%.*s\\000`", 2, ${key_str_fn_name}(key)));')
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${key_str_fn_name}(key));')
}
Expand All @@ -60,7 +58,6 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) {
} else if val_sym.kind == .string {
tmp_str := str_intp_sq('*($val_styp*)DenseArray_value(&m.key_values, i)')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, $tmp_str);')
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("\'%.*s\\000\'", 2, *($val_styp*)DenseArray_value(&m.key_values, i)));')
} else if should_use_indent_func(val_sym.kind) && !val_sym.has_method('str') {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, indent_${elem_str_fn_name}(*($val_styp*)DenseArray_value(&m.key_values, i), indent_count));')
} else if val_sym.kind in [.f32, .f64] {
Expand All @@ -70,11 +67,9 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) {
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${str_intp_g64(tmp_val)});')
}
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("%g", 1, *($val_styp*)DenseArray_value(&m.key_values, i)));')
} else if val_sym.kind == .rune {
tmp_str := str_intp_rune('${elem_str_fn_name}(*($val_styp*)DenseArray_value(&m.key_values, i))')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, $tmp_str);')
// g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _STR("`%.*s\\000`", 2, ${elem_str_fn_name}(*($val_styp*)DenseArray_value(&m.key_values, i))));')
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}(*($val_styp*)DenseArray_value(&m.key_values, i)));')
}
Expand Down
37 changes: 0 additions & 37 deletions vlib/v/gen/c/auto_str_methods.v
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string)
if sym.kind == .string {
tmp_res := '${parent_str_fn_name}(*($sym.cname*)it.data)'
g.auto_str_funcs.writeln('\t\tres = ${str_intp_sq(tmp_res)};')
// g.auto_str_funcs.writeln('\t\tres = _STR("\'%.*s\\000\'", 2, ${parent_str_fn_name}(*($sym.cname*)it.data));')
} else if should_use_indent_func(sym.kind) && !sym_has_str_method {
g.auto_str_funcs.writeln('\t\tres = indent_${parent_str_fn_name}(*($sym.cname*)it.data, indent_count);')
} else {
Expand All @@ -211,12 +210,9 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string)

tmp_str := str_intp_sub('error: %%', 'IError_str(it.err)')
g.auto_str_funcs.writeln('\t\tres = $tmp_str;')
// g.auto_str_funcs.writeln('\t\tres = _STR("error: %.*s\\000", 2, IError_str(it.err));')

g.auto_str_funcs.writeln('\t}')

g.auto_str_funcs.writeln('\treturn ${str_intp_sub('Option(%%)', 'res')};')
// g.auto_str_funcs.writeln('\treturn _STR("Option(%.*s\\000)", 2, res);')
g.auto_str_funcs.writeln('}')
}

Expand All @@ -243,8 +239,6 @@ fn (mut g Gen) gen_str_for_alias(info ast.Alias, styp string, str_fn_name string
{_SLIT(")"), 0, {.d_c = 0 }}
}));\n')

// g.auto_str_funcs.writeln('\treturn _STR("%.*s\\000${clean_type_v_type_name}(%.*s\\000)", 3, indents, ${parent_str_fn_name}(it));')

g.auto_str_funcs.writeln('}')
}

Expand Down Expand Up @@ -284,11 +278,9 @@ fn (mut g Gen) gen_str_for_multi_return(info ast.MultiReturn, styp string, str_f
tmp_val := str_intp_g64('a.arg$i')
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, $tmp_val);')
}
// g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _STR("%g", 1, a.arg$i));')
} else if sym.kind == .string {
tmp_str := str_intp_sq('a.arg$i')
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, $tmp_str);')
// g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _STR("\'%.*s\\000\'", 2, a.arg$i));')
} else if sym.kind == .function {
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, ${arg_str_fn_name}());')
} else {
Expand Down Expand Up @@ -402,21 +394,6 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam
g.auto_str_funcs.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)')
g.auto_str_funcs.write_string(' return $res;\n')
}

//------------------------------------------
/*
deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '*' }
value_fmt := if typ == ast.string_type { "'%.*s\\000'" } else { '%.*s\\000' }
g.auto_str_funcs.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)')
g.auto_str_funcs.write_string(' return _STR("${clean_interface_v_type_name}($value_fmt)", 2, ')
g.auto_str_funcs.write_string('${func_name}(${deref}($subtype.cname*)x._$subtype.cname')
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
g.auto_str_funcs.write_string(', indent_count')
}
g.auto_str_funcs.writeln('));\n')
*/
//------------------------------------------
}
g.auto_str_funcs.writeln('\treturn _SLIT("unknown interface value");')
g.auto_str_funcs.writeln('}')
Expand Down Expand Up @@ -482,20 +459,6 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_
}))'
g.auto_str_funcs.write_string('\t\tcase $typ: return $res;')
}

//------------------------------------------
/*
mut value_fmt := '%.*s\\000'
if typ == ast.string_type {
value_fmt = "'$value_fmt'"
}
g.auto_str_funcs.write_string('\t\tcase $typ: return _STR("${clean_sum_type_v_type_name}($value_fmt)", 2, ${func_name}(${deref}($typ_str*)x._$sym.cname')
if should_use_indent_func(sym.kind) && !sym_has_str_method {
g.auto_str_funcs.write_string(', indent_count')
}
g.auto_str_funcs.writeln('));')
*/
//------------------------------------------
}
g.auto_str_funcs.writeln('\t\tdefault: return _SLIT("unknown sum type value");')
g.auto_str_funcs.writeln('\t}')
Expand Down
173 changes: 0 additions & 173 deletions vlib/v/gen/c/auto_str_struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -212,176 +212,3 @@ fn struct_auto_str_func1(sym &ast.TypeSymbol, field_type ast.Type, fn_name strin
return method_str
}
}

//=============================================================================
// OLD CODE
//=============================================================================
/*
fn (g &Gen) type_to_fmt(typ ast.Type) string {
if typ == ast.byte_type_idx {
return '%hhx\\000'
}
if typ == ast.char_type_idx {
return '%c\\000'
}
if typ == ast.voidptr_type_idx || typ in ast.byteptr_types {
return '%p\\000'
}
if typ in ast.charptr_types {
return '%C\\000' // a C string
}
sym := g.table.get_type_symbol(typ)
if typ.is_ptr() && (typ.is_int_valptr() || typ.is_float_valptr()) {
return '%.*s\\000'
} else if sym.kind in [.struct_, .array, .array_fixed, .map, .bool, .enum_, .interface_,
.sum_type, .function, .alias] {
return '%.*s\\000'
} else if sym.kind == .string {
return "'%.*s\\000'"
} else if sym.kind in [.f32, .f64] {
return '%g\\000' // g removes trailing zeros unlike %f
} else if sym.kind == .int {
return '%d\\000'
} else if sym.kind == .u32 {
return '%u\\000'
} else if sym.kind == .u64 {
return '%llu\\000'
} else if sym.kind == .i64 {
return '%lld\\000'
}
return '%d\\000'
}
fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name string) {
//g.gen_str_for_struct1(info, styp, str_fn_name)
// TODO: short it if possible
// generates all definitions of substructs
mut fnames2strfunc := map{
'': ''
}
for field in info.fields {
sym := g.table.get_type_symbol(field.typ)
if !sym.has_method('str') {
mut typ := field.typ
if typ.is_ptr() {
typ = typ.deref()
}
field_styp := g.typ(typ)
field_fn_name := g.gen_str_for_type(field.typ)
fnames2strfunc[field_styp] = field_fn_name
}
}
// _str() functions should have a single argument, the indenting ones take 2:
g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto')
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0);}')
g.type_definitions.writeln('static string indent_${str_fn_name}($styp it, int indent_count); // auto')
g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp it, int indent_count) {')
mut clean_struct_v_type_name := styp.replace('__', '.')
if clean_struct_v_type_name.contains('_T_') {
// TODO: this is a bit hacky. styp shouldn't be even parsed with _T_
// use something different than g.typ for styp
clean_struct_v_type_name =
clean_struct_v_type_name.replace('Array_', '[]').replace('_T_', '<').replace('_', ', ') +
'>'
}
clean_struct_v_type_name = util.strip_main_name(clean_struct_v_type_name)
// generate ident / indent length = 4 spaces
g.auto_str_funcs.writeln('\tstring indents = _SLIT("");')
g.auto_str_funcs.writeln('\tfor (int i = 0; i < indent_count; ++i) {')
g.auto_str_funcs.writeln('\t\tindents = string__plus(indents, _SLIT(" "));')
g.auto_str_funcs.writeln('\t}')
if info.fields.len == 0 {
g.auto_str_funcs.write_string('\treturn _SLIT("$clean_struct_v_type_name{}");')
} else {
g.auto_str_funcs.write_string('\treturn _STR("$clean_struct_v_type_name{\\n"')
for field in info.fields {
mut fmt := if field.typ.is_ptr() { '&' } else { '' }
fmt += g.type_to_fmt(field.typ)
g.auto_str_funcs.writeln('\t\t"%.*s\\000 $field.name: $fmt\\n"')
}
g.auto_str_funcs.write_string('\t\t"%.*s\\000}", ${2 * (info.fields.len + 1)}')
if info.fields.len > 0 {
g.auto_str_funcs.write_string(',\n\t\t')
for i, field in info.fields {
sym := g.table.get_type_symbol(field.typ)
has_custom_str := sym.has_method('str')
mut field_styp := g.typ(field.typ).replace('*', '')
field_styp_fn_name := if has_custom_str {
'${field_styp}_str'
} else {
fnames2strfunc[field_styp]
}
g.auto_str_funcs.write_string('indents, ')
mut func := struct_auto_str_func(sym, field.typ, field_styp_fn_name, field.name)
// reference types can be "nil"
if field.typ.is_ptr() && !(field.typ in ast.charptr_types
|| field.typ in ast.byteptr_types
|| field.typ == ast.voidptr_type_idx) {
g.auto_str_funcs.write_string('isnil(it.${c_name(field.name)})')
g.auto_str_funcs.write_string(' ? _SLIT("nil") : ')
// struct, floats and ints have a special case through the _str function
if sym.kind != .struct_ && !field.typ.is_int_valptr()
&& !field.typ.is_float_valptr() {
g.auto_str_funcs.write_string('*')
}
}
// handle circular ref type of struct to the struct itself
if styp == field_styp {
g.auto_str_funcs.write_string('_SLIT("<circular>")')
} else {
g.auto_str_funcs.write_string(func)
}
if i < info.fields.len - 1 {
g.auto_str_funcs.write_string(',\n\t\t')
}
}
}
g.auto_str_funcs.writeln(',')
g.auto_str_funcs.writeln('\t\tindents);')
}
g.auto_str_funcs.writeln('}')
}
fn struct_auto_str_func(sym &ast.TypeSymbol, field_type ast.Type, fn_name string, field_name string) string {
has_custom_str, expects_ptr, _ := sym.str_method_info()
if sym.kind == .enum_ {
return '${fn_name}(it.${c_name(field_name)})'
} else if should_use_indent_func(sym.kind) {
mut obj := 'it.${c_name(field_name)}'
if field_type.is_ptr() && !expects_ptr {
obj = '*$obj'
}
if has_custom_str {
return '${fn_name}($obj)'
}
return 'indent_${fn_name}($obj, indent_count + 1)'
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] {
if has_custom_str {
return '${fn_name}(it.${c_name(field_name)})'
}
return 'indent_${fn_name}(it.${c_name(field_name)}, indent_count + 1)'
} else if sym.kind == .function {
return '${fn_name}()'
} else {
mut method_str := 'it.${c_name(field_name)}'
if sym.kind == .bool {
method_str += ' ? _SLIT("true") : _SLIT("false")'
} else if (field_type.is_int_valptr() || field_type.is_float_valptr())
&& field_type.is_ptr() && !expects_ptr {
// ptr int can be "nil", so this needs to be castet to a string
fmt := if sym.kind in [.f32, .f64] {
'%g\\000'
} else if sym.kind == .u64 {
'%lld\\000'
} else {
'%d\\000'
}
method_str = '_STR("$fmt", 2, *$method_str)'
}
return method_str
}
}
*/
4 changes: 1 addition & 3 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,6 @@ pub fn (mut g Gen) init() {
} else {
g.cheaders.writeln(c_headers)
}
// g.definitions.writeln('string _STR(const char*, int, ...);')
// g.definitions.writeln('string _STR_TMP(const char*, ...);')
}
if g.pref.os == .ios {
g.cheaders.writeln('#define __TARGET_IOS__ 1')
Expand Down Expand Up @@ -2196,7 +2194,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
// here, not in call_expr().
// `pos := s.index('x') or { return }`
// ==========>
// Option_int _t190 = string_index(s, _STR("x"));
// Option_int _t190 = string_index(s, _STR("x")); // _STR() no more used!!
// if (_t190.state != 2) {
// Error err = _t190.err;
// return;
Expand Down
Loading

0 comments on commit 2dd1d3f

Please sign in to comment.